Drop FrameLoaderClient::sessionID()
[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-2019 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 "HTMLFormControlElement.h"
61 #include "HTMLFormElement.h"
62 #include "HTMLFrameElementBase.h"
63 #include "HTMLNames.h"
64 #include "HTMLTableCellElement.h"
65 #include "HTMLTableRowElement.h"
66 #include "HitTestResult.h"
67 #include "ImageBuffer.h"
68 #include "InspectorInstrumentation.h"
69 #include "JSWindowProxy.h"
70 #include "Logging.h"
71 #include "NavigationScheduler.h"
72 #include "Navigator.h"
73 #include "NodeList.h"
74 #include "NodeTraversal.h"
75 #include "Page.h"
76 #include "PageCache.h"
77 #include "ProcessWarming.h"
78 #include "RenderLayerCompositor.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 "SVGDocument.h"
87 #include "SVGDocumentExtensions.h"
88 #include "ScriptController.h"
89 #include "ScriptSourceCode.h"
90 #include "ScrollingCoordinator.h"
91 #include "Settings.h"
92 #include "StyleProperties.h"
93 #include "StyleScope.h"
94 #include "TextNodeTraversal.h"
95 #include "TextResourceDecoder.h"
96 #include "UserContentController.h"
97 #include "UserContentURLPattern.h"
98 #include "UserGestureIndicator.h"
99 #include "UserScript.h"
100 #include "UserTypingGestureIndicator.h"
101 #include "VisibleUnits.h"
102 #include "markup.h"
103 #include "npruntime_impl.h"
104 #include "runtime_root.h"
105 #include <JavaScriptCore/RegularExpression.h>
106 #include <wtf/RefCountedLeakCounter.h>
107 #include <wtf/StdLibExtras.h>
108 #include <wtf/text/StringBuilder.h>
109
110 namespace WebCore {
111
112 using namespace HTMLNames;
113
114 #if PLATFORM(IOS_FAMILY)
115 static const Seconds scrollFrequency { 1000_s / 60. };
116 #endif
117
118 DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, frameCounter, ("Frame"));
119
120 // We prewarm local storage for at most 5 origins in a given page.
121 static const unsigned maxlocalStoragePrewarmingCount { 5 };
122
123 static inline Frame* parentFromOwnerElement(HTMLFrameOwnerElement* ownerElement)
124 {
125     if (!ownerElement)
126         return 0;
127     return ownerElement->document().frame();
128 }
129
130 static inline float parentPageZoomFactor(Frame* frame)
131 {
132     Frame* parent = frame->tree().parent();
133     if (!parent)
134         return 1;
135     return parent->pageZoomFactor();
136 }
137
138 static inline float parentTextZoomFactor(Frame* frame)
139 {
140     Frame* parent = frame->tree().parent();
141     if (!parent)
142         return 1;
143     return parent->textZoomFactor();
144 }
145
146 Frame::Frame(Page& page, HTMLFrameOwnerElement* ownerElement, FrameLoaderClient& frameLoaderClient)
147     : m_mainFrame(ownerElement ? page.mainFrame() : *this)
148     , m_page(&page)
149     , m_settings(&page.settings())
150     , m_treeNode(*this, parentFromOwnerElement(ownerElement))
151     , m_loader(makeUniqueRef<FrameLoader>(*this, frameLoaderClient))
152     , m_navigationScheduler(makeUniqueRef<NavigationScheduler>(*this))
153     , m_ownerElement(ownerElement)
154     , m_script(makeUniqueRef<ScriptController>(*this))
155     , m_editor(makeUniqueRef<Editor>(*this))
156     , m_selection(makeUniqueRef<FrameSelection>(this))
157     , m_animationController(makeUniqueRef<CSSAnimationController>(*this))
158     , m_pageZoomFactor(parentPageZoomFactor(this))
159     , m_textZoomFactor(parentTextZoomFactor(this))
160     , m_eventHandler(makeUniqueRef<EventHandler>(*this))
161 {
162     ProcessWarming::initializeNames();
163
164     if (ownerElement) {
165         m_mainFrame.selfOnlyRef();
166         page.incrementSubframeCount();
167         ownerElement->setContentFrame(this);
168     }
169
170 #ifndef NDEBUG
171     frameCounter.increment();
172 #endif
173
174     // Pause future ActiveDOMObjects if this frame is being created while the page is in a paused state.
175     Frame* parent = parentFromOwnerElement(ownerElement);
176     if (parent && parent->activeDOMObjectsAndAnimationsSuspended())
177         suspendActiveDOMObjectsAndAnimations();
178 }
179
180 void Frame::init()
181 {
182     m_loader->init();
183 }
184
185 Ref<Frame> Frame::create(Page* page, HTMLFrameOwnerElement* ownerElement, FrameLoaderClient* client)
186 {
187     ASSERT(page);
188     ASSERT(client);
189     return adoptRef(*new Frame(*page, ownerElement, *client));
190 }
191
192 Frame::~Frame()
193 {
194     setView(nullptr);
195     loader().cancelAndClear();
196
197     // FIXME: We should not be doing all this work inside the destructor
198
199 #ifndef NDEBUG
200     frameCounter.decrement();
201 #endif
202
203     disconnectOwnerElement();
204
205     while (auto* destructionObserver = m_destructionObservers.takeAny())
206         destructionObserver->frameDestroyed();
207
208     if (!isMainFrame())
209         m_mainFrame.selfOnlyDeref();
210 }
211
212 void Frame::addDestructionObserver(FrameDestructionObserver* observer)
213 {
214     m_destructionObservers.add(observer);
215 }
216
217 void Frame::removeDestructionObserver(FrameDestructionObserver* observer)
218 {
219     m_destructionObservers.remove(observer);
220 }
221
222 void Frame::setView(RefPtr<FrameView>&& view)
223 {
224     // We the custom scroll bars as early as possible to prevent m_doc->detach()
225     // from messing with the view such that its scroll bars won't be torn down.
226     // FIXME: We should revisit this.
227     if (m_view)
228         m_view->prepareForDetach();
229
230     // Prepare for destruction now, so any unload event handlers get run and the DOMWindow is
231     // notified. If we wait until the view is destroyed, then things won't be hooked up enough for
232     // these calls to work.
233     if (!view && m_doc && m_doc->pageCacheState() != Document::InPageCache)
234         m_doc->prepareForDestruction();
235     
236     if (m_view)
237         m_view->layoutContext().unscheduleLayout();
238     
239     m_eventHandler->clear();
240
241     RELEASE_ASSERT(!m_doc || !m_doc->hasLivingRenderTree());
242
243     m_view = WTFMove(view);
244     
245     // Only one form submission is allowed per view of a part.
246     // Since this part may be getting reused as a result of being
247     // pulled from the back/forward cache, reset this flag.
248     loader().resetMultipleFormSubmissionProtection();
249 }
250
251 void Frame::setDocument(RefPtr<Document>&& newDocument)
252 {
253     ASSERT(!newDocument || newDocument->frame() == this);
254
255     if (m_documentIsBeingReplaced)
256         return;
257
258     m_documentIsBeingReplaced = true;
259
260     if (isMainFrame()) {
261         if (m_page)
262             m_page->didChangeMainDocument();
263         m_loader->client().dispatchDidChangeMainDocument();
264
265         // We want to generate the same unique names whenever a page is loaded to avoid making layout tests
266         // flaky and for things like form state restoration to work. To achieve this, we reset our frame
267         // identifier generator every time the page is navigated.
268         tree().resetFrameIdentifiers();
269     }
270
271 #if ENABLE(ATTACHMENT_ELEMENT)
272     if (m_doc) {
273         for (auto& attachment : m_doc->attachmentElementsByIdentifier().values())
274             editor().didRemoveAttachmentElement(attachment);
275     }
276 #endif
277
278     if (m_doc && m_doc->pageCacheState() != Document::InPageCache)
279         m_doc->prepareForDestruction();
280
281     m_doc = newDocument.copyRef();
282     ASSERT(!m_doc || m_doc->domWindow());
283     ASSERT(!m_doc || m_doc->domWindow()->frame() == this);
284
285     // Don't use m_doc because it can be overwritten and we want to guarantee
286     // that the document is not destroyed during this function call.
287     if (newDocument)
288         newDocument->didBecomeCurrentDocumentInFrame();
289
290 #if ENABLE(ATTACHMENT_ELEMENT)
291     if (m_doc) {
292         for (auto& attachment : m_doc->attachmentElementsByIdentifier().values())
293             editor().didInsertAttachmentElement(attachment);
294     }
295 #endif
296
297     InspectorInstrumentation::frameDocumentUpdated(*this);
298
299     m_documentIsBeingReplaced = false;
300 }
301
302 #if ENABLE(ORIENTATION_EVENTS)
303 void Frame::orientationChanged()
304 {
305     Vector<Ref<Frame>> frames;
306     for (Frame* frame = this; frame; frame = frame->tree().traverseNext())
307         frames.append(*frame);
308
309     auto newOrientation = orientation();
310     for (auto& frame : frames) {
311         if (Document* document = frame->document())
312             document->orientationChanged(newOrientation);
313     }
314 }
315
316 int Frame::orientation() const
317 {
318     if (m_page)
319         return m_page->chrome().client().deviceOrientation();
320     return 0;
321 }
322 #endif // ENABLE(ORIENTATION_EVENTS)
323
324 static JSC::Yarr::RegularExpression createRegExpForLabels(const Vector<String>& labels)
325 {
326     // REVIEW- version of this call in FrameMac.mm caches based on the NSArray ptrs being
327     // the same across calls.  We can't do that.
328
329     static NeverDestroyed<JSC::Yarr::RegularExpression> wordRegExp("\\w");
330     StringBuilder pattern;
331     pattern.append('(');
332     unsigned int numLabels = labels.size();
333     unsigned int i;
334     for (i = 0; i < numLabels; i++) {
335         String label = labels[i];
336
337         bool startsWithWordChar = false;
338         bool endsWithWordChar = false;
339         if (label.length()) {
340             startsWithWordChar = wordRegExp.get().match(label.substring(0, 1)) >= 0;
341             endsWithWordChar = wordRegExp.get().match(label.substring(label.length() - 1, 1)) >= 0;
342         }
343
344         if (i)
345             pattern.append('|');
346         // Search for word boundaries only if label starts/ends with "word characters".
347         // If we always searched for word boundaries, this wouldn't work for languages
348         // such as Japanese.
349         if (startsWithWordChar)
350             pattern.appendLiteral("\\b");
351         pattern.append(label);
352         if (endsWithWordChar)
353             pattern.appendLiteral("\\b");
354     }
355     pattern.append(')');
356     return JSC::Yarr::RegularExpression(pattern.toString(), JSC::Yarr::TextCaseInsensitive);
357 }
358
359 String Frame::searchForLabelsAboveCell(const JSC::Yarr::RegularExpression& regExp, HTMLTableCellElement* cell, size_t* resultDistanceFromStartOfCell)
360 {
361     HTMLTableCellElement* aboveCell = cell->cellAbove();
362     if (aboveCell) {
363         // search within the above cell we found for a match
364         size_t lengthSearched = 0;    
365         for (Text* textNode = TextNodeTraversal::firstWithin(*aboveCell); textNode; textNode = TextNodeTraversal::next(*textNode, aboveCell)) {
366             if (!textNode->renderer() || textNode->renderer()->style().visibility() != Visibility::Visible)
367                 continue;
368             // For each text chunk, run the regexp
369             String nodeString = textNode->data();
370             int pos = regExp.searchRev(nodeString);
371             if (pos >= 0) {
372                 if (resultDistanceFromStartOfCell)
373                     *resultDistanceFromStartOfCell = lengthSearched;
374                 return nodeString.substring(pos, regExp.matchedLength());
375             }
376             lengthSearched += nodeString.length();
377         }
378     }
379
380     // Any reason in practice to search all cells in that are above cell?
381     if (resultDistanceFromStartOfCell)
382         *resultDistanceFromStartOfCell = notFound;
383     return String();
384 }
385
386 // FIXME: This should take an Element&.
387 String Frame::searchForLabelsBeforeElement(const Vector<String>& labels, Element* element, size_t* resultDistance, bool* resultIsInCellAbove)
388 {
389     ASSERT(element);
390     JSC::Yarr::RegularExpression regExp = createRegExpForLabels(labels);
391     // We stop searching after we've seen this many chars
392     const unsigned int charsSearchedThreshold = 500;
393     // This is the absolute max we search.  We allow a little more slop than
394     // charsSearchedThreshold, to make it more likely that we'll search whole nodes.
395     const unsigned int maxCharsSearched = 600;
396     // If the starting element is within a table, the cell that contains it
397     HTMLTableCellElement* startingTableCell = nullptr;
398     bool searchedCellAbove = false;
399
400     if (resultDistance)
401         *resultDistance = notFound;
402     if (resultIsInCellAbove)
403         *resultIsInCellAbove = false;
404     
405     // walk backwards in the node tree, until another element, or form, or end of tree
406     int unsigned lengthSearched = 0;
407     Node* n;
408     for (n = NodeTraversal::previous(*element); n && lengthSearched < charsSearchedThreshold; n = NodeTraversal::previous(*n)) {
409         // We hit another form element or the start of the form - bail out
410         if (is<HTMLFormElement>(*n) || is<HTMLFormControlElement>(*n))
411             break;
412
413         if (n->hasTagName(tdTag) && !startingTableCell)
414             startingTableCell = downcast<HTMLTableCellElement>(n);
415         else if (is<HTMLTableRowElement>(*n) && startingTableCell) {
416             String result = searchForLabelsAboveCell(regExp, startingTableCell, resultDistance);
417             if (!result.isEmpty()) {
418                 if (resultIsInCellAbove)
419                     *resultIsInCellAbove = true;
420                 return result;
421             }
422             searchedCellAbove = true;
423         } else if (n->isTextNode() && n->renderer() && n->renderer()->style().visibility() == Visibility::Visible) {
424             // For each text chunk, run the regexp
425             String nodeString = n->nodeValue();
426             // add 100 for slop, to make it more likely that we'll search whole nodes
427             if (lengthSearched + nodeString.length() > maxCharsSearched)
428                 nodeString = nodeString.right(charsSearchedThreshold - lengthSearched);
429             int pos = regExp.searchRev(nodeString);
430             if (pos >= 0) {
431                 if (resultDistance)
432                     *resultDistance = lengthSearched;
433                 return nodeString.substring(pos, regExp.matchedLength());
434             }
435             lengthSearched += nodeString.length();
436         }
437     }
438
439     // If we started in a cell, but bailed because we found the start of the form or the
440     // previous element, we still might need to search the row above us for a label.
441     if (startingTableCell && !searchedCellAbove) {
442         String result = searchForLabelsAboveCell(regExp, startingTableCell, resultDistance);
443         if (!result.isEmpty()) {
444             if (resultIsInCellAbove)
445                 *resultIsInCellAbove = true;
446             return result;
447         }
448     }
449     return String();
450 }
451
452 static String matchLabelsAgainstString(const Vector<String>& labels, const String& stringToMatch)
453 {
454     if (stringToMatch.isEmpty())
455         return String();
456
457     String mutableStringToMatch = stringToMatch;
458
459     // Make numbers and _'s in field names behave like word boundaries, e.g., "address2"
460     replace(mutableStringToMatch, JSC::Yarr::RegularExpression("\\d"), " ");
461     mutableStringToMatch.replace('_', ' ');
462     
463     JSC::Yarr::RegularExpression regExp = createRegExpForLabels(labels);
464     // Use the largest match we can find in the whole string
465     int pos;
466     int length;
467     int bestPos = -1;
468     int bestLength = -1;
469     int start = 0;
470     do {
471         pos = regExp.match(mutableStringToMatch, start);
472         if (pos != -1) {
473             length = regExp.matchedLength();
474             if (length >= bestLength) {
475                 bestPos = pos;
476                 bestLength = length;
477             }
478             start = pos + 1;
479         }
480     } while (pos != -1);
481     
482     if (bestPos != -1)
483         return mutableStringToMatch.substring(bestPos, bestLength);
484     return String();
485 }
486     
487 String Frame::matchLabelsAgainstElement(const Vector<String>& labels, Element* element)
488 {
489     // Match against the name element, then against the id element if no match is found for the name element.
490     // See 7538330 for one popular site that benefits from the id element check.
491     // FIXME: This code is mirrored in FrameMac.mm. It would be nice to make the Mac code call the platform-agnostic
492     // code, which would require converting the NSArray of NSStrings to a Vector of Strings somewhere along the way.
493     String resultFromNameAttribute = matchLabelsAgainstString(labels, element->getNameAttribute());
494     if (!resultFromNameAttribute.isEmpty())
495         return resultFromNameAttribute;
496     
497     return matchLabelsAgainstString(labels, element->attributeWithoutSynchronization(idAttr));
498 }
499
500 #if PLATFORM(IOS_FAMILY)
501
502 void Frame::setSelectionChangeCallbacksDisabled(bool selectionChangeCallbacksDisabled)
503 {
504     m_selectionChangeCallbacksDisabled = selectionChangeCallbacksDisabled;
505 }
506
507 bool Frame::selectionChangeCallbacksDisabled() const
508 {
509     return m_selectionChangeCallbacksDisabled;
510 }
511 #endif // PLATFORM(IOS_FAMILY)
512
513 bool Frame::requestDOMPasteAccess()
514 {
515     if (m_settings->javaScriptCanAccessClipboard() && m_settings->DOMPasteAllowed())
516         return true;
517
518     if (!m_settings->domPasteAccessRequestsEnabled() || !m_doc)
519         return false;
520
521     auto gestureToken = UserGestureIndicator::currentUserGesture();
522     if (!gestureToken || !gestureToken->processingUserGesture())
523         return false;
524
525     switch (gestureToken->domPasteAccessPolicy()) {
526     case DOMPasteAccessPolicy::Granted:
527         return true;
528     case DOMPasteAccessPolicy::Denied:
529         return false;
530     case DOMPasteAccessPolicy::NotRequestedYet: {
531         auto* client = m_editor->client();
532         if (!client)
533             return false;
534
535         auto response = client->requestDOMPasteAccess(m_doc->originIdentifierForPasteboard());
536         gestureToken->didRequestDOMPasteAccess(response);
537         switch (response) {
538         case DOMPasteAccessResponse::GrantedForCommand:
539         case DOMPasteAccessResponse::GrantedForGesture:
540             return true;
541         case DOMPasteAccessResponse::DeniedForGesture:
542             return false;
543         }
544     }
545     }
546
547     ASSERT_NOT_REACHED();
548     return false;
549 }
550
551 void Frame::setPrinting(bool printing, const FloatSize& pageSize, const FloatSize& originalPageSize, float maximumShrinkRatio, AdjustViewSizeOrNot shouldAdjustViewSize)
552 {
553     if (!view())
554         return;
555     // In setting printing, we should not validate resources already cached for the document.
556     // See https://bugs.webkit.org/show_bug.cgi?id=43704
557     ResourceCacheValidationSuppressor validationSuppressor(m_doc->cachedResourceLoader());
558
559     m_doc->setPrinting(printing);
560     auto& frameView = *view();
561     frameView.adjustMediaTypeForPrinting(printing);
562
563     m_doc->styleScope().didChangeStyleSheetEnvironment();
564     if (shouldUsePrintingLayout())
565         frameView.forceLayoutForPagination(pageSize, originalPageSize, maximumShrinkRatio, shouldAdjustViewSize);
566     else {
567         frameView.forceLayout();
568         if (shouldAdjustViewSize == AdjustViewSize)
569             frameView.adjustViewSize();
570     }
571
572     // Subframes of the one we're printing don't lay out to the page size.
573     for (RefPtr<Frame> child = tree().firstChild(); child; child = child->tree().nextSibling())
574         child->setPrinting(printing, FloatSize(), FloatSize(), 0, shouldAdjustViewSize);
575 }
576
577 bool Frame::shouldUsePrintingLayout() const
578 {
579     // Only top frame being printed should be fit to page size.
580     // Subframes should be constrained by parents only.
581     return m_doc->printing() && (!tree().parent() || !tree().parent()->m_doc->printing());
582 }
583
584 FloatSize Frame::resizePageRectsKeepingRatio(const FloatSize& originalSize, const FloatSize& expectedSize)
585 {
586     FloatSize resultSize;
587     if (!contentRenderer())
588         return FloatSize();
589
590     if (contentRenderer()->style().isHorizontalWritingMode()) {
591         ASSERT(fabs(originalSize.width()) > std::numeric_limits<float>::epsilon());
592         float ratio = originalSize.height() / originalSize.width();
593         resultSize.setWidth(floorf(expectedSize.width()));
594         resultSize.setHeight(floorf(resultSize.width() * ratio));
595     } else {
596         ASSERT(fabs(originalSize.height()) > std::numeric_limits<float>::epsilon());
597         float ratio = originalSize.width() / originalSize.height();
598         resultSize.setHeight(floorf(expectedSize.height()));
599         resultSize.setWidth(floorf(resultSize.height() * ratio));
600     }
601     return resultSize;
602 }
603
604 void Frame::injectUserScripts(UserScriptInjectionTime injectionTime)
605 {
606     if (!m_page)
607         return;
608
609     if (loader().stateMachine().creatingInitialEmptyDocument() && !settings().shouldInjectUserScriptsInInitialEmptyDocument())
610         return;
611
612     m_page->userContentProvider().forEachUserScript([this, protectedThis = makeRef(*this), injectionTime](DOMWrapperWorld& world, const UserScript& script) {
613         if (script.injectionTime() == injectionTime)
614             injectUserScriptImmediately(world, script);
615     });
616 }
617
618 void Frame::injectUserScriptImmediately(DOMWrapperWorld& world, const UserScript& script)
619 {
620     auto* document = this->document();
621     if (!document)
622         return;
623     if (script.injectedFrames() == InjectInTopFrameOnly && !isMainFrame())
624         return;
625     if (!UserContentURLPattern::matchesPatterns(document->url(), script.whitelist(), script.blacklist()))
626         return;
627     if (!m_script->shouldAllowUserAgentScripts(*document))
628         return;
629
630     document->setAsRunningUserScripts();
631     loader().client().willInjectUserScript(world);
632     m_script->evaluateInWorld(ScriptSourceCode(script.source(), URL(script.url())), world);
633 }
634
635 RenderView* Frame::contentRenderer() const
636 {
637     return document() ? document()->renderView() : nullptr;
638 }
639
640 RenderWidget* Frame::ownerRenderer() const
641 {
642     auto* ownerElement = m_ownerElement;
643     if (!ownerElement)
644         return nullptr;
645     auto* object = ownerElement->renderer();
646     // FIXME: If <object> is ever fixed to disassociate itself from frames
647     // that it has started but canceled, then this can turn into an ASSERT
648     // since m_ownerElement would be nullptr when the load is canceled.
649     // https://bugs.webkit.org/show_bug.cgi?id=18585
650     if (!is<RenderWidget>(object))
651         return nullptr;
652     return downcast<RenderWidget>(object);
653 }
654
655 Frame* Frame::frameForWidget(const Widget& widget)
656 {
657     if (auto* renderer = RenderWidget::find(widget))
658         return renderer->frameOwnerElement().document().frame();
659
660     // Assume all widgets are either a FrameView or owned by a RenderWidget.
661     // FIXME: That assumption is not right for scroll bars!
662     return &downcast<FrameView>(widget).frame();
663 }
664
665 void Frame::clearTimers(FrameView *view, Document *document)
666 {
667     if (view) {
668         view->layoutContext().unscheduleLayout();
669         if (RuntimeEnabledFeatures::sharedFeatures().webAnimationsCSSIntegrationEnabled()) {
670             if (auto* timeline = document->existingTimeline())
671                 timeline->suspendAnimations();
672         } else
673             view->frame().animation().suspendAnimationsForDocument(document);
674         view->frame().eventHandler().stopAutoscrollTimer();
675     }
676 }
677
678 void Frame::clearTimers()
679 {
680     clearTimers(m_view.get(), document());
681 }
682
683 void Frame::willDetachPage()
684 {
685     if (Frame* parent = tree().parent())
686         parent->loader().checkLoadComplete();
687
688     for (auto& observer : m_destructionObservers)
689         observer->willDetachPage();
690
691     // FIXME: It's unclear as to why this is called more than once, but it is,
692     // so page() could be NULL.
693     if (page() && page()->focusController().focusedFrame() == this)
694         page()->focusController().setFocusedFrame(nullptr);
695
696     if (page() && page()->scrollingCoordinator() && m_view)
697         page()->scrollingCoordinator()->willDestroyScrollableArea(*m_view);
698
699     script().clearScriptObjects();
700     script().updatePlatformScriptObjects();
701
702     // We promise that the Frame is always connected to a Page while the render tree is live.
703     //
704     // The render tree can be torn down in a few different ways, but the two important ones are:
705     //
706     // - When calling Frame::setView() with a null FrameView*. This is always done before calling
707     //   Frame::willDetachPage (this function.) Hence the assertion below.
708     //
709     // - When adding a document to the page cache, the tree is torn down before instantiating
710     //   the CachedPage+CachedFrame object tree.
711     ASSERT(!document() || !document()->renderView());
712 }
713
714 void Frame::disconnectOwnerElement()
715 {
716     if (m_ownerElement) {
717         m_ownerElement->clearContentFrame();
718         if (m_page)
719             m_page->decrementSubframeCount();
720     }
721     m_ownerElement = nullptr;
722
723     if (auto* document = this->document())
724         document->frameWasDisconnectedFromOwner();
725 }
726
727 String Frame::displayStringModifiedByEncoding(const String& str) const
728 {
729     return document() ? document()->displayStringModifiedByEncoding(str) : str;
730 }
731
732 VisiblePosition Frame::visiblePositionForPoint(const IntPoint& framePoint) const
733 {
734     HitTestResult result = eventHandler().hitTestResultAtPoint(framePoint, HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::AllowChildFrameContent);
735     Node* node = result.innerNonSharedNode();
736     if (!node)
737         return VisiblePosition();
738     auto renderer = node->renderer();
739     if (!renderer)
740         return VisiblePosition();
741     VisiblePosition visiblePos = renderer->positionForPoint(result.localPoint(), nullptr);
742     if (visiblePos.isNull())
743         visiblePos = firstPositionInOrBeforeNode(node);
744     return visiblePos;
745 }
746
747 Document* Frame::documentAtPoint(const IntPoint& point)
748 {
749     if (!view())
750         return nullptr;
751
752     IntPoint pt = view()->windowToContents(point);
753     HitTestResult result = HitTestResult(pt);
754
755     if (contentRenderer())
756         result = eventHandler().hitTestResultAtPoint(pt, HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::DisallowUserAgentShadowContent | HitTestRequest::AllowChildFrameContent);
757     return result.innerNode() ? &result.innerNode()->document() : 0;
758 }
759
760 RefPtr<Range> Frame::rangeForPoint(const IntPoint& framePoint)
761 {
762     VisiblePosition position = visiblePositionForPoint(framePoint);
763     if (position.isNull())
764         return nullptr;
765
766     Position deepPosition = position.deepEquivalent();
767     Text* containerText = deepPosition.containerText();
768     if (!containerText || !containerText->renderer() || containerText->renderer()->style().userSelect() == UserSelect::None)
769         return nullptr;
770
771     VisiblePosition previous = position.previous();
772     if (previous.isNotNull()) {
773         RefPtr<Range> previousCharacterRange = makeRange(previous, position);
774         LayoutRect rect = editor().firstRectForRange(previousCharacterRange.get());
775         if (rect.contains(framePoint))
776             return previousCharacterRange;
777     }
778
779     VisiblePosition next = position.next();
780     if (RefPtr<Range> nextCharacterRange = makeRange(position, next)) {
781         LayoutRect rect = editor().firstRectForRange(nextCharacterRange.get());
782         if (rect.contains(framePoint))
783             return nextCharacterRange;
784     }
785
786     return nullptr;
787 }
788
789 void Frame::createView(const IntSize& viewportSize, const Optional<Color>& backgroundColor,
790     const IntSize& fixedLayoutSize, const IntRect& fixedVisibleContentRect,
791     bool useFixedLayout, ScrollbarMode horizontalScrollbarMode, bool horizontalLock,
792     ScrollbarMode verticalScrollbarMode, bool verticalLock)
793 {
794     ASSERT(m_page);
795
796     bool isMainFrame = this->isMainFrame();
797
798     if (isMainFrame && view())
799         view()->setParentVisible(false);
800
801     setView(nullptr);
802
803     RefPtr<FrameView> frameView;
804     if (isMainFrame) {
805         frameView = FrameView::create(*this, viewportSize);
806         frameView->setFixedLayoutSize(fixedLayoutSize);
807 #if USE(COORDINATED_GRAPHICS)
808         frameView->setFixedVisibleContentRect(fixedVisibleContentRect);
809 #else
810         UNUSED_PARAM(fixedVisibleContentRect);
811 #endif
812         frameView->setUseFixedLayout(useFixedLayout);
813     } else
814         frameView = FrameView::create(*this);
815
816     frameView->setScrollbarModes(horizontalScrollbarMode, verticalScrollbarMode, horizontalLock, verticalLock);
817
818     setView(frameView.copyRef());
819
820     frameView->updateBackgroundRecursively(backgroundColor);
821
822     if (isMainFrame)
823         frameView->setParentVisible(true);
824
825     if (ownerRenderer())
826         ownerRenderer()->setWidget(frameView);
827
828     if (HTMLFrameOwnerElement* owner = ownerElement())
829         view()->setCanHaveScrollbars(owner->scrollingMode() != ScrollbarAlwaysOff);
830 }
831
832 DOMWindow* Frame::window() const
833 {
834     return document() ? document()->domWindow() : nullptr;
835 }
836
837 AbstractDOMWindow* Frame::virtualWindow() const
838 {
839     return window();
840 }
841
842 String Frame::layerTreeAsText(LayerTreeFlags flags) const
843 {
844     document()->updateLayout();
845
846     if (!contentRenderer())
847         return String();
848
849     return contentRenderer()->compositor().layerTreeAsText(flags);
850 }
851
852 String Frame::trackedRepaintRectsAsText() const
853 {
854     if (!m_view)
855         return String();
856     return m_view->trackedRepaintRectsAsText();
857 }
858
859 void Frame::setPageZoomFactor(float factor)
860 {
861     setPageAndTextZoomFactors(factor, m_textZoomFactor);
862 }
863
864 void Frame::setTextZoomFactor(float factor)
865 {
866     setPageAndTextZoomFactors(m_pageZoomFactor, factor);
867 }
868
869 void Frame::setPageAndTextZoomFactors(float pageZoomFactor, float textZoomFactor)
870 {
871     if (m_pageZoomFactor == pageZoomFactor && m_textZoomFactor == textZoomFactor)
872         return;
873
874     Page* page = this->page();
875     if (!page)
876         return;
877
878     Document* document = this->document();
879     if (!document)
880         return;
881
882     m_editor->dismissCorrectionPanelAsIgnored();
883
884     // Respect SVGs zoomAndPan="disabled" property in standalone SVG documents.
885     // FIXME: How to handle compound documents + zoomAndPan="disabled"? Needs SVG WG clarification.
886     if (is<SVGDocument>(*document) && !downcast<SVGDocument>(*document).zoomAndPanEnabled())
887         return;
888
889     if (m_pageZoomFactor != pageZoomFactor) {
890         if (FrameView* view = this->view()) {
891             // Update the scroll position when doing a full page zoom, so the content stays in relatively the same position.
892             LayoutPoint scrollPosition = view->scrollPosition();
893             float percentDifference = (pageZoomFactor / m_pageZoomFactor);
894             view->setScrollPosition(IntPoint(scrollPosition.x() * percentDifference, scrollPosition.y() * percentDifference));
895         }
896     }
897
898     m_pageZoomFactor = pageZoomFactor;
899     m_textZoomFactor = textZoomFactor;
900
901     document->resolveStyle(Document::ResolveStyleType::Rebuild);
902
903     for (RefPtr<Frame> child = tree().firstChild(); child; child = child->tree().nextSibling())
904         child->setPageAndTextZoomFactors(m_pageZoomFactor, m_textZoomFactor);
905
906     if (FrameView* view = this->view()) {
907         if (document->renderView() && document->renderView()->needsLayout() && view->didFirstLayout())
908             view->layoutContext().layout();
909     }
910 }
911
912 float Frame::frameScaleFactor() const
913 {
914     Page* page = this->page();
915
916     // Main frame is scaled with respect to he container but inner frames are not scaled with respect to the main frame.
917     if (!page || &page->mainFrame() != this || settings().delegatesPageScaling())
918         return 1;
919
920     return page->pageScaleFactor();
921 }
922
923 void Frame::suspendActiveDOMObjectsAndAnimations()
924 {
925     bool wasSuspended = activeDOMObjectsAndAnimationsSuspended();
926
927     m_activeDOMObjectsAndAnimationsSuspendedCount++;
928
929     if (wasSuspended)
930         return;
931
932     // FIXME: Suspend/resume calls will not match if the frame is navigated, and gets a new document.
933     clearTimers(); // Suspends animations and pending relayouts.
934     if (m_doc)
935         m_doc->suspendScheduledTasks(ReasonForSuspension::PageWillBeSuspended);
936 }
937
938 void Frame::resumeActiveDOMObjectsAndAnimations()
939 {
940     if (!activeDOMObjectsAndAnimationsSuspended())
941         return;
942
943     m_activeDOMObjectsAndAnimationsSuspendedCount--;
944
945     if (activeDOMObjectsAndAnimationsSuspended())
946         return;
947
948     if (!m_doc)
949         return;
950
951     // FIXME: Suspend/resume calls will not match if the frame is navigated, and gets a new document.
952     m_doc->resumeScheduledTasks(ReasonForSuspension::PageWillBeSuspended);
953
954     // Frame::clearTimers() suspended animations and pending relayouts.
955     animation().resumeAnimationsForDocument(m_doc.get());
956     if (m_view)
957         m_view->layoutContext().scheduleLayout();
958 }
959
960 void Frame::deviceOrPageScaleFactorChanged()
961 {
962     for (RefPtr<Frame> child = tree().firstChild(); child; child = child->tree().nextSibling())
963         child->deviceOrPageScaleFactorChanged();
964
965     if (RenderView* root = contentRenderer())
966         root->compositor().deviceOrPageScaleFactorChanged();
967 }
968
969 bool Frame::isAlwaysOnLoggingAllowed() const
970 {
971     return page() && page()->isAlwaysOnLoggingAllowed();
972 }
973
974 void Frame::dropChildren()
975 {
976     ASSERT(isMainFrame());
977     while (Frame* child = tree().firstChild())
978         tree().removeChild(*child);
979 }
980
981 void Frame::didPrewarmLocalStorage()
982 {
983     ASSERT(isMainFrame());
984     ASSERT(m_localStoragePrewarmingCount < maxlocalStoragePrewarmingCount);
985     ++m_localStoragePrewarmingCount;
986 }
987
988 bool Frame::mayPrewarmLocalStorage() const
989 {
990     ASSERT(isMainFrame());
991     return m_localStoragePrewarmingCount < maxlocalStoragePrewarmingCount;
992 }
993
994 void Frame::selfOnlyRef()
995 {
996     ASSERT(isMainFrame());
997     if (m_selfOnlyRefCount++)
998         return;
999
1000     ref();
1001 }
1002
1003 void Frame::selfOnlyDeref()
1004 {
1005     ASSERT(isMainFrame());
1006     ASSERT(m_selfOnlyRefCount);
1007     if (--m_selfOnlyRefCount)
1008         return;
1009
1010     if (hasOneRef())
1011         dropChildren();
1012
1013     deref();
1014 }
1015
1016 PAL::SessionID Frame::sessionID() const
1017 {
1018     auto* page = this->page();
1019     return page ? page->sessionID() : PAL::SessionID::defaultSessionID();
1020 }
1021
1022 } // namespace WebCore