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.
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.
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.
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.
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"
41 #include "ChromeClient.h"
42 #include "DOMWindow.h"
43 #include "DocumentType.h"
45 #include "EditorClient.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"
69 #include "MainFrame.h"
70 #include "MathMLNames.h"
71 #include "MediaFeatureNames.h"
72 #include "Navigator.h"
74 #include "NodeTraversal.h"
76 #include "PageCache.h"
77 #include "PageGroup.h"
78 #include "RegularExpression.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"
87 #include "ScriptController.h"
88 #include "ScriptSourceCode.h"
89 #include "ScrollingCoordinator.h"
91 #include "StyleProperties.h"
92 #include "TextIterator.h"
93 #include "TextNodeTraversal.h"
94 #include "TextResourceDecoder.h"
95 #include "UserContentURLPattern.h"
96 #include "UserTypingGestureIndicator.h"
97 #include "VisibleUnits.h"
98 #include "WebKitFontFamilyNames.h"
99 #include "XLinkNames.h"
100 #include "XMLNSNames.h"
101 #include "XMLNames.h"
102 #include "htmlediting.h"
104 #include "npruntime_impl.h"
105 #include "runtime_root.h"
106 #include <bindings/ScriptValue.h>
107 #include <wtf/PassOwnPtr.h>
108 #include <wtf/RefCountedLeakCounter.h>
109 #include <wtf/StdLibExtras.h>
111 #if USE(ACCELERATED_COMPOSITING)
112 #include "RenderLayerCompositor.h"
116 #include "SVGDocument.h"
117 #include "SVGDocumentExtensions.h"
120 #if USE(TILED_BACKING_STORE)
121 #include "TiledBackingStore.h"
126 using namespace HTMLNames;
128 DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, frameCounter, ("Frame"));
130 static inline Frame* parentFromOwnerElement(HTMLFrameOwnerElement* ownerElement)
134 return ownerElement->document().frame();
137 static inline float parentPageZoomFactor(Frame* frame)
139 Frame* parent = frame->tree().parent();
142 return parent->pageZoomFactor();
145 static inline float parentTextZoomFactor(Frame* frame)
147 Frame* parent = frame->tree().parent();
150 return parent->textZoomFactor();
153 Frame::Frame(Page& page, HTMLFrameOwnerElement* ownerElement, FrameLoaderClient& frameLoaderClient)
154 : m_mainFrame(ownerElement ? page.mainFrame() : static_cast<MainFrame&>(*this))
156 , m_settings(&page.settings())
157 , m_treeNode(this, parentFromOwnerElement(ownerElement))
158 , m_loader(*this, frameLoaderClient)
159 , m_navigationScheduler(this)
160 , m_ownerElement(ownerElement)
161 , m_script(std::make_unique<ScriptController>(*this))
162 , m_editor(Editor::create(*this))
163 , m_selection(adoptPtr(new FrameSelection(this)))
164 , m_eventHandler(adoptPtr(new EventHandler(*this)))
165 , m_animationController(std::make_unique<AnimationController>(*this))
166 , m_pageZoomFactor(parentPageZoomFactor(this))
167 , m_textZoomFactor(parentTextZoomFactor(this))
168 #if ENABLE(ORIENTATION_EVENTS)
171 , m_inViewSourceMode(false)
172 , m_activeDOMObjectsAndAnimationsSuspendedCount(0)
174 AtomicString::init();
176 QualifiedName::init();
177 MediaFeatureNames::init();
183 WebKitFontFamilyNames::init();
186 #if USE(TILED_BACKING_STORE)
187 // Top level frame only for now.
188 setTiledBackingStoreEnabled(settings().tiledBackingStoreEnabled());
191 m_mainFrame.selfOnlyRef();
192 page.incrementSubframeCount();
193 ownerElement->setContentFrame(this);
197 frameCounter.increment();
200 // Pause future ActiveDOMObjects if this frame is being created while the page is in a paused state.
201 Frame* parent = parentFromOwnerElement(ownerElement);
202 if (parent && parent->activeDOMObjectsAndAnimationsSuspended())
203 suspendActiveDOMObjectsAndAnimations();
206 PassRefPtr<Frame> Frame::create(Page* page, HTMLFrameOwnerElement* ownerElement, FrameLoaderClient* client)
210 return adoptRef(new Frame(*page, ownerElement, *client));
216 loader().cancelAndClear();
218 // FIXME: We should not be doing all this work inside the destructor
221 frameCounter.decrement();
224 disconnectOwnerElement();
226 for (auto& observer : m_destructionObservers)
227 observer->frameDestroyed();
230 m_mainFrame.selfOnlyDeref();
233 void Frame::addDestructionObserver(FrameDestructionObserver* observer)
235 m_destructionObservers.add(observer);
238 void Frame::removeDestructionObserver(FrameDestructionObserver* observer)
240 m_destructionObservers.remove(observer);
243 void Frame::setView(PassRefPtr<FrameView> view)
245 // We the custom scroll bars as early as possible to prevent m_doc->detach()
246 // from messing with the view such that its scroll bars won't be torn down.
247 // FIXME: We should revisit this.
249 m_view->prepareForDetach();
251 // Prepare for destruction now, so any unload event handlers get run and the DOMWindow is
252 // notified. If we wait until the view is destroyed, then things won't be hooked up enough for
253 // these calls to work.
254 if (!view && m_doc && m_doc->attached() && !m_doc->inPageCache())
255 m_doc->prepareForDestruction();
258 m_view->unscheduleRelayout();
260 eventHandler().clear();
264 // Only one form submission is allowed per view of a part.
265 // Since this part may be getting reused as a result of being
266 // pulled from the back/forward cache, reset this flag.
267 loader().resetMultipleFormSubmissionProtection();
269 #if USE(TILED_BACKING_STORE)
270 if (m_view && tiledBackingStore())
271 m_view->setPaintsEntireContents(true);
275 void Frame::setDocument(PassRefPtr<Document> newDocument)
277 ASSERT(!newDocument || newDocument->frame() == this);
279 if (m_doc && m_doc->attached() && !m_doc->inPageCache())
280 m_doc->prepareForDestruction();
282 m_doc = newDocument.get();
283 ASSERT(!m_doc || m_doc->domWindow());
284 ASSERT(!m_doc || m_doc->domWindow()->frame() == this);
286 // Don't use m_doc because it can be overwritten and we want to guarantee
287 // that the document is not destroyed during this function call.
289 newDocument->didBecomeCurrentDocumentInFrame();
292 #if ENABLE(ORIENTATION_EVENTS)
293 void Frame::sendOrientationChangeEvent(int orientation)
295 m_orientation = orientation;
296 if (Document* doc = document())
297 doc->dispatchWindowEvent(Event::create(eventNames().orientationchangeEvent, false, false));
299 #endif // ENABLE(ORIENTATION_EVENTS)
301 static PassOwnPtr<RegularExpression> createRegExpForLabels(const Vector<String>& labels)
303 // REVIEW- version of this call in FrameMac.mm caches based on the NSArray ptrs being
304 // the same across calls. We can't do that.
306 DEFINE_STATIC_LOCAL(RegularExpression, wordRegExp, ("\\w", TextCaseSensitive));
308 unsigned int numLabels = labels.size();
310 for (i = 0; i < numLabels; i++) {
311 String label = labels[i];
313 bool startsWithWordChar = false;
314 bool endsWithWordChar = false;
315 if (label.length()) {
316 startsWithWordChar = wordRegExp.match(label.substring(0, 1)) >= 0;
317 endsWithWordChar = wordRegExp.match(label.substring(label.length() - 1, 1)) >= 0;
322 // Search for word boundaries only if label starts/ends with "word characters".
323 // If we always searched for word boundaries, this wouldn't work for languages
325 if (startsWithWordChar)
326 pattern.append("\\b");
327 pattern.append(label);
328 if (endsWithWordChar)
329 pattern.append("\\b");
332 return adoptPtr(new RegularExpression(pattern, TextCaseInsensitive));
335 String Frame::searchForLabelsAboveCell(RegularExpression* regExp, HTMLTableCellElement* cell, size_t* resultDistanceFromStartOfCell)
337 HTMLTableCellElement* aboveCell = cell->cellAbove();
339 // search within the above cell we found for a match
340 size_t lengthSearched = 0;
341 for (Text* textNode = TextNodeTraversal::firstWithin(aboveCell); textNode; textNode = TextNodeTraversal::next(textNode, aboveCell)) {
342 if (!textNode->renderer() || textNode->renderer()->style().visibility() != VISIBLE)
344 // For each text chunk, run the regexp
345 String nodeString = textNode->data();
346 int pos = regExp->searchRev(nodeString);
348 if (resultDistanceFromStartOfCell)
349 *resultDistanceFromStartOfCell = lengthSearched;
350 return nodeString.substring(pos, regExp->matchedLength());
352 lengthSearched += nodeString.length();
356 // Any reason in practice to search all cells in that are above cell?
357 if (resultDistanceFromStartOfCell)
358 *resultDistanceFromStartOfCell = notFound;
362 String Frame::searchForLabelsBeforeElement(const Vector<String>& labels, Element* element, size_t* resultDistance, bool* resultIsInCellAbove)
364 OwnPtr<RegularExpression> regExp(createRegExpForLabels(labels));
365 // We stop searching after we've seen this many chars
366 const unsigned int charsSearchedThreshold = 500;
367 // This is the absolute max we search. We allow a little more slop than
368 // charsSearchedThreshold, to make it more likely that we'll search whole nodes.
369 const unsigned int maxCharsSearched = 600;
370 // If the starting element is within a table, the cell that contains it
371 HTMLTableCellElement* startingTableCell = 0;
372 bool searchedCellAbove = false;
375 *resultDistance = notFound;
376 if (resultIsInCellAbove)
377 *resultIsInCellAbove = false;
379 // walk backwards in the node tree, until another element, or form, or end of tree
380 int unsigned lengthSearched = 0;
382 for (n = NodeTraversal::previous(element); n && lengthSearched < charsSearchedThreshold; n = NodeTraversal::previous(n)) {
383 // We hit another form element or the start of the form - bail out
384 if (isHTMLFormElement(n) || (n->isHTMLElement() && toElement(n)->isFormControlElement()))
387 if (n->hasTagName(tdTag) && !startingTableCell) {
388 startingTableCell = toHTMLTableCellElement(n);
389 } else if (n->hasTagName(trTag) && startingTableCell) {
390 String result = searchForLabelsAboveCell(regExp.get(), startingTableCell, resultDistance);
391 if (!result.isEmpty()) {
392 if (resultIsInCellAbove)
393 *resultIsInCellAbove = true;
396 searchedCellAbove = true;
397 } else if (n->isTextNode() && n->renderer() && n->renderer()->style().visibility() == VISIBLE) {
398 // For each text chunk, run the regexp
399 String nodeString = n->nodeValue();
400 // add 100 for slop, to make it more likely that we'll search whole nodes
401 if (lengthSearched + nodeString.length() > maxCharsSearched)
402 nodeString = nodeString.right(charsSearchedThreshold - lengthSearched);
403 int pos = regExp->searchRev(nodeString);
406 *resultDistance = lengthSearched;
407 return nodeString.substring(pos, regExp->matchedLength());
409 lengthSearched += nodeString.length();
413 // If we started in a cell, but bailed because we found the start of the form or the
414 // previous element, we still might need to search the row above us for a label.
415 if (startingTableCell && !searchedCellAbove) {
416 String result = searchForLabelsAboveCell(regExp.get(), startingTableCell, resultDistance);
417 if (!result.isEmpty()) {
418 if (resultIsInCellAbove)
419 *resultIsInCellAbove = true;
426 static String matchLabelsAgainstString(const Vector<String>& labels, const String& stringToMatch)
428 if (stringToMatch.isEmpty())
431 String mutableStringToMatch = stringToMatch;
433 // Make numbers and _'s in field names behave like word boundaries, e.g., "address2"
434 replace(mutableStringToMatch, RegularExpression("\\d", TextCaseSensitive), " ");
435 mutableStringToMatch.replace('_', ' ');
437 OwnPtr<RegularExpression> regExp(createRegExpForLabels(labels));
438 // Use the largest match we can find in the whole string
445 pos = regExp->match(mutableStringToMatch, start);
447 length = regExp->matchedLength();
448 if (length >= bestLength) {
457 return mutableStringToMatch.substring(bestPos, bestLength);
461 String Frame::matchLabelsAgainstElement(const Vector<String>& labels, Element* element)
463 // Match against the name element, then against the id element if no match is found for the name element.
464 // See 7538330 for one popular site that benefits from the id element check.
465 // FIXME: This code is mirrored in FrameMac.mm. It would be nice to make the Mac code call the platform-agnostic
466 // code, which would require converting the NSArray of NSStrings to a Vector of Strings somewhere along the way.
467 String resultFromNameAttribute = matchLabelsAgainstString(labels, element->getNameAttribute());
468 if (!resultFromNameAttribute.isEmpty())
469 return resultFromNameAttribute;
471 return matchLabelsAgainstString(labels, element->getAttribute(idAttr));
474 void Frame::setPrinting(bool printing, const FloatSize& pageSize, const FloatSize& originalPageSize, float maximumShrinkRatio, AdjustViewSizeOrNot shouldAdjustViewSize)
476 // In setting printing, we should not validate resources already cached for the document.
477 // See https://bugs.webkit.org/show_bug.cgi?id=43704
478 ResourceCacheValidationSuppressor validationSuppressor(m_doc->cachedResourceLoader());
480 m_doc->setPrinting(printing);
481 view()->adjustMediaTypeForPrinting(printing);
483 m_doc->styleResolverChanged(RecalcStyleImmediately);
484 if (shouldUsePrintingLayout()) {
485 view()->forceLayoutForPagination(pageSize, originalPageSize, maximumShrinkRatio, shouldAdjustViewSize);
487 view()->forceLayout();
488 if (shouldAdjustViewSize == AdjustViewSize)
489 view()->adjustViewSize();
492 // Subframes of the one we're printing don't lay out to the page size.
493 for (RefPtr<Frame> child = tree().firstChild(); child; child = child->tree().nextSibling())
494 child->setPrinting(printing, FloatSize(), FloatSize(), 0, shouldAdjustViewSize);
497 bool Frame::shouldUsePrintingLayout() const
499 // Only top frame being printed should be fit to page size.
500 // Subframes should be constrained by parents only.
501 return m_doc->printing() && (!tree().parent() || !tree().parent()->m_doc->printing());
504 FloatSize Frame::resizePageRectsKeepingRatio(const FloatSize& originalSize, const FloatSize& expectedSize)
506 FloatSize resultSize;
507 if (!contentRenderer())
510 if (contentRenderer()->style().isHorizontalWritingMode()) {
511 ASSERT(fabs(originalSize.width()) > std::numeric_limits<float>::epsilon());
512 float ratio = originalSize.height() / originalSize.width();
513 resultSize.setWidth(floorf(expectedSize.width()));
514 resultSize.setHeight(floorf(resultSize.width() * ratio));
516 ASSERT(fabs(originalSize.height()) > std::numeric_limits<float>::epsilon());
517 float ratio = originalSize.width() / originalSize.height();
518 resultSize.setHeight(floorf(expectedSize.height()));
519 resultSize.setWidth(floorf(resultSize.height() * ratio));
524 void Frame::injectUserScripts(UserScriptInjectionTime injectionTime)
529 if (loader().stateMachine()->creatingInitialEmptyDocument() && !settings().shouldInjectUserScriptsInInitialEmptyDocument())
532 // Walk the hashtable. Inject by world.
533 const UserScriptMap* userScripts = m_page->group().userScripts();
537 for (auto it = userScripts->begin(), end = userScripts->end(); it != end; ++it)
538 injectUserScriptsForWorld(*it->key.get(), *it->value, injectionTime);
541 void Frame::injectUserScriptsForWorld(DOMWrapperWorld& world, const UserScriptVector& userScripts, UserScriptInjectionTime injectionTime)
543 if (userScripts.isEmpty())
546 Document* doc = document();
550 Vector<ScriptSourceCode> sourceCode;
551 unsigned count = userScripts.size();
552 for (unsigned i = 0; i < count; ++i) {
553 UserScript* script = userScripts[i].get();
554 if (script->injectedFrames() == InjectInTopFrameOnly && ownerElement())
557 if (script->injectionTime() == injectionTime && UserContentURLPattern::matchesPatterns(doc->url(), script->whitelist(), script->blacklist()))
558 m_script->evaluateInWorld(ScriptSourceCode(script->source(), script->url()), world);
562 RenderView* Frame::contentRenderer() const
564 return document() ? document()->renderView() : 0;
567 RenderWidget* Frame::ownerRenderer() const
569 HTMLFrameOwnerElement* ownerElement = m_ownerElement;
572 auto object = ownerElement->renderer();
575 // FIXME: If <object> is ever fixed to disassociate itself from frames
576 // that it has started but canceled, then this can turn into an ASSERT
577 // since m_ownerElement would be 0 when the load is canceled.
578 // https://bugs.webkit.org/show_bug.cgi?id=18585
579 if (!object->isWidget())
581 return toRenderWidget(object);
584 Frame* Frame::frameForWidget(const Widget* widget)
586 ASSERT_ARG(widget, widget);
588 if (RenderWidget* renderer = RenderWidget::find(widget))
589 return renderer->frameOwnerElement().document().frame();
591 // Assume all widgets are either a FrameView or owned by a RenderWidget.
592 // FIXME: That assumption is not right for scroll bars!
593 ASSERT_WITH_SECURITY_IMPLICATION(widget->isFrameView());
594 return &toFrameView(widget)->frame();
597 void Frame::clearTimers(FrameView *view, Document *document)
600 view->unscheduleRelayout();
601 view->frame().animation().suspendAnimationsForDocument(document);
602 view->frame().eventHandler().stopAutoscrollTimer();
606 void Frame::clearTimers()
608 clearTimers(m_view.get(), document());
611 void Frame::willDetachPage()
613 if (Frame* parent = tree().parent())
614 parent->loader().checkLoadComplete();
616 for (auto& observer : m_destructionObservers)
617 observer->willDetachPage();
619 // FIXME: It's unclear as to why this is called more than once, but it is,
620 // so page() could be NULL.
621 if (page() && page()->focusController().focusedFrame() == this)
622 page()->focusController().setFocusedFrame(0);
624 if (page() && page()->scrollingCoordinator() && m_view)
625 page()->scrollingCoordinator()->willDestroyScrollableArea(m_view.get());
627 script().clearScriptObjects();
628 script().updatePlatformScriptObjects();
631 void Frame::disconnectOwnerElement()
633 if (m_ownerElement) {
634 // We use the ownerElement's document to retrieve the cache, because the contentDocument for this
635 // frame is already detached (and can't access the top level AX cache).
636 // However, we pass in the current document to clearTextMarkerNodesInUse so we can identify the
637 // nodes inside this document that need to be removed from the cache.
639 // We don't clear the AXObjectCache here because we don't want to clear the top level cache
640 // when a sub-frame is removed.
641 #if HAVE(ACCESSIBILITY)
642 if (AXObjectCache* cache = m_ownerElement->document().existingAXObjectCache())
643 cache->clearTextMarkerNodesInUse(document());
646 m_ownerElement->clearContentFrame();
648 m_page->decrementSubframeCount();
650 m_ownerElement = nullptr;
653 String Frame::displayStringModifiedByEncoding(const String& str) const
655 return document() ? document()->displayStringModifiedByEncoding(str) : str;
658 VisiblePosition Frame::visiblePositionForPoint(const IntPoint& framePoint)
660 HitTestResult result = eventHandler().hitTestResultAtPoint(framePoint, HitTestRequest::ReadOnly | HitTestRequest::Active);
661 Node* node = result.innerNonSharedNode();
663 return VisiblePosition();
664 auto renderer = node->renderer();
666 return VisiblePosition();
667 VisiblePosition visiblePos = renderer->positionForPoint(result.localPoint());
668 if (visiblePos.isNull())
669 visiblePos = firstPositionInOrBeforeNode(node);
673 Document* Frame::documentAtPoint(const IntPoint& point)
678 IntPoint pt = view()->windowToContents(point);
679 HitTestResult result = HitTestResult(pt);
681 if (contentRenderer())
682 result = eventHandler().hitTestResultAtPoint(pt);
683 return result.innerNode() ? &result.innerNode()->document() : 0;
686 PassRefPtr<Range> Frame::rangeForPoint(const IntPoint& framePoint)
688 VisiblePosition position = visiblePositionForPoint(framePoint);
689 if (position.isNull())
692 VisiblePosition previous = position.previous();
693 if (previous.isNotNull()) {
694 RefPtr<Range> previousCharacterRange = makeRange(previous, position);
695 LayoutRect rect = editor().firstRectForRange(previousCharacterRange.get());
696 if (rect.contains(framePoint))
697 return previousCharacterRange.release();
700 VisiblePosition next = position.next();
701 if (RefPtr<Range> nextCharacterRange = makeRange(position, next)) {
702 LayoutRect rect = editor().firstRectForRange(nextCharacterRange.get());
703 if (rect.contains(framePoint))
704 return nextCharacterRange.release();
710 void Frame::createView(const IntSize& viewportSize, const Color& backgroundColor, bool transparent,
711 const IntSize& fixedLayoutSize, const IntRect& fixedVisibleContentRect ,
712 bool useFixedLayout, ScrollbarMode horizontalScrollbarMode, bool horizontalLock,
713 ScrollbarMode verticalScrollbarMode, bool verticalLock)
718 bool isMainFrame = this->isMainFrame();
720 if (isMainFrame && view())
721 view()->setParentVisible(false);
725 RefPtr<FrameView> frameView;
727 frameView = FrameView::create(*this, viewportSize);
728 frameView->setFixedLayoutSize(fixedLayoutSize);
729 frameView->setFixedVisibleContentRect(fixedVisibleContentRect);
730 frameView->setUseFixedLayout(useFixedLayout);
732 frameView = FrameView::create(*this);
734 frameView->setScrollbarModes(horizontalScrollbarMode, verticalScrollbarMode, horizontalLock, verticalLock);
738 if (backgroundColor.isValid())
739 frameView->updateBackgroundRecursively(backgroundColor, transparent);
742 frameView->setParentVisible(true);
745 ownerRenderer()->setWidget(frameView);
747 if (HTMLFrameOwnerElement* owner = ownerElement())
748 view()->setCanHaveScrollbars(owner->scrollingMode() != ScrollbarAlwaysOff);
751 #if USE(TILED_BACKING_STORE)
752 void Frame::setTiledBackingStoreEnabled(bool enabled)
755 m_tiledBackingStore.clear();
758 if (m_tiledBackingStore)
760 m_tiledBackingStore = adoptPtr(new TiledBackingStore(this));
761 m_tiledBackingStore->setCommitTileUpdatesOnIdleEventLoop(true);
763 m_view->setPaintsEntireContents(true);
766 void Frame::tiledBackingStorePaintBegin()
770 m_view->updateLayoutAndStyleIfNeededRecursive();
771 m_view->flushDeferredRepaints();
774 void Frame::tiledBackingStorePaint(GraphicsContext* context, const IntRect& rect)
778 m_view->paintContents(context, rect);
781 void Frame::tiledBackingStorePaintEnd(const Vector<IntRect>& paintedArea)
783 if (!m_page || !m_view)
785 unsigned size = paintedArea.size();
786 // Request repaint from the system
787 for (unsigned n = 0; n < size; ++n)
788 m_page->chrome().invalidateContentsAndRootView(m_view->contentsToRootView(paintedArea[n]), false);
791 IntRect Frame::tiledBackingStoreContentsRect()
795 return IntRect(IntPoint(), m_view->contentsSize());
798 IntRect Frame::tiledBackingStoreVisibleRect()
802 return m_page->chrome().client().visibleRectForTiledBackingStore();
805 Color Frame::tiledBackingStoreBackgroundColor() const
809 return m_view->baseBackgroundColor();
813 String Frame::layerTreeAsText(LayerTreeFlags flags) const
815 #if USE(ACCELERATED_COMPOSITING)
816 document()->updateLayout();
818 if (!contentRenderer())
821 return contentRenderer()->compositor().layerTreeAsText(flags);
828 String Frame::trackedRepaintRectsAsText() const
832 return m_view->trackedRepaintRectsAsText();
835 void Frame::setPageZoomFactor(float factor)
837 setPageAndTextZoomFactors(factor, m_textZoomFactor);
840 void Frame::setTextZoomFactor(float factor)
842 setPageAndTextZoomFactors(m_pageZoomFactor, factor);
845 void Frame::setPageAndTextZoomFactors(float pageZoomFactor, float textZoomFactor)
847 if (m_pageZoomFactor == pageZoomFactor && m_textZoomFactor == textZoomFactor)
850 Page* page = this->page();
854 Document* document = this->document();
858 m_editor->dismissCorrectionPanelAsIgnored();
861 // Respect SVGs zoomAndPan="disabled" property in standalone SVG documents.
862 // FIXME: How to handle compound documents + zoomAndPan="disabled"? Needs SVG WG clarification.
863 if (document->isSVGDocument()) {
864 if (!toSVGDocument(document)->zoomAndPanEnabled())
869 if (m_pageZoomFactor != pageZoomFactor) {
870 if (FrameView* view = this->view()) {
871 // Update the scroll position when doing a full page zoom, so the content stays in relatively the same position.
872 LayoutPoint scrollPosition = view->scrollPosition();
873 float percentDifference = (pageZoomFactor / m_pageZoomFactor);
874 view->setScrollPosition(IntPoint(scrollPosition.x() * percentDifference, scrollPosition.y() * percentDifference));
878 m_pageZoomFactor = pageZoomFactor;
879 m_textZoomFactor = textZoomFactor;
881 document->recalcStyle(Style::Force);
883 for (RefPtr<Frame> child = tree().firstChild(); child; child = child->tree().nextSibling())
884 child->setPageAndTextZoomFactors(m_pageZoomFactor, m_textZoomFactor);
886 if (FrameView* view = this->view()) {
887 if (document->renderView() && document->renderView()->needsLayout() && view->didFirstLayout())
892 pageCache()->markPagesForFullStyleRecalc(page);
895 float Frame::frameScaleFactor() const
897 Page* page = this->page();
899 // Main frame is scaled with respect to he container but inner frames are not scaled with respect to the main frame.
900 if (!page || &page->mainFrame() != this || settings().delegatesPageScaling())
903 return page->pageScaleFactor();
906 void Frame::suspendActiveDOMObjectsAndAnimations()
908 bool wasSuspended = activeDOMObjectsAndAnimationsSuspended();
910 m_activeDOMObjectsAndAnimationsSuspendedCount++;
915 // FIXME: Suspend/resume calls will not match if the frame is navigated, and gets a new document.
917 document()->suspendScriptedAnimationControllerCallbacks();
918 animation().suspendAnimationsForDocument(document());
919 document()->suspendActiveDOMObjects(ActiveDOMObject::PageWillBeSuspended);
923 void Frame::resumeActiveDOMObjectsAndAnimations()
925 ASSERT(activeDOMObjectsAndAnimationsSuspended());
927 m_activeDOMObjectsAndAnimationsSuspendedCount--;
929 if (activeDOMObjectsAndAnimationsSuspended())
933 document()->resumeActiveDOMObjects(ActiveDOMObject::PageWillBeSuspended);
934 animation().resumeAnimationsForDocument(document());
935 document()->resumeScriptedAnimationControllerCallbacks();
939 #if USE(ACCELERATED_COMPOSITING)
940 void Frame::deviceOrPageScaleFactorChanged()
942 for (RefPtr<Frame> child = tree().firstChild(); child; child = child->tree().nextSibling())
943 child->deviceOrPageScaleFactorChanged();
945 if (RenderView* root = contentRenderer())
946 root->compositor().deviceOrPageScaleFactorChanged();
950 bool Frame::isURLAllowed(const URL& url) const
952 // We allow one level of self-reference because some sites depend on that,
953 // but we don't allow more than one.
954 if (m_page->subframeCount() >= Page::maxNumberOfFrames)
956 bool foundSelfReference = false;
957 for (const Frame* frame = this; frame; frame = frame->tree().parent()) {
958 if (equalIgnoringFragmentIdentifier(frame->document()->url(), url)) {
959 if (foundSelfReference)
961 foundSelfReference = true;
967 } // namespace WebCore