Use range for syntax in Frame and FrameView.
[WebKit-https.git] / Source / WebCore / page / Frame.cpp
1 /*
2  * Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
3  *                     1999 Lars Knoll <knoll@kde.org>
4  *                     1999 Antti Koivisto <koivisto@kde.org>
5  *                     2000 Simon Hausmann <hausmann@kde.org>
6  *                     2000 Stefan Schimanski <1Stein@gmx.de>
7  *                     2001 George Staikos <staikos@kde.org>
8  * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
9  * Copyright (C) 2005 Alexey Proskuryakov <ap@nypop.com>
10  * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
11  * Copyright (C) 2008 Eric Seidel <eric@webkit.org>
12  * Copyright (C) 2008 Google Inc.
13  *
14  * This library is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU Library General Public
16  * License as published by the Free Software Foundation; either
17  * version 2 of the License, or (at your option) any later version.
18  *
19  * This library is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22  * Library General Public License for more details.
23  *
24  * You should have received a copy of the GNU Library General Public License
25  * along with this library; see the file COPYING.LIB.  If not, write to
26  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
27  * Boston, MA 02110-1301, USA.
28  */
29
30 #include "config.h"
31 #include "Frame.h"
32
33 #include "AnimationController.h"
34 #include "ApplyStyleCommand.h"
35 #include "BackForwardController.h"
36 #include "CSSComputedStyleDeclaration.h"
37 #include "CSSPropertyNames.h"
38 #include "CachedCSSStyleSheet.h"
39 #include "CachedResourceLoader.h"
40 #include "Chrome.h"
41 #include "ChromeClient.h"
42 #include "DOMWindow.h"
43 #include "DocumentType.h"
44 #include "Editor.h"
45 #include "EditorClient.h"
46 #include "Event.h"
47 #include "EventHandler.h"
48 #include "EventNames.h"
49 #include "FloatQuad.h"
50 #include "FocusController.h"
51 #include "FrameDestructionObserver.h"
52 #include "FrameLoader.h"
53 #include "FrameLoaderClient.h"
54 #include "FrameSelection.h"
55 #include "FrameView.h"
56 #include "GraphicsContext.h"
57 #include "GraphicsLayer.h"
58 #include "HTMLDocument.h"
59 #include "HTMLFormControlElement.h"
60 #include "HTMLFormElement.h"
61 #include "HTMLFrameElementBase.h"
62 #include "HTMLNames.h"
63 #include "HTMLTableCellElement.h"
64 #include "HitTestResult.h"
65 #include "ImageBuffer.h"
66 #include "InspectorInstrumentation.h"
67 #include "JSDOMWindowShell.h"
68 #include "Logging.h"
69 #include "MainFrame.h"
70 #include "MathMLNames.h"
71 #include "MediaFeatureNames.h"
72 #include "Navigator.h"
73 #include "NodeList.h"
74 #include "NodeTraversal.h"
75 #include "Page.h"
76 #include "PageCache.h"
77 #include "PageGroup.h"
78 #include "RegularExpression.h"
79 #include "RenderTableCell.h"
80 #include "RenderText.h"
81 #include "RenderTextControl.h"
82 #include "RenderTheme.h"
83 #include "RenderView.h"
84 #include "RenderWidget.h"
85 #include "RuntimeEnabledFeatures.h"
86 #include "SVGNames.h"
87 #include "ScriptController.h"
88 #include "ScriptSourceCode.h"
89 #include "ScrollingCoordinator.h"
90 #include "Settings.h"
91 #include "StyleProperties.h"
92 #include "TextIterator.h"
93 #include "TextNodeTraversal.h"
94 #include "TextResourceDecoder.h"
95 #include "UserContentURLPattern.h"
96 #include "UserTypingGestureIndicator.h"
97 #include "VisibleUnits.h"
98 #include "WebKitFontFamilyNames.h"
99 #include "XLinkNames.h"
100 #include "XMLNSNames.h"
101 #include "XMLNames.h"
102 #include "htmlediting.h"
103 #include "markup.h"
104 #include "npruntime_impl.h"
105 #include "runtime_root.h"
106 #include <bindings/ScriptValue.h>
107 #include <wtf/PassOwnPtr.h>
108 #include <wtf/RefCountedLeakCounter.h>
109 #include <wtf/StdLibExtras.h>
110
111 #if USE(ACCELERATED_COMPOSITING)
112 #include "RenderLayerCompositor.h"
113 #endif
114
115 #if ENABLE(SVG)
116 #include "SVGDocument.h"
117 #include "SVGDocumentExtensions.h"
118 #endif
119
120 #if USE(TILED_BACKING_STORE)
121 #include "TiledBackingStore.h"
122 #endif
123
124 namespace WebCore {
125
126 using namespace HTMLNames;
127
128 DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, frameCounter, ("Frame"));
129
130 static inline Frame* parentFromOwnerElement(HTMLFrameOwnerElement* ownerElement)
131 {
132     if (!ownerElement)
133         return 0;
134     return ownerElement->document().frame();
135 }
136
137 static inline float parentPageZoomFactor(Frame* frame)
138 {
139     Frame* parent = frame->tree().parent();
140     if (!parent)
141         return 1;
142     return parent->pageZoomFactor();
143 }
144
145 static inline float parentTextZoomFactor(Frame* frame)
146 {
147     Frame* parent = frame->tree().parent();
148     if (!parent)
149         return 1;
150     return parent->textZoomFactor();
151 }
152
153 Frame::Frame(Page& page, HTMLFrameOwnerElement* ownerElement, FrameLoaderClient& frameLoaderClient)
154     : m_mainFrame(ownerElement ? page.mainFrame() : static_cast<MainFrame&>(*this))
155     , m_page(&page)
156     , m_settings(&page.settings())
157     , m_treeNode(this, parentFromOwnerElement(ownerElement))
158     , m_loader(*this, frameLoaderClient)
159     , m_navigationScheduler(this)
160     , m_ownerElement(ownerElement)
161     , m_script(std::make_unique<ScriptController>(*this))
162     , m_editor(Editor::create(*this))
163     , m_selection(adoptPtr(new FrameSelection(this)))
164     , m_eventHandler(adoptPtr(new EventHandler(*this)))
165     , m_animationController(std::make_unique<AnimationController>(*this))
166     , m_pageZoomFactor(parentPageZoomFactor(this))
167     , m_textZoomFactor(parentTextZoomFactor(this))
168 #if ENABLE(ORIENTATION_EVENTS)
169     , m_orientation(0)
170 #endif
171     , m_inViewSourceMode(false)
172     , m_activeDOMObjectsAndAnimationsSuspendedCount(0)
173 {
174     AtomicString::init();
175     HTMLNames::init();
176     QualifiedName::init();
177     MediaFeatureNames::init();
178     SVGNames::init();
179     XLinkNames::init();
180     MathMLNames::init();
181     XMLNSNames::init();
182     XMLNames::init();
183     WebKitFontFamilyNames::init();
184
185     if (!ownerElement) {
186 #if USE(TILED_BACKING_STORE)
187         // Top level frame only for now.
188         setTiledBackingStoreEnabled(settings().tiledBackingStoreEnabled());
189 #endif
190     } else {
191         m_mainFrame.selfOnlyRef();
192         page.incrementSubframeCount();
193         ownerElement->setContentFrame(this);
194     }
195
196 #ifndef NDEBUG
197     frameCounter.increment();
198 #endif
199
200     // Pause future ActiveDOMObjects if this frame is being created while the page is in a paused state.
201     Frame* parent = parentFromOwnerElement(ownerElement);
202     if (parent && parent->activeDOMObjectsAndAnimationsSuspended())
203         suspendActiveDOMObjectsAndAnimations();
204 }
205
206 PassRefPtr<Frame> Frame::create(Page* page, HTMLFrameOwnerElement* ownerElement, FrameLoaderClient* client)
207 {
208     ASSERT(page);
209     ASSERT(client);
210     return adoptRef(new Frame(*page, ownerElement, *client));
211 }
212
213 Frame::~Frame()
214 {
215     setView(0);
216     loader().cancelAndClear();
217
218     // FIXME: We should not be doing all this work inside the destructor
219
220 #ifndef NDEBUG
221     frameCounter.decrement();
222 #endif
223
224     disconnectOwnerElement();
225
226     for (auto& observer : m_destructionObservers)
227         observer->frameDestroyed();
228
229     if (!isMainFrame())
230         m_mainFrame.selfOnlyDeref();
231 }
232
233 void Frame::addDestructionObserver(FrameDestructionObserver* observer)
234 {
235     m_destructionObservers.add(observer);
236 }
237
238 void Frame::removeDestructionObserver(FrameDestructionObserver* observer)
239 {
240     m_destructionObservers.remove(observer);
241 }
242
243 void Frame::setView(PassRefPtr<FrameView> view)
244 {
245     // We the custom scroll bars as early as possible to prevent m_doc->detach()
246     // from messing with the view such that its scroll bars won't be torn down.
247     // FIXME: We should revisit this.
248     if (m_view)
249         m_view->prepareForDetach();
250
251     // Prepare for destruction now, so any unload event handlers get run and the DOMWindow is
252     // notified. If we wait until the view is destroyed, then things won't be hooked up enough for
253     // these calls to work.
254     if (!view && m_doc && m_doc->attached() && !m_doc->inPageCache())
255         m_doc->prepareForDestruction();
256     
257     if (m_view)
258         m_view->unscheduleRelayout();
259     
260     eventHandler().clear();
261
262     m_view = view;
263
264     // Only one form submission is allowed per view of a part.
265     // Since this part may be getting reused as a result of being
266     // pulled from the back/forward cache, reset this flag.
267     loader().resetMultipleFormSubmissionProtection();
268     
269 #if USE(TILED_BACKING_STORE)
270     if (m_view && tiledBackingStore())
271         m_view->setPaintsEntireContents(true);
272 #endif
273 }
274
275 void Frame::setDocument(PassRefPtr<Document> newDocument)
276 {
277     ASSERT(!newDocument || newDocument->frame() == this);
278
279     if (m_doc && m_doc->attached() && !m_doc->inPageCache())
280         m_doc->prepareForDestruction();
281
282     m_doc = newDocument.get();
283     ASSERT(!m_doc || m_doc->domWindow());
284     ASSERT(!m_doc || m_doc->domWindow()->frame() == this);
285
286     // Don't use m_doc because it can be overwritten and we want to guarantee
287     // that the document is not destroyed during this function call.
288     if (newDocument)
289         newDocument->didBecomeCurrentDocumentInFrame();
290 }
291
292 #if ENABLE(ORIENTATION_EVENTS)
293 void Frame::sendOrientationChangeEvent(int orientation)
294 {
295     m_orientation = orientation;
296     if (Document* doc = document())
297         doc->dispatchWindowEvent(Event::create(eventNames().orientationchangeEvent, false, false));
298 }
299 #endif // ENABLE(ORIENTATION_EVENTS)
300
301 static PassOwnPtr<RegularExpression> createRegExpForLabels(const Vector<String>& labels)
302 {
303     // REVIEW- version of this call in FrameMac.mm caches based on the NSArray ptrs being
304     // the same across calls.  We can't do that.
305
306     DEFINE_STATIC_LOCAL(RegularExpression, wordRegExp, ("\\w", TextCaseSensitive));
307     String pattern("(");
308     unsigned int numLabels = labels.size();
309     unsigned int i;
310     for (i = 0; i < numLabels; i++) {
311         String label = labels[i];
312
313         bool startsWithWordChar = false;
314         bool endsWithWordChar = false;
315         if (label.length()) {
316             startsWithWordChar = wordRegExp.match(label.substring(0, 1)) >= 0;
317             endsWithWordChar = wordRegExp.match(label.substring(label.length() - 1, 1)) >= 0;
318         }
319
320         if (i)
321             pattern.append("|");
322         // Search for word boundaries only if label starts/ends with "word characters".
323         // If we always searched for word boundaries, this wouldn't work for languages
324         // such as Japanese.
325         if (startsWithWordChar)
326             pattern.append("\\b");
327         pattern.append(label);
328         if (endsWithWordChar)
329             pattern.append("\\b");
330     }
331     pattern.append(")");
332     return adoptPtr(new RegularExpression(pattern, TextCaseInsensitive));
333 }
334
335 String Frame::searchForLabelsAboveCell(RegularExpression* regExp, HTMLTableCellElement* cell, size_t* resultDistanceFromStartOfCell)
336 {
337     HTMLTableCellElement* aboveCell = cell->cellAbove();
338     if (aboveCell) {
339         // search within the above cell we found for a match
340         size_t lengthSearched = 0;    
341         for (Text* textNode = TextNodeTraversal::firstWithin(aboveCell); textNode; textNode = TextNodeTraversal::next(textNode, aboveCell)) {
342             if (!textNode->renderer() || textNode->renderer()->style().visibility() != VISIBLE)
343                 continue;
344             // For each text chunk, run the regexp
345             String nodeString = textNode->data();
346             int pos = regExp->searchRev(nodeString);
347             if (pos >= 0) {
348                 if (resultDistanceFromStartOfCell)
349                     *resultDistanceFromStartOfCell = lengthSearched;
350                 return nodeString.substring(pos, regExp->matchedLength());
351             }
352             lengthSearched += nodeString.length();
353         }
354     }
355
356     // Any reason in practice to search all cells in that are above cell?
357     if (resultDistanceFromStartOfCell)
358         *resultDistanceFromStartOfCell = notFound;
359     return String();
360 }
361
362 String Frame::searchForLabelsBeforeElement(const Vector<String>& labels, Element* element, size_t* resultDistance, bool* resultIsInCellAbove)
363 {
364     OwnPtr<RegularExpression> regExp(createRegExpForLabels(labels));
365     // We stop searching after we've seen this many chars
366     const unsigned int charsSearchedThreshold = 500;
367     // This is the absolute max we search.  We allow a little more slop than
368     // charsSearchedThreshold, to make it more likely that we'll search whole nodes.
369     const unsigned int maxCharsSearched = 600;
370     // If the starting element is within a table, the cell that contains it
371     HTMLTableCellElement* startingTableCell = 0;
372     bool searchedCellAbove = false;
373
374     if (resultDistance)
375         *resultDistance = notFound;
376     if (resultIsInCellAbove)
377         *resultIsInCellAbove = false;
378     
379     // walk backwards in the node tree, until another element, or form, or end of tree
380     int unsigned lengthSearched = 0;
381     Node* n;
382     for (n = NodeTraversal::previous(element); n && lengthSearched < charsSearchedThreshold; n = NodeTraversal::previous(n)) {
383         // We hit another form element or the start of the form - bail out
384         if (isHTMLFormElement(n) || (n->isHTMLElement() && toElement(n)->isFormControlElement()))
385             break;
386
387         if (n->hasTagName(tdTag) && !startingTableCell) {
388             startingTableCell = toHTMLTableCellElement(n);
389         } else if (n->hasTagName(trTag) && startingTableCell) {
390             String result = searchForLabelsAboveCell(regExp.get(), startingTableCell, resultDistance);
391             if (!result.isEmpty()) {
392                 if (resultIsInCellAbove)
393                     *resultIsInCellAbove = true;
394                 return result;
395             }
396             searchedCellAbove = true;
397         } else if (n->isTextNode() && n->renderer() && n->renderer()->style().visibility() == VISIBLE) {
398             // For each text chunk, run the regexp
399             String nodeString = n->nodeValue();
400             // add 100 for slop, to make it more likely that we'll search whole nodes
401             if (lengthSearched + nodeString.length() > maxCharsSearched)
402                 nodeString = nodeString.right(charsSearchedThreshold - lengthSearched);
403             int pos = regExp->searchRev(nodeString);
404             if (pos >= 0) {
405                 if (resultDistance)
406                     *resultDistance = lengthSearched;
407                 return nodeString.substring(pos, regExp->matchedLength());
408             }
409             lengthSearched += nodeString.length();
410         }
411     }
412
413     // If we started in a cell, but bailed because we found the start of the form or the
414     // previous element, we still might need to search the row above us for a label.
415     if (startingTableCell && !searchedCellAbove) {
416          String result = searchForLabelsAboveCell(regExp.get(), startingTableCell, resultDistance);
417         if (!result.isEmpty()) {
418             if (resultIsInCellAbove)
419                 *resultIsInCellAbove = true;
420             return result;
421         }
422     }
423     return String();
424 }
425
426 static String matchLabelsAgainstString(const Vector<String>& labels, const String& stringToMatch)
427 {
428     if (stringToMatch.isEmpty())
429         return String();
430
431     String mutableStringToMatch = stringToMatch;
432
433     // Make numbers and _'s in field names behave like word boundaries, e.g., "address2"
434     replace(mutableStringToMatch, RegularExpression("\\d", TextCaseSensitive), " ");
435     mutableStringToMatch.replace('_', ' ');
436     
437     OwnPtr<RegularExpression> regExp(createRegExpForLabels(labels));
438     // Use the largest match we can find in the whole string
439     int pos;
440     int length;
441     int bestPos = -1;
442     int bestLength = -1;
443     int start = 0;
444     do {
445         pos = regExp->match(mutableStringToMatch, start);
446         if (pos != -1) {
447             length = regExp->matchedLength();
448             if (length >= bestLength) {
449                 bestPos = pos;
450                 bestLength = length;
451             }
452             start = pos + 1;
453         }
454     } while (pos != -1);
455     
456     if (bestPos != -1)
457         return mutableStringToMatch.substring(bestPos, bestLength);
458     return String();
459 }
460     
461 String Frame::matchLabelsAgainstElement(const Vector<String>& labels, Element* element)
462 {
463     // Match against the name element, then against the id element if no match is found for the name element.
464     // See 7538330 for one popular site that benefits from the id element check.
465     // FIXME: This code is mirrored in FrameMac.mm. It would be nice to make the Mac code call the platform-agnostic
466     // code, which would require converting the NSArray of NSStrings to a Vector of Strings somewhere along the way.
467     String resultFromNameAttribute = matchLabelsAgainstString(labels, element->getNameAttribute());
468     if (!resultFromNameAttribute.isEmpty())
469         return resultFromNameAttribute;
470     
471     return matchLabelsAgainstString(labels, element->getAttribute(idAttr));
472 }
473
474 void Frame::setPrinting(bool printing, const FloatSize& pageSize, const FloatSize& originalPageSize, float maximumShrinkRatio, AdjustViewSizeOrNot shouldAdjustViewSize)
475 {
476     // In setting printing, we should not validate resources already cached for the document.
477     // See https://bugs.webkit.org/show_bug.cgi?id=43704
478     ResourceCacheValidationSuppressor validationSuppressor(m_doc->cachedResourceLoader());
479
480     m_doc->setPrinting(printing);
481     view()->adjustMediaTypeForPrinting(printing);
482
483     m_doc->styleResolverChanged(RecalcStyleImmediately);
484     if (shouldUsePrintingLayout()) {
485         view()->forceLayoutForPagination(pageSize, originalPageSize, maximumShrinkRatio, shouldAdjustViewSize);
486     } else {
487         view()->forceLayout();
488         if (shouldAdjustViewSize == AdjustViewSize)
489             view()->adjustViewSize();
490     }
491
492     // Subframes of the one we're printing don't lay out to the page size.
493     for (RefPtr<Frame> child = tree().firstChild(); child; child = child->tree().nextSibling())
494         child->setPrinting(printing, FloatSize(), FloatSize(), 0, shouldAdjustViewSize);
495 }
496
497 bool Frame::shouldUsePrintingLayout() const
498 {
499     // Only top frame being printed should be fit to page size.
500     // Subframes should be constrained by parents only.
501     return m_doc->printing() && (!tree().parent() || !tree().parent()->m_doc->printing());
502 }
503
504 FloatSize Frame::resizePageRectsKeepingRatio(const FloatSize& originalSize, const FloatSize& expectedSize)
505 {
506     FloatSize resultSize;
507     if (!contentRenderer())
508         return FloatSize();
509
510     if (contentRenderer()->style().isHorizontalWritingMode()) {
511         ASSERT(fabs(originalSize.width()) > std::numeric_limits<float>::epsilon());
512         float ratio = originalSize.height() / originalSize.width();
513         resultSize.setWidth(floorf(expectedSize.width()));
514         resultSize.setHeight(floorf(resultSize.width() * ratio));
515     } else {
516         ASSERT(fabs(originalSize.height()) > std::numeric_limits<float>::epsilon());
517         float ratio = originalSize.width() / originalSize.height();
518         resultSize.setHeight(floorf(expectedSize.height()));
519         resultSize.setWidth(floorf(resultSize.height() * ratio));
520     }
521     return resultSize;
522 }
523
524 void Frame::injectUserScripts(UserScriptInjectionTime injectionTime)
525 {
526     if (!m_page)
527         return;
528
529     if (loader().stateMachine()->creatingInitialEmptyDocument() && !settings().shouldInjectUserScriptsInInitialEmptyDocument())
530         return;
531
532     // Walk the hashtable. Inject by world.
533     const UserScriptMap* userScripts = m_page->group().userScripts();
534     if (!userScripts)
535         return;
536
537     for (auto it = userScripts->begin(), end = userScripts->end(); it != end; ++it)
538         injectUserScriptsForWorld(*it->key.get(), *it->value, injectionTime);
539 }
540
541 void Frame::injectUserScriptsForWorld(DOMWrapperWorld& world, const UserScriptVector& userScripts, UserScriptInjectionTime injectionTime)
542 {
543     if (userScripts.isEmpty())
544         return;
545
546     Document* doc = document();
547     if (!doc)
548         return;
549
550     Vector<ScriptSourceCode> sourceCode;
551     unsigned count = userScripts.size();
552     for (unsigned i = 0; i < count; ++i) {
553         UserScript* script = userScripts[i].get();
554         if (script->injectedFrames() == InjectInTopFrameOnly && ownerElement())
555             continue;
556
557         if (script->injectionTime() == injectionTime && UserContentURLPattern::matchesPatterns(doc->url(), script->whitelist(), script->blacklist()))
558             m_script->evaluateInWorld(ScriptSourceCode(script->source(), script->url()), world);
559     }
560 }
561
562 RenderView* Frame::contentRenderer() const
563 {
564     return document() ? document()->renderView() : 0;
565 }
566
567 RenderWidget* Frame::ownerRenderer() const
568 {
569     HTMLFrameOwnerElement* ownerElement = m_ownerElement;
570     if (!ownerElement)
571         return 0;
572     auto object = ownerElement->renderer();
573     if (!object)
574         return 0;
575     // FIXME: If <object> is ever fixed to disassociate itself from frames
576     // that it has started but canceled, then this can turn into an ASSERT
577     // since m_ownerElement would be 0 when the load is canceled.
578     // https://bugs.webkit.org/show_bug.cgi?id=18585
579     if (!object->isWidget())
580         return 0;
581     return toRenderWidget(object);
582 }
583
584 Frame* Frame::frameForWidget(const Widget* widget)
585 {
586     ASSERT_ARG(widget, widget);
587
588     if (RenderWidget* renderer = RenderWidget::find(widget))
589         return renderer->frameOwnerElement().document().frame();
590
591     // Assume all widgets are either a FrameView or owned by a RenderWidget.
592     // FIXME: That assumption is not right for scroll bars!
593     ASSERT_WITH_SECURITY_IMPLICATION(widget->isFrameView());
594     return &toFrameView(widget)->frame();
595 }
596
597 void Frame::clearTimers(FrameView *view, Document *document)
598 {
599     if (view) {
600         view->unscheduleRelayout();
601         view->frame().animation().suspendAnimationsForDocument(document);
602         view->frame().eventHandler().stopAutoscrollTimer();
603     }
604 }
605
606 void Frame::clearTimers()
607 {
608     clearTimers(m_view.get(), document());
609 }
610
611 void Frame::willDetachPage()
612 {
613     if (Frame* parent = tree().parent())
614         parent->loader().checkLoadComplete();
615
616     for (auto& observer : m_destructionObservers)
617         observer->willDetachPage();
618
619     // FIXME: It's unclear as to why this is called more than once, but it is,
620     // so page() could be NULL.
621     if (page() && page()->focusController().focusedFrame() == this)
622         page()->focusController().setFocusedFrame(0);
623
624     if (page() && page()->scrollingCoordinator() && m_view)
625         page()->scrollingCoordinator()->willDestroyScrollableArea(m_view.get());
626
627     script().clearScriptObjects();
628     script().updatePlatformScriptObjects();
629 }
630
631 void Frame::disconnectOwnerElement()
632 {
633     if (m_ownerElement) {
634         // We use the ownerElement's document to retrieve the cache, because the contentDocument for this
635         // frame is already detached (and can't access the top level AX cache).
636         // However, we pass in the current document to clearTextMarkerNodesInUse so we can identify the
637         // nodes inside this document that need to be removed from the cache.
638         
639         // We don't clear the AXObjectCache here because we don't want to clear the top level cache
640         // when a sub-frame is removed.
641 #if HAVE(ACCESSIBILITY)
642         if (AXObjectCache* cache = m_ownerElement->document().existingAXObjectCache())
643             cache->clearTextMarkerNodesInUse(document());
644 #endif
645         
646         m_ownerElement->clearContentFrame();
647         if (m_page)
648             m_page->decrementSubframeCount();
649     }
650     m_ownerElement = nullptr;
651 }
652
653 String Frame::displayStringModifiedByEncoding(const String& str) const
654 {
655     return document() ? document()->displayStringModifiedByEncoding(str) : str;
656 }
657
658 VisiblePosition Frame::visiblePositionForPoint(const IntPoint& framePoint)
659 {
660     HitTestResult result = eventHandler().hitTestResultAtPoint(framePoint, HitTestRequest::ReadOnly | HitTestRequest::Active);
661     Node* node = result.innerNonSharedNode();
662     if (!node)
663         return VisiblePosition();
664     auto renderer = node->renderer();
665     if (!renderer)
666         return VisiblePosition();
667     VisiblePosition visiblePos = renderer->positionForPoint(result.localPoint());
668     if (visiblePos.isNull())
669         visiblePos = firstPositionInOrBeforeNode(node);
670     return visiblePos;
671 }
672
673 Document* Frame::documentAtPoint(const IntPoint& point)
674 {
675     if (!view())
676         return 0;
677
678     IntPoint pt = view()->windowToContents(point);
679     HitTestResult result = HitTestResult(pt);
680
681     if (contentRenderer())
682         result = eventHandler().hitTestResultAtPoint(pt);
683     return result.innerNode() ? &result.innerNode()->document() : 0;
684 }
685
686 PassRefPtr<Range> Frame::rangeForPoint(const IntPoint& framePoint)
687 {
688     VisiblePosition position = visiblePositionForPoint(framePoint);
689     if (position.isNull())
690         return 0;
691
692     VisiblePosition previous = position.previous();
693     if (previous.isNotNull()) {
694         RefPtr<Range> previousCharacterRange = makeRange(previous, position);
695         LayoutRect rect = editor().firstRectForRange(previousCharacterRange.get());
696         if (rect.contains(framePoint))
697             return previousCharacterRange.release();
698     }
699
700     VisiblePosition next = position.next();
701     if (RefPtr<Range> nextCharacterRange = makeRange(position, next)) {
702         LayoutRect rect = editor().firstRectForRange(nextCharacterRange.get());
703         if (rect.contains(framePoint))
704             return nextCharacterRange.release();
705     }
706
707     return 0;
708 }
709
710 void Frame::createView(const IntSize& viewportSize, const Color& backgroundColor, bool transparent,
711     const IntSize& fixedLayoutSize, const IntRect& fixedVisibleContentRect ,
712     bool useFixedLayout, ScrollbarMode horizontalScrollbarMode, bool horizontalLock,
713     ScrollbarMode verticalScrollbarMode, bool verticalLock)
714 {
715     ASSERT(this);
716     ASSERT(m_page);
717
718     bool isMainFrame = this->isMainFrame();
719
720     if (isMainFrame && view())
721         view()->setParentVisible(false);
722
723     setView(0);
724
725     RefPtr<FrameView> frameView;
726     if (isMainFrame) {
727         frameView = FrameView::create(*this, viewportSize);
728         frameView->setFixedLayoutSize(fixedLayoutSize);
729         frameView->setFixedVisibleContentRect(fixedVisibleContentRect);
730         frameView->setUseFixedLayout(useFixedLayout);
731     } else
732         frameView = FrameView::create(*this);
733
734     frameView->setScrollbarModes(horizontalScrollbarMode, verticalScrollbarMode, horizontalLock, verticalLock);
735
736     setView(frameView);
737
738     if (backgroundColor.isValid())
739         frameView->updateBackgroundRecursively(backgroundColor, transparent);
740
741     if (isMainFrame)
742         frameView->setParentVisible(true);
743
744     if (ownerRenderer())
745         ownerRenderer()->setWidget(frameView);
746
747     if (HTMLFrameOwnerElement* owner = ownerElement())
748         view()->setCanHaveScrollbars(owner->scrollingMode() != ScrollbarAlwaysOff);
749 }
750
751 #if USE(TILED_BACKING_STORE)
752 void Frame::setTiledBackingStoreEnabled(bool enabled)
753 {
754     if (!enabled) {
755         m_tiledBackingStore.clear();
756         return;
757     }
758     if (m_tiledBackingStore)
759         return;
760     m_tiledBackingStore = adoptPtr(new TiledBackingStore(this));
761     m_tiledBackingStore->setCommitTileUpdatesOnIdleEventLoop(true);
762     if (m_view)
763         m_view->setPaintsEntireContents(true);
764 }
765
766 void Frame::tiledBackingStorePaintBegin()
767 {
768     if (!m_view)
769         return;
770     m_view->updateLayoutAndStyleIfNeededRecursive();
771     m_view->flushDeferredRepaints();
772 }
773
774 void Frame::tiledBackingStorePaint(GraphicsContext* context, const IntRect& rect)
775 {
776     if (!m_view)
777         return;
778     m_view->paintContents(context, rect);
779 }
780
781 void Frame::tiledBackingStorePaintEnd(const Vector<IntRect>& paintedArea)
782 {
783     if (!m_page || !m_view)
784         return;
785     unsigned size = paintedArea.size();
786     // Request repaint from the system
787     for (unsigned n = 0; n < size; ++n)
788         m_page->chrome().invalidateContentsAndRootView(m_view->contentsToRootView(paintedArea[n]), false);
789 }
790
791 IntRect Frame::tiledBackingStoreContentsRect()
792 {
793     if (!m_view)
794         return IntRect();
795     return IntRect(IntPoint(), m_view->contentsSize());
796 }
797
798 IntRect Frame::tiledBackingStoreVisibleRect()
799 {
800     if (!m_page)
801         return IntRect();
802     return m_page->chrome().client().visibleRectForTiledBackingStore();
803 }
804
805 Color Frame::tiledBackingStoreBackgroundColor() const
806 {
807     if (!m_view)
808         return Color();
809     return m_view->baseBackgroundColor();
810 }
811 #endif
812
813 String Frame::layerTreeAsText(LayerTreeFlags flags) const
814 {
815 #if USE(ACCELERATED_COMPOSITING)
816     document()->updateLayout();
817
818     if (!contentRenderer())
819         return String();
820
821     return contentRenderer()->compositor().layerTreeAsText(flags);
822 #else
823     UNUSED_PARAM(flags);
824     return String();
825 #endif
826 }
827
828 String Frame::trackedRepaintRectsAsText() const
829 {
830     if (!m_view)
831         return String();
832     return m_view->trackedRepaintRectsAsText();
833 }
834
835 void Frame::setPageZoomFactor(float factor)
836 {
837     setPageAndTextZoomFactors(factor, m_textZoomFactor);
838 }
839
840 void Frame::setTextZoomFactor(float factor)
841 {
842     setPageAndTextZoomFactors(m_pageZoomFactor, factor);
843 }
844
845 void Frame::setPageAndTextZoomFactors(float pageZoomFactor, float textZoomFactor)
846 {
847     if (m_pageZoomFactor == pageZoomFactor && m_textZoomFactor == textZoomFactor)
848         return;
849
850     Page* page = this->page();
851     if (!page)
852         return;
853
854     Document* document = this->document();
855     if (!document)
856         return;
857
858     m_editor->dismissCorrectionPanelAsIgnored();
859
860 #if ENABLE(SVG)
861     // Respect SVGs zoomAndPan="disabled" property in standalone SVG documents.
862     // FIXME: How to handle compound documents + zoomAndPan="disabled"? Needs SVG WG clarification.
863     if (document->isSVGDocument()) {
864         if (!toSVGDocument(document)->zoomAndPanEnabled())
865             return;
866     }
867 #endif
868
869     if (m_pageZoomFactor != pageZoomFactor) {
870         if (FrameView* view = this->view()) {
871             // Update the scroll position when doing a full page zoom, so the content stays in relatively the same position.
872             LayoutPoint scrollPosition = view->scrollPosition();
873             float percentDifference = (pageZoomFactor / m_pageZoomFactor);
874             view->setScrollPosition(IntPoint(scrollPosition.x() * percentDifference, scrollPosition.y() * percentDifference));
875         }
876     }
877
878     m_pageZoomFactor = pageZoomFactor;
879     m_textZoomFactor = textZoomFactor;
880
881     document->recalcStyle(Style::Force);
882
883     for (RefPtr<Frame> child = tree().firstChild(); child; child = child->tree().nextSibling())
884         child->setPageAndTextZoomFactors(m_pageZoomFactor, m_textZoomFactor);
885
886     if (FrameView* view = this->view()) {
887         if (document->renderView() && document->renderView()->needsLayout() && view->didFirstLayout())
888             view->layout();
889     }
890
891     if (isMainFrame())
892         pageCache()->markPagesForFullStyleRecalc(page);
893 }
894
895 float Frame::frameScaleFactor() const
896 {
897     Page* page = this->page();
898
899     // Main frame is scaled with respect to he container but inner frames are not scaled with respect to the main frame.
900     if (!page || &page->mainFrame() != this || settings().delegatesPageScaling())
901         return 1;
902
903     return page->pageScaleFactor();
904 }
905
906 void Frame::suspendActiveDOMObjectsAndAnimations()
907 {
908     bool wasSuspended = activeDOMObjectsAndAnimationsSuspended();
909
910     m_activeDOMObjectsAndAnimationsSuspendedCount++;
911
912     if (wasSuspended)
913         return;
914
915     // FIXME: Suspend/resume calls will not match if the frame is navigated, and gets a new document.
916     if (document()) {
917         document()->suspendScriptedAnimationControllerCallbacks();
918         animation().suspendAnimationsForDocument(document());
919         document()->suspendActiveDOMObjects(ActiveDOMObject::PageWillBeSuspended);
920     }
921 }
922
923 void Frame::resumeActiveDOMObjectsAndAnimations()
924 {
925     ASSERT(activeDOMObjectsAndAnimationsSuspended());
926
927     m_activeDOMObjectsAndAnimationsSuspendedCount--;
928
929     if (activeDOMObjectsAndAnimationsSuspended())
930         return;
931
932     if (document()) {
933         document()->resumeActiveDOMObjects(ActiveDOMObject::PageWillBeSuspended);
934         animation().resumeAnimationsForDocument(document());
935         document()->resumeScriptedAnimationControllerCallbacks();
936     }
937 }
938
939 #if USE(ACCELERATED_COMPOSITING)
940 void Frame::deviceOrPageScaleFactorChanged()
941 {
942     for (RefPtr<Frame> child = tree().firstChild(); child; child = child->tree().nextSibling())
943         child->deviceOrPageScaleFactorChanged();
944
945     if (RenderView* root = contentRenderer())
946         root->compositor().deviceOrPageScaleFactorChanged();
947 }
948 #endif
949
950 bool Frame::isURLAllowed(const URL& url) const
951 {
952     // We allow one level of self-reference because some sites depend on that,
953     // but we don't allow more than one.
954     if (m_page->subframeCount() >= Page::maxNumberOfFrames)
955         return false;
956     bool foundSelfReference = false;
957     for (const Frame* frame = this; frame; frame = frame->tree().parent()) {
958         if (equalIgnoringFragmentIdentifier(frame->document()->url(), url)) {
959             if (foundSelfReference)
960                 return false;
961             foundSelfReference = true;
962         }
963     }
964     return true;
965 }
966
967 } // namespace WebCore