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