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