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