8b8f63cbf57376995ad1f53f47b4a1e9184ec23c
[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 "HTMLTableRowElement.h"
65 #include "HitTestResult.h"
66 #include "ImageBuffer.h"
67 #include "InspectorInstrumentation.h"
68 #include "JSDOMWindowShell.h"
69 #include "Logging.h"
70 #include "MainFrame.h"
71 #include "MathMLNames.h"
72 #include "MediaFeatureNames.h"
73 #include "Navigator.h"
74 #include "NodeList.h"
75 #include "NodeTraversal.h"
76 #include "Page.h"
77 #include "PageCache.h"
78 #include "PageGroup.h"
79 #include "RenderLayerCompositor.h"
80 #include "RenderTableCell.h"
81 #include "RenderText.h"
82 #include "RenderTextControl.h"
83 #include "RenderTheme.h"
84 #include "RenderView.h"
85 #include "RenderWidget.h"
86 #include "RuntimeEnabledFeatures.h"
87 #include "SVGDocument.h"
88 #include "SVGDocumentExtensions.h"
89 #include "SVGNames.h"
90 #include "ScriptController.h"
91 #include "ScriptSourceCode.h"
92 #include "ScrollingCoordinator.h"
93 #include "Settings.h"
94 #include "StyleProperties.h"
95 #include "TextNodeTraversal.h"
96 #include "TextResourceDecoder.h"
97 #include "UserContentController.h"
98 #include "UserContentURLPattern.h"
99 #include "UserTypingGestureIndicator.h"
100 #include "VisibleUnits.h"
101 #include "WebKitFontFamilyNames.h"
102 #include "XLinkNames.h"
103 #include "XMLNSNames.h"
104 #include "XMLNames.h"
105 #include "htmlediting.h"
106 #include "markup.h"
107 #include "npruntime_impl.h"
108 #include "runtime_root.h"
109 #include <bindings/ScriptValue.h>
110 #include <wtf/RefCountedLeakCounter.h>
111 #include <wtf/StdLibExtras.h>
112 #include <yarr/RegularExpression.h>
113
114 #if PLATFORM(IOS)
115 #include "WKContentObservation.h"
116 #endif
117
118 namespace WebCore {
119
120 using namespace HTMLNames;
121
122 #if PLATFORM(IOS)
123 const unsigned scrollFrequency = 1000 / 60;
124 #endif
125
126 DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, frameCounter, ("Frame"));
127
128 static inline Frame* parentFromOwnerElement(HTMLFrameOwnerElement* ownerElement)
129 {
130     if (!ownerElement)
131         return 0;
132     return ownerElement->document().frame();
133 }
134
135 static inline float parentPageZoomFactor(Frame* frame)
136 {
137     Frame* parent = frame->tree().parent();
138     if (!parent)
139         return 1;
140     return parent->pageZoomFactor();
141 }
142
143 static inline float parentTextZoomFactor(Frame* frame)
144 {
145     Frame* parent = frame->tree().parent();
146     if (!parent)
147         return 1;
148     return parent->textZoomFactor();
149 }
150
151 Frame::Frame(Page& page, HTMLFrameOwnerElement* ownerElement, FrameLoaderClient& frameLoaderClient)
152     : m_mainFrame(ownerElement ? page.mainFrame() : static_cast<MainFrame&>(*this))
153     , m_page(&page)
154     , m_settings(&page.settings())
155     , m_treeNode(*this, parentFromOwnerElement(ownerElement))
156     , m_loader(*this, frameLoaderClient)
157     , m_navigationScheduler(*this)
158     , m_ownerElement(ownerElement)
159     , m_script(std::make_unique<ScriptController>(*this))
160     , m_editor(std::make_unique<Editor>(*this))
161     , m_selection(std::make_unique<FrameSelection>(this))
162     , m_eventHandler(std::make_unique<EventHandler>(*this))
163     , m_animationController(std::make_unique<AnimationController>(*this))
164 #if PLATFORM(IOS)
165     , m_overflowAutoScrollTimer(this, &Frame::overflowAutoScrollTimerFired)
166     , m_selectionChangeCallbacksDisabled(false)
167     , m_timersPausedCount(0)
168 #endif
169     , m_pageZoomFactor(parentPageZoomFactor(this))
170     , m_textZoomFactor(parentTextZoomFactor(this))
171     , m_activeDOMObjectsAndAnimationsSuspendedCount(0)
172 {
173     AtomicString::init();
174     HTMLNames::init();
175     QualifiedName::init();
176     MediaFeatureNames::init();
177     SVGNames::init();
178     XLinkNames::init();
179     MathMLNames::init();
180     XMLNSNames::init();
181     XMLNames::init();
182     WebKitFontFamilyNames::init();
183
184     if (ownerElement) {
185         m_mainFrame.selfOnlyRef();
186         page.incrementSubframeCount();
187         ownerElement->setContentFrame(this);
188     }
189
190 #ifndef NDEBUG
191     frameCounter.increment();
192 #endif
193
194     // FIXME: We should reconcile the iOS and OpenSource code below.
195     Frame* parent = parentFromOwnerElement(ownerElement);
196 #if PLATFORM(IOS)
197     // Pause future timers if this frame is created when page is in pending state.
198     if (parent && parent->timersPaused())
199         setTimersPaused(true);
200 #else
201     // Pause future ActiveDOMObjects if this frame is being created while the page is in a paused state.
202     if (parent && parent->activeDOMObjectsAndAnimationsSuspended())
203         suspendActiveDOMObjectsAndAnimations();
204 #endif
205 }
206
207 PassRefPtr<Frame> Frame::create(Page* page, HTMLFrameOwnerElement* ownerElement, FrameLoaderClient* client)
208 {
209     ASSERT(page);
210     ASSERT(client);
211     return adoptRef(new Frame(*page, ownerElement, *client));
212 }
213
214 Frame::~Frame()
215 {
216     setView(0);
217     loader().cancelAndClear();
218
219     // FIXME: We should not be doing all this work inside the destructor
220
221 #ifndef NDEBUG
222     frameCounter.decrement();
223 #endif
224
225     disconnectOwnerElement();
226
227     for (auto& observer : m_destructionObservers)
228         observer->frameDestroyed();
229
230     if (!isMainFrame())
231         m_mainFrame.selfOnlyDeref();
232 }
233
234 void Frame::addDestructionObserver(FrameDestructionObserver* observer)
235 {
236     m_destructionObservers.add(observer);
237 }
238
239 void Frame::removeDestructionObserver(FrameDestructionObserver* observer)
240 {
241     m_destructionObservers.remove(observer);
242 }
243
244 void Frame::setView(PassRefPtr<FrameView> view)
245 {
246     // We the custom scroll bars as early as possible to prevent m_doc->detach()
247     // from messing with the view such that its scroll bars won't be torn down.
248     // FIXME: We should revisit this.
249     if (m_view)
250         m_view->prepareForDetach();
251
252     // Prepare for destruction now, so any unload event handlers get run and the DOMWindow is
253     // notified. If we wait until the view is destroyed, then things won't be hooked up enough for
254     // these calls to work.
255     if (!view && m_doc && !m_doc->inPageCache())
256         m_doc->prepareForDestruction();
257     
258     if (m_view)
259         m_view->unscheduleRelayout();
260     
261     eventHandler().clear();
262
263     m_view = view;
264
265     // Only one form submission is allowed per view of a part.
266     // Since this part may be getting reused as a result of being
267     // pulled from the back/forward cache, reset this flag.
268     loader().resetMultipleFormSubmissionProtection();
269 }
270
271 void Frame::setDocument(PassRefPtr<Document> newDocument)
272 {
273     ASSERT(!newDocument || newDocument->frame() == this);
274
275     if (m_doc && !m_doc->inPageCache())
276         m_doc->prepareForDestruction();
277
278     m_doc = newDocument.get();
279     ASSERT(!m_doc || m_doc->domWindow());
280     ASSERT(!m_doc || m_doc->domWindow()->frame() == this);
281
282     // Don't use m_doc because it can be overwritten and we want to guarantee
283     // that the document is not destroyed during this function call.
284     if (newDocument)
285         newDocument->didBecomeCurrentDocumentInFrame();
286 }
287
288 #if ENABLE(ORIENTATION_EVENTS)
289 void Frame::orientationChanged()
290 {
291     Vector<Ref<Frame>> frames;
292     for (Frame* frame = this; frame; frame = frame->tree().traverseNext())
293         frames.append(*frame);
294
295     for (unsigned i = 0; i < frames.size(); i++) {
296         if (Document* doc = frames[i]->document())
297             doc->dispatchWindowEvent(Event::create(eventNames().orientationchangeEvent, false, false));
298     }
299 }
300
301 int Frame::orientation() const
302 {
303     if (m_page)
304         return m_page->chrome().client().deviceOrientation();
305     return 0;
306 }
307 #endif // ENABLE(ORIENTATION_EVENTS)
308
309 static JSC::Yarr::RegularExpression createRegExpForLabels(const Vector<String>& labels)
310 {
311     // REVIEW- version of this call in FrameMac.mm caches based on the NSArray ptrs being
312     // the same across calls.  We can't do that.
313
314     DEPRECATED_DEFINE_STATIC_LOCAL(JSC::Yarr::RegularExpression, wordRegExp, ("\\w", TextCaseSensitive));
315     StringBuilder pattern;
316     pattern.append('(');
317     unsigned int numLabels = labels.size();
318     unsigned int i;
319     for (i = 0; i < numLabels; i++) {
320         String label = labels[i];
321
322         bool startsWithWordChar = false;
323         bool endsWithWordChar = false;
324         if (label.length()) {
325             startsWithWordChar = wordRegExp.match(label.substring(0, 1)) >= 0;
326             endsWithWordChar = wordRegExp.match(label.substring(label.length() - 1, 1)) >= 0;
327         }
328
329         if (i)
330             pattern.append('|');
331         // Search for word boundaries only if label starts/ends with "word characters".
332         // If we always searched for word boundaries, this wouldn't work for languages
333         // such as Japanese.
334         if (startsWithWordChar)
335             pattern.appendLiteral("\\b");
336         pattern.append(label);
337         if (endsWithWordChar)
338             pattern.appendLiteral("\\b");
339     }
340     pattern.append(')');
341     return JSC::Yarr::RegularExpression(pattern.toString(), TextCaseInsensitive);
342 }
343
344 String Frame::searchForLabelsAboveCell(const JSC::Yarr::RegularExpression& regExp, HTMLTableCellElement* cell, size_t* resultDistanceFromStartOfCell)
345 {
346     HTMLTableCellElement* aboveCell = cell->cellAbove();
347     if (aboveCell) {
348         // search within the above cell we found for a match
349         size_t lengthSearched = 0;    
350         for (Text* textNode = TextNodeTraversal::firstWithin(aboveCell); textNode; textNode = TextNodeTraversal::next(textNode, aboveCell)) {
351             if (!textNode->renderer() || textNode->renderer()->style().visibility() != VISIBLE)
352                 continue;
353             // For each text chunk, run the regexp
354             String nodeString = textNode->data();
355             int pos = regExp.searchRev(nodeString);
356             if (pos >= 0) {
357                 if (resultDistanceFromStartOfCell)
358                     *resultDistanceFromStartOfCell = lengthSearched;
359                 return nodeString.substring(pos, regExp.matchedLength());
360             }
361             lengthSearched += nodeString.length();
362         }
363     }
364
365     // Any reason in practice to search all cells in that are above cell?
366     if (resultDistanceFromStartOfCell)
367         *resultDistanceFromStartOfCell = notFound;
368     return String();
369 }
370
371 String Frame::searchForLabelsBeforeElement(const Vector<String>& labels, Element* element, size_t* resultDistance, bool* resultIsInCellAbove)
372 {
373     JSC::Yarr::RegularExpression regExp = createRegExpForLabels(labels);
374     // We stop searching after we've seen this many chars
375     const unsigned int charsSearchedThreshold = 500;
376     // This is the absolute max we search.  We allow a little more slop than
377     // charsSearchedThreshold, to make it more likely that we'll search whole nodes.
378     const unsigned int maxCharsSearched = 600;
379     // If the starting element is within a table, the cell that contains it
380     HTMLTableCellElement* startingTableCell = 0;
381     bool searchedCellAbove = false;
382
383     if (resultDistance)
384         *resultDistance = notFound;
385     if (resultIsInCellAbove)
386         *resultIsInCellAbove = false;
387     
388     // walk backwards in the node tree, until another element, or form, or end of tree
389     int unsigned lengthSearched = 0;
390     Node* n;
391     for (n = NodeTraversal::previous(element); n && lengthSearched < charsSearchedThreshold; n = NodeTraversal::previous(n)) {
392         // We hit another form element or the start of the form - bail out
393         if (is<HTMLFormElement>(*n) || is<HTMLFormControlElement>(*n))
394             break;
395
396         if (n->hasTagName(tdTag) && !startingTableCell)
397             startingTableCell = downcast<HTMLTableCellElement>(n);
398         else if (is<HTMLTableRowElement>(*n) && startingTableCell) {
399             String result = searchForLabelsAboveCell(regExp, startingTableCell, resultDistance);
400             if (!result.isEmpty()) {
401                 if (resultIsInCellAbove)
402                     *resultIsInCellAbove = true;
403                 return result;
404             }
405             searchedCellAbove = true;
406         } else if (n->isTextNode() && n->renderer() && n->renderer()->style().visibility() == VISIBLE) {
407             // For each text chunk, run the regexp
408             String nodeString = n->nodeValue();
409             // add 100 for slop, to make it more likely that we'll search whole nodes
410             if (lengthSearched + nodeString.length() > maxCharsSearched)
411                 nodeString = nodeString.right(charsSearchedThreshold - lengthSearched);
412             int pos = regExp.searchRev(nodeString);
413             if (pos >= 0) {
414                 if (resultDistance)
415                     *resultDistance = lengthSearched;
416                 return nodeString.substring(pos, regExp.matchedLength());
417             }
418             lengthSearched += nodeString.length();
419         }
420     }
421
422     // If we started in a cell, but bailed because we found the start of the form or the
423     // previous element, we still might need to search the row above us for a label.
424     if (startingTableCell && !searchedCellAbove) {
425         String result = searchForLabelsAboveCell(regExp, startingTableCell, resultDistance);
426         if (!result.isEmpty()) {
427             if (resultIsInCellAbove)
428                 *resultIsInCellAbove = true;
429             return result;
430         }
431     }
432     return String();
433 }
434
435 static String matchLabelsAgainstString(const Vector<String>& labels, const String& stringToMatch)
436 {
437     if (stringToMatch.isEmpty())
438         return String();
439
440     String mutableStringToMatch = stringToMatch;
441
442     // Make numbers and _'s in field names behave like word boundaries, e.g., "address2"
443     replace(mutableStringToMatch, JSC::Yarr::RegularExpression("\\d", TextCaseSensitive), " ");
444     mutableStringToMatch.replace('_', ' ');
445     
446     JSC::Yarr::RegularExpression regExp = createRegExpForLabels(labels);
447     // Use the largest match we can find in the whole string
448     int pos;
449     int length;
450     int bestPos = -1;
451     int bestLength = -1;
452     int start = 0;
453     do {
454         pos = regExp.match(mutableStringToMatch, start);
455         if (pos != -1) {
456             length = regExp.matchedLength();
457             if (length >= bestLength) {
458                 bestPos = pos;
459                 bestLength = length;
460             }
461             start = pos + 1;
462         }
463     } while (pos != -1);
464     
465     if (bestPos != -1)
466         return mutableStringToMatch.substring(bestPos, bestLength);
467     return String();
468 }
469     
470 String Frame::matchLabelsAgainstElement(const Vector<String>& labels, Element* element)
471 {
472     // Match against the name element, then against the id element if no match is found for the name element.
473     // See 7538330 for one popular site that benefits from the id element check.
474     // FIXME: This code is mirrored in FrameMac.mm. It would be nice to make the Mac code call the platform-agnostic
475     // code, which would require converting the NSArray of NSStrings to a Vector of Strings somewhere along the way.
476     String resultFromNameAttribute = matchLabelsAgainstString(labels, element->getNameAttribute());
477     if (!resultFromNameAttribute.isEmpty())
478         return resultFromNameAttribute;
479     
480     return matchLabelsAgainstString(labels, element->fastGetAttribute(idAttr));
481 }
482
483 #if PLATFORM(IOS)
484 void Frame::scrollOverflowLayer(RenderLayer* layer, const IntRect& visibleRect, const IntRect& exposeRect)
485 {
486     if (!layer)
487         return;
488
489     RenderBox* box = layer->renderBox();
490     if (!box)
491         return;
492
493     if (visibleRect.intersects(exposeRect))
494         return;
495
496     int x = layer->scrollXOffset();
497     int exposeLeft = exposeRect.x();
498     int exposeRight = exposeLeft + exposeRect.width();
499     int clientWidth = box->clientWidth();
500     if (exposeLeft <= 0)
501         x = std::max(0, x + exposeLeft - clientWidth / 2);
502     else if (exposeRight >= clientWidth)
503         x = std::min(box->scrollWidth() - clientWidth, x + clientWidth / 2);
504
505     int y = layer->scrollYOffset();
506     int exposeTop = exposeRect.y();
507     int exposeBottom = exposeTop + exposeRect.height();
508     int clientHeight = box->clientHeight();
509     if (exposeTop <= 0)
510         y = std::max(0, y + exposeTop - clientHeight / 2);
511     else if (exposeBottom >= clientHeight)
512         y = std::min(box->scrollHeight() - clientHeight, y + clientHeight / 2);
513
514     layer->scrollToOffset(IntSize(x, y));
515     selection().setCaretRectNeedsUpdate();
516     selection().updateAppearance();
517 }
518
519 void Frame::overflowAutoScrollTimerFired(Timer<Frame>*)
520 {
521     if (!eventHandler().mousePressed() || checkOverflowScroll(PerformOverflowScroll) == OverflowScrollNone) {
522         if (m_overflowAutoScrollTimer.isActive())
523             m_overflowAutoScrollTimer.stop();
524     }
525 }
526
527 void Frame::startOverflowAutoScroll(const IntPoint& mousePosition)
528 {
529     m_overflowAutoScrollPos = mousePosition;
530
531     if (m_overflowAutoScrollTimer.isActive())
532         return;
533
534     if (checkOverflowScroll(DoNotPerformOverflowScroll) == OverflowScrollNone)
535         return;
536
537     m_overflowAutoScrollTimer.startRepeating(scrollFrequency);
538     m_overflowAutoScrollDelta = 3;
539 }
540
541 int Frame::checkOverflowScroll(OverflowScrollAction action)
542 {
543     Position extent = selection().selection().extent();
544     if (extent.isNull())
545         return OverflowScrollNone;
546
547     RenderObject* renderer = extent.deprecatedNode()->renderer();
548     if (!renderer)
549         return OverflowScrollNone;
550
551     FrameView* view = this->view();
552     if (!view)
553         return OverflowScrollNone;
554
555     RenderBlock* containingBlock = renderer->containingBlock();
556     if (!containingBlock || !containingBlock->hasOverflowClip())
557         return OverflowScrollNone;
558     RenderLayer* layer = containingBlock->layer();
559     ASSERT(layer);
560
561     IntRect visibleRect = IntRect(view->scrollX(), view->scrollY(), view->visibleWidth(), view->visibleHeight());
562     IntPoint position = m_overflowAutoScrollPos;
563     if (visibleRect.contains(position.x(), position.y()))
564         return OverflowScrollNone;
565
566     int scrollType = 0;
567     int deltaX = 0;
568     int deltaY = 0;
569     IntPoint selectionPosition;
570
571     // This constant will make the selection draw a little bit beyond the edge of the visible area.
572     // This prevents a visual glitch, in that you can fail to select a portion of a character that
573     // is being rendered right at the edge of the visible rectangle.
574     // FIXME: This probably needs improvement, and may need to take the font size into account.
575     static const int scrollBoundsAdjustment = 3;
576
577     // FIXME: Make a small buffer at the end of a visible rectangle so that autoscrolling works 
578     // even if the visible extends to the limits of the screen.
579     if (position.x() < visibleRect.x()) {
580         scrollType |= OverflowScrollLeft;
581         if (action == PerformOverflowScroll) {
582             deltaX -= static_cast<int>(m_overflowAutoScrollDelta);
583             selectionPosition.setX(view->scrollX() - scrollBoundsAdjustment);
584         }
585     } else if (position.x() > visibleRect.maxX()) {
586         scrollType |= OverflowScrollRight;
587         if (action == PerformOverflowScroll) {
588             deltaX += static_cast<int>(m_overflowAutoScrollDelta);
589             selectionPosition.setX(view->scrollX() + view->visibleWidth() + scrollBoundsAdjustment);
590         }
591     }
592
593     if (position.y() < visibleRect.y()) {
594         scrollType |= OverflowScrollUp;
595         if (action == PerformOverflowScroll) {
596             deltaY -= static_cast<int>(m_overflowAutoScrollDelta);
597             selectionPosition.setY(view->scrollY() - scrollBoundsAdjustment);
598         }
599     } else if (position.y() > visibleRect.maxY()) {
600         scrollType |= OverflowScrollDown;
601         if (action == PerformOverflowScroll) {
602             deltaY += static_cast<int>(m_overflowAutoScrollDelta);
603             selectionPosition.setY(view->scrollY() + view->visibleHeight() + scrollBoundsAdjustment);
604         }
605     }
606
607     if (action == PerformOverflowScroll && (deltaX || deltaY)) {
608         layer->scrollToOffset(IntSize(layer->scrollXOffset() + deltaX, layer->scrollYOffset() + deltaY));
609
610         // Handle making selection.
611         VisiblePosition visiblePosition(renderer->positionForPoint(selectionPosition, nullptr));
612         if (visiblePosition.isNotNull()) {
613             VisibleSelection visibleSelection = selection().selection();
614             visibleSelection.setExtent(visiblePosition);
615             if (selection().granularity() != CharacterGranularity)
616                 visibleSelection.expandUsingGranularity(selection().granularity());
617             if (selection().shouldChangeSelection(visibleSelection))
618                 selection().setSelection(visibleSelection);
619         }
620
621         m_overflowAutoScrollDelta *= 1.02f; // Accelerate the scroll
622     }
623     return scrollType;
624 }
625
626 void Frame::setSelectionChangeCallbacksDisabled(bool selectionChangeCallbacksDisabled)
627 {
628     m_selectionChangeCallbacksDisabled = selectionChangeCallbacksDisabled;
629 }
630
631 bool Frame::selectionChangeCallbacksDisabled() const
632 {
633     return m_selectionChangeCallbacksDisabled;
634 }
635 #endif // PLATFORM(IOS)
636
637 void Frame::setPrinting(bool printing, const FloatSize& pageSize, const FloatSize& originalPageSize, float maximumShrinkRatio, AdjustViewSizeOrNot shouldAdjustViewSize)
638 {
639     // In setting printing, we should not validate resources already cached for the document.
640     // See https://bugs.webkit.org/show_bug.cgi?id=43704
641     ResourceCacheValidationSuppressor validationSuppressor(m_doc->cachedResourceLoader());
642
643     m_doc->setPrinting(printing);
644     view()->adjustMediaTypeForPrinting(printing);
645
646     m_doc->styleResolverChanged(RecalcStyleImmediately);
647     if (shouldUsePrintingLayout()) {
648         view()->forceLayoutForPagination(pageSize, originalPageSize, maximumShrinkRatio, shouldAdjustViewSize);
649     } else {
650         view()->forceLayout();
651         if (shouldAdjustViewSize == AdjustViewSize)
652             view()->adjustViewSize();
653     }
654
655     // Subframes of the one we're printing don't lay out to the page size.
656     for (RefPtr<Frame> child = tree().firstChild(); child; child = child->tree().nextSibling())
657         child->setPrinting(printing, FloatSize(), FloatSize(), 0, shouldAdjustViewSize);
658 }
659
660 bool Frame::shouldUsePrintingLayout() const
661 {
662     // Only top frame being printed should be fit to page size.
663     // Subframes should be constrained by parents only.
664     return m_doc->printing() && (!tree().parent() || !tree().parent()->m_doc->printing());
665 }
666
667 FloatSize Frame::resizePageRectsKeepingRatio(const FloatSize& originalSize, const FloatSize& expectedSize)
668 {
669     FloatSize resultSize;
670     if (!contentRenderer())
671         return FloatSize();
672
673     if (contentRenderer()->style().isHorizontalWritingMode()) {
674         ASSERT(fabs(originalSize.width()) > std::numeric_limits<float>::epsilon());
675         float ratio = originalSize.height() / originalSize.width();
676         resultSize.setWidth(floorf(expectedSize.width()));
677         resultSize.setHeight(floorf(resultSize.width() * ratio));
678     } else {
679         ASSERT(fabs(originalSize.height()) > std::numeric_limits<float>::epsilon());
680         float ratio = originalSize.width() / originalSize.height();
681         resultSize.setHeight(floorf(expectedSize.height()));
682         resultSize.setWidth(floorf(resultSize.height() * ratio));
683     }
684     return resultSize;
685 }
686
687 void Frame::injectUserScripts(UserScriptInjectionTime injectionTime)
688 {
689     if (!m_page)
690         return;
691
692     if (loader().stateMachine().creatingInitialEmptyDocument() && !settings().shouldInjectUserScriptsInInitialEmptyDocument())
693         return;
694
695     const auto* userContentController = m_page->userContentController();
696     if (!userContentController)
697         return;
698
699     // Walk the hashtable. Inject by world.
700     const UserScriptMap* userScripts = userContentController->userScripts();
701     if (!userScripts)
702         return;
703
704     for (const auto& worldAndUserScript : *userScripts)
705         injectUserScriptsForWorld(*worldAndUserScript.key, *worldAndUserScript.value, injectionTime);
706 }
707
708 void Frame::injectUserScriptsForWorld(DOMWrapperWorld& world, const UserScriptVector& userScripts, UserScriptInjectionTime injectionTime)
709 {
710     if (userScripts.isEmpty())
711         return;
712
713     Document* doc = document();
714     if (!doc)
715         return;
716
717     Vector<ScriptSourceCode> sourceCode;
718     unsigned count = userScripts.size();
719     for (unsigned i = 0; i < count; ++i) {
720         UserScript* script = userScripts[i].get();
721         if (script->injectedFrames() == InjectInTopFrameOnly && ownerElement())
722             continue;
723
724         if (script->injectionTime() == injectionTime && UserContentURLPattern::matchesPatterns(doc->url(), script->whitelist(), script->blacklist()))
725             m_script->evaluateInWorld(ScriptSourceCode(script->source(), script->url()), world);
726     }
727 }
728
729 RenderView* Frame::contentRenderer() const
730 {
731     return document() ? document()->renderView() : nullptr;
732 }
733
734 RenderWidget* Frame::ownerRenderer() const
735 {
736     HTMLFrameOwnerElement* ownerElement = m_ownerElement;
737     if (!ownerElement)
738         return 0;
739     auto object = ownerElement->renderer();
740     if (!object)
741         return 0;
742     // FIXME: If <object> is ever fixed to disassociate itself from frames
743     // that it has started but canceled, then this can turn into an ASSERT
744     // since m_ownerElement would be 0 when the load is canceled.
745     // https://bugs.webkit.org/show_bug.cgi?id=18585
746     if (!object->isWidget())
747         return 0;
748     return toRenderWidget(object);
749 }
750
751 Frame* Frame::frameForWidget(const Widget* widget)
752 {
753     ASSERT_ARG(widget, widget);
754
755     if (RenderWidget* renderer = RenderWidget::find(widget))
756         return renderer->frameOwnerElement().document().frame();
757
758     // Assume all widgets are either a FrameView or owned by a RenderWidget.
759     // FIXME: That assumption is not right for scroll bars!
760     return &downcast<FrameView>(*widget).frame();
761 }
762
763 void Frame::clearTimers(FrameView *view, Document *document)
764 {
765     if (view) {
766         view->unscheduleRelayout();
767         view->frame().animation().suspendAnimationsForDocument(document);
768         view->frame().eventHandler().stopAutoscrollTimer();
769     }
770 }
771
772 void Frame::clearTimers()
773 {
774     clearTimers(m_view.get(), document());
775 }
776
777 void Frame::willDetachPage()
778 {
779     if (Frame* parent = tree().parent())
780         parent->loader().checkLoadComplete();
781
782     for (auto& observer : m_destructionObservers)
783         observer->willDetachPage();
784
785     // FIXME: It's unclear as to why this is called more than once, but it is,
786     // so page() could be NULL.
787     if (page() && page()->focusController().focusedFrame() == this)
788         page()->focusController().setFocusedFrame(0);
789
790     if (page() && page()->scrollingCoordinator() && m_view)
791         page()->scrollingCoordinator()->willDestroyScrollableArea(m_view.get());
792
793 #if PLATFORM(IOS)
794     if (WebThreadCountOfObservedContentModifiers() > 0 && m_page)
795         m_page->chrome().client().clearContentChangeObservers(this);
796 #endif
797
798     script().clearScriptObjects();
799     script().updatePlatformScriptObjects();
800 }
801
802 void Frame::disconnectOwnerElement()
803 {
804     if (m_ownerElement) {
805         // We use the ownerElement's document to retrieve the cache, because the contentDocument for this
806         // frame is already detached (and can't access the top level AX cache).
807         // However, we pass in the current document to clearTextMarkerNodesInUse so we can identify the
808         // nodes inside this document that need to be removed from the cache.
809         
810         // We don't clear the AXObjectCache here because we don't want to clear the top level cache
811         // when a sub-frame is removed.
812 #if HAVE(ACCESSIBILITY)
813         if (AXObjectCache* cache = m_ownerElement->document().existingAXObjectCache())
814             cache->clearTextMarkerNodesInUse(document());
815 #endif
816         
817         m_ownerElement->clearContentFrame();
818         if (m_page)
819             m_page->decrementSubframeCount();
820     }
821     m_ownerElement = nullptr;
822 }
823
824 String Frame::displayStringModifiedByEncoding(const String& str) const
825 {
826     return document() ? document()->displayStringModifiedByEncoding(str) : str;
827 }
828
829 VisiblePosition Frame::visiblePositionForPoint(const IntPoint& framePoint)
830 {
831     HitTestResult result = eventHandler().hitTestResultAtPoint(framePoint, HitTestRequest::ReadOnly | HitTestRequest::Active);
832     Node* node = result.innerNonSharedNode();
833     if (!node)
834         return VisiblePosition();
835     auto renderer = node->renderer();
836     if (!renderer)
837         return VisiblePosition();
838     VisiblePosition visiblePos = renderer->positionForPoint(result.localPoint(), nullptr);
839     if (visiblePos.isNull())
840         visiblePos = firstPositionInOrBeforeNode(node);
841     return visiblePos;
842 }
843
844 Document* Frame::documentAtPoint(const IntPoint& point)
845 {
846     if (!view())
847         return 0;
848
849     IntPoint pt = view()->windowToContents(point);
850     HitTestResult result = HitTestResult(pt);
851
852     if (contentRenderer())
853         result = eventHandler().hitTestResultAtPoint(pt);
854     return result.innerNode() ? &result.innerNode()->document() : 0;
855 }
856
857 PassRefPtr<Range> Frame::rangeForPoint(const IntPoint& framePoint)
858 {
859     VisiblePosition position = visiblePositionForPoint(framePoint);
860     if (position.isNull())
861         return 0;
862
863     VisiblePosition previous = position.previous();
864     if (previous.isNotNull()) {
865         RefPtr<Range> previousCharacterRange = makeRange(previous, position);
866         LayoutRect rect = editor().firstRectForRange(previousCharacterRange.get());
867         if (rect.contains(framePoint))
868             return previousCharacterRange.release();
869     }
870
871     VisiblePosition next = position.next();
872     if (RefPtr<Range> nextCharacterRange = makeRange(position, next)) {
873         LayoutRect rect = editor().firstRectForRange(nextCharacterRange.get());
874         if (rect.contains(framePoint))
875             return nextCharacterRange.release();
876     }
877
878     return 0;
879 }
880
881 void Frame::createView(const IntSize& viewportSize, const Color& backgroundColor, bool transparent,
882     const IntSize& fixedLayoutSize, const IntRect& fixedVisibleContentRect,
883     bool useFixedLayout, ScrollbarMode horizontalScrollbarMode, bool horizontalLock,
884     ScrollbarMode verticalScrollbarMode, bool verticalLock)
885 {
886     ASSERT(this);
887     ASSERT(m_page);
888
889     bool isMainFrame = this->isMainFrame();
890
891     if (isMainFrame && view())
892         view()->setParentVisible(false);
893
894     setView(0);
895
896     RefPtr<FrameView> frameView;
897     if (isMainFrame) {
898         frameView = FrameView::create(*this, viewportSize);
899         frameView->setFixedLayoutSize(fixedLayoutSize);
900 #if USE(TILED_BACKING_STORE)
901         frameView->setFixedVisibleContentRect(fixedVisibleContentRect);
902 #else
903         UNUSED_PARAM(fixedVisibleContentRect);
904 #endif
905         frameView->setUseFixedLayout(useFixedLayout);
906     } else
907         frameView = FrameView::create(*this);
908
909     frameView->setScrollbarModes(horizontalScrollbarMode, verticalScrollbarMode, horizontalLock, verticalLock);
910
911     setView(frameView);
912
913     if (backgroundColor.isValid())
914         frameView->updateBackgroundRecursively(backgroundColor, transparent);
915
916     if (isMainFrame)
917         frameView->setParentVisible(true);
918
919     if (ownerRenderer())
920         ownerRenderer()->setWidget(frameView);
921
922     if (HTMLFrameOwnerElement* owner = ownerElement())
923         view()->setCanHaveScrollbars(owner->scrollingMode() != ScrollbarAlwaysOff);
924 }
925
926 String Frame::layerTreeAsText(LayerTreeFlags flags) const
927 {
928     document()->updateLayout();
929
930     if (!contentRenderer())
931         return String();
932
933     return contentRenderer()->compositor().layerTreeAsText(flags);
934 }
935
936 String Frame::trackedRepaintRectsAsText() const
937 {
938     if (!m_view)
939         return String();
940     return m_view->trackedRepaintRectsAsText();
941 }
942
943 void Frame::setPageZoomFactor(float factor)
944 {
945     setPageAndTextZoomFactors(factor, m_textZoomFactor);
946 }
947
948 void Frame::setTextZoomFactor(float factor)
949 {
950     setPageAndTextZoomFactors(m_pageZoomFactor, factor);
951 }
952
953 void Frame::setPageAndTextZoomFactors(float pageZoomFactor, float textZoomFactor)
954 {
955     if (m_pageZoomFactor == pageZoomFactor && m_textZoomFactor == textZoomFactor)
956         return;
957
958     Page* page = this->page();
959     if (!page)
960         return;
961
962     Document* document = this->document();
963     if (!document)
964         return;
965
966     m_editor->dismissCorrectionPanelAsIgnored();
967
968     // Respect SVGs zoomAndPan="disabled" property in standalone SVG documents.
969     // FIXME: How to handle compound documents + zoomAndPan="disabled"? Needs SVG WG clarification.
970     if (is<SVGDocument>(*document) && !downcast<SVGDocument>(*document).zoomAndPanEnabled())
971         return;
972
973     if (m_pageZoomFactor != pageZoomFactor) {
974         if (FrameView* view = this->view()) {
975             // Update the scroll position when doing a full page zoom, so the content stays in relatively the same position.
976             LayoutPoint scrollPosition = view->scrollPosition();
977             float percentDifference = (pageZoomFactor / m_pageZoomFactor);
978             view->setScrollPosition(IntPoint(scrollPosition.x() * percentDifference, scrollPosition.y() * percentDifference));
979         }
980     }
981
982     m_pageZoomFactor = pageZoomFactor;
983     m_textZoomFactor = textZoomFactor;
984
985     document->recalcStyle(Style::Force);
986
987     for (RefPtr<Frame> child = tree().firstChild(); child; child = child->tree().nextSibling())
988         child->setPageAndTextZoomFactors(m_pageZoomFactor, m_textZoomFactor);
989
990     if (FrameView* view = this->view()) {
991         if (document->renderView() && document->renderView()->needsLayout() && view->didFirstLayout())
992             view->layout();
993     }
994
995     if (isMainFrame())
996         pageCache()->markPagesForFullStyleRecalc(page);
997 }
998
999 float Frame::frameScaleFactor() const
1000 {
1001     Page* page = this->page();
1002
1003     // Main frame is scaled with respect to he container but inner frames are not scaled with respect to the main frame.
1004     if (!page || &page->mainFrame() != this || settings().delegatesPageScaling())
1005         return 1;
1006
1007     return page->pageScaleFactor();
1008 }
1009
1010 void Frame::suspendActiveDOMObjectsAndAnimations()
1011 {
1012     bool wasSuspended = activeDOMObjectsAndAnimationsSuspended();
1013
1014     m_activeDOMObjectsAndAnimationsSuspendedCount++;
1015
1016     if (wasSuspended)
1017         return;
1018
1019     // FIXME: Suspend/resume calls will not match if the frame is navigated, and gets a new document.
1020     if (document()) {
1021         document()->suspendScriptedAnimationControllerCallbacks();
1022         animation().suspendAnimationsForDocument(document());
1023         document()->suspendActiveDOMObjects(ActiveDOMObject::PageWillBeSuspended);
1024     }
1025 }
1026
1027 void Frame::resumeActiveDOMObjectsAndAnimations()
1028 {
1029     ASSERT(activeDOMObjectsAndAnimationsSuspended());
1030
1031     m_activeDOMObjectsAndAnimationsSuspendedCount--;
1032
1033     if (activeDOMObjectsAndAnimationsSuspended())
1034         return;
1035
1036     if (document()) {
1037         document()->resumeActiveDOMObjects(ActiveDOMObject::PageWillBeSuspended);
1038         animation().resumeAnimationsForDocument(document());
1039         document()->resumeScriptedAnimationControllerCallbacks();
1040     }
1041 }
1042
1043 void Frame::deviceOrPageScaleFactorChanged()
1044 {
1045     for (RefPtr<Frame> child = tree().firstChild(); child; child = child->tree().nextSibling())
1046         child->deviceOrPageScaleFactorChanged();
1047
1048     if (RenderView* root = contentRenderer())
1049         root->compositor().deviceOrPageScaleFactorChanged();
1050 }
1051
1052 bool Frame::isURLAllowed(const URL& url) const
1053 {
1054     // We allow one level of self-reference because some sites depend on that,
1055     // but we don't allow more than one.
1056     if (m_page->subframeCount() >= Page::maxNumberOfFrames)
1057         return false;
1058     bool foundSelfReference = false;
1059     for (const Frame* frame = this; frame; frame = frame->tree().parent()) {
1060         if (equalIgnoringFragmentIdentifier(frame->document()->url(), url)) {
1061             if (foundSelfReference)
1062                 return false;
1063             foundSelfReference = true;
1064         }
1065     }
1066     return true;
1067 }
1068
1069 } // namespace WebCore