diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
commit | 1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch) | |
tree | 46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/WebCore/page/Frame.cpp | |
parent | 32761a6cee1d0dee366b885b7b9c777e67885688 (diff) | |
download | WebKitGtk-tarball-master.tar.gz |
webkitgtk-2.16.5HEADwebkitgtk-2.16.5master
Diffstat (limited to 'Source/WebCore/page/Frame.cpp')
-rw-r--r-- | Source/WebCore/page/Frame.cpp | 468 |
1 files changed, 193 insertions, 275 deletions
diff --git a/Source/WebCore/page/Frame.cpp b/Source/WebCore/page/Frame.cpp index 4456c0d5a..990885027 100644 --- a/Source/WebCore/page/Frame.cpp +++ b/Source/WebCore/page/Frame.cpp @@ -5,7 +5,7 @@ * 2000 Simon Hausmann <hausmann@kde.org> * 2000 Stefan Schimanski <1Stein@gmx.de> * 2001 George Staikos <staikos@kde.org> - * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved. + * Copyright (C) 2004-2016 Apple Inc. All rights reserved. * Copyright (C) 2005 Alexey Proskuryakov <ap@nypop.com> * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) * Copyright (C) 2008 Eric Seidel <eric@webkit.org> @@ -30,9 +30,9 @@ #include "config.h" #include "Frame.h" -#include "AnimationController.h" #include "ApplyStyleCommand.h" #include "BackForwardController.h" +#include "CSSAnimationController.h" #include "CSSComputedStyleDeclaration.h" #include "CSSPropertyNames.h" #include "CachedCSSStyleSheet.h" @@ -61,6 +61,7 @@ #include "HTMLFrameElementBase.h" #include "HTMLNames.h" #include "HTMLTableCellElement.h" +#include "HTMLTableRowElement.h" #include "HitTestResult.h" #include "ImageBuffer.h" #include "InspectorInstrumentation.h" @@ -74,7 +75,7 @@ #include "NodeTraversal.h" #include "Page.h" #include "PageCache.h" -#include "PageGroup.h" +#include "RenderLayerCompositor.h" #include "RenderTableCell.h" #include "RenderText.h" #include "RenderTextControl.h" @@ -82,17 +83,20 @@ #include "RenderView.h" #include "RenderWidget.h" #include "RuntimeEnabledFeatures.h" +#include "SVGDocument.h" +#include "SVGDocumentExtensions.h" #include "SVGNames.h" #include "ScriptController.h" #include "ScriptSourceCode.h" #include "ScrollingCoordinator.h" #include "Settings.h" #include "StyleProperties.h" -#include "TextIterator.h" +#include "StyleScope.h" #include "TextNodeTraversal.h" #include "TextResourceDecoder.h" #include "UserContentController.h" #include "UserContentURLPattern.h" +#include "UserScript.h" #include "UserTypingGestureIndicator.h" #include "VisibleUnits.h" #include "WebKitFontFamilyNames.h" @@ -103,25 +107,11 @@ #include "markup.h" #include "npruntime_impl.h" #include "runtime_root.h" -#include <bindings/ScriptValue.h> -#include <wtf/PassOwnPtr.h> #include <wtf/RefCountedLeakCounter.h> #include <wtf/StdLibExtras.h> +#include <wtf/text/StringBuilder.h> #include <yarr/RegularExpression.h> -#if USE(ACCELERATED_COMPOSITING) -#include "RenderLayerCompositor.h" -#endif - -#if ENABLE(SVG) -#include "SVGDocument.h" -#include "SVGDocumentExtensions.h" -#endif - -#if USE(TILED_BACKING_STORE) -#include "TiledBackingStore.h" -#endif - #if PLATFORM(IOS) #include "WKContentObservation.h" #endif @@ -168,22 +158,17 @@ Frame::Frame(Page& page, HTMLFrameOwnerElement* ownerElement, FrameLoaderClient& , m_navigationScheduler(*this) , m_ownerElement(ownerElement) , m_script(std::make_unique<ScriptController>(*this)) - , m_editor(Editor::create(*this)) - , m_selection(adoptPtr(new FrameSelection(this))) - , m_eventHandler(adoptPtr(new EventHandler(*this))) - , m_animationController(std::make_unique<AnimationController>(*this)) + , m_editor(std::make_unique<Editor>(*this)) + , m_selection(std::make_unique<FrameSelection>(this)) + , m_animationController(std::make_unique<CSSAnimationController>(*this)) #if PLATFORM(IOS) - , m_overflowAutoScrollTimer(this, &Frame::overflowAutoScrollTimerFired) + , m_overflowAutoScrollTimer(*this, &Frame::overflowAutoScrollTimerFired) , m_selectionChangeCallbacksDisabled(false) - , m_timersPausedCount(0) #endif , m_pageZoomFactor(parentPageZoomFactor(this)) , m_textZoomFactor(parentTextZoomFactor(this)) -#if ENABLE(ORIENTATION_EVENTS) - , m_orientation(0) -#endif - , m_inViewSourceMode(false) , m_activeDOMObjectsAndAnimationsSuspendedCount(0) + , m_eventHandler(std::make_unique<EventHandler>(*this)) { AtomicString::init(); HTMLNames::init(); @@ -196,12 +181,7 @@ Frame::Frame(Page& page, HTMLFrameOwnerElement* ownerElement, FrameLoaderClient& XMLNames::init(); WebKitFontFamilyNames::init(); - if (!ownerElement) { -#if USE(TILED_BACKING_STORE) - // Top level frame only for now. - setTiledBackingStoreEnabled(settings().tiledBackingStoreEnabled()); -#endif - } else { + if (ownerElement) { m_mainFrame.selfOnlyRef(); page.incrementSubframeCount(); ownerElement->setContentFrame(this); @@ -211,29 +191,22 @@ Frame::Frame(Page& page, HTMLFrameOwnerElement* ownerElement, FrameLoaderClient& frameCounter.increment(); #endif - // FIXME: We should reconcile the iOS and OpenSource code below. - Frame* parent = parentFromOwnerElement(ownerElement); -#if PLATFORM(IOS) - // Pause future timers if this frame is created when page is in pending state. - if (parent && parent->timersPaused()) - setTimersPaused(true); -#else // Pause future ActiveDOMObjects if this frame is being created while the page is in a paused state. + Frame* parent = parentFromOwnerElement(ownerElement); if (parent && parent->activeDOMObjectsAndAnimationsSuspended()) suspendActiveDOMObjectsAndAnimations(); -#endif } -PassRefPtr<Frame> Frame::create(Page* page, HTMLFrameOwnerElement* ownerElement, FrameLoaderClient* client) +Ref<Frame> Frame::create(Page* page, HTMLFrameOwnerElement* ownerElement, FrameLoaderClient* client) { ASSERT(page); ASSERT(client); - return adoptRef(new Frame(*page, ownerElement, *client)); + return adoptRef(*new Frame(*page, ownerElement, *client)); } Frame::~Frame() { - setView(0); + setView(nullptr); loader().cancelAndClear(); // FIXME: We should not be doing all this work inside the destructor @@ -244,8 +217,8 @@ Frame::~Frame() disconnectOwnerElement(); - for (auto& observer : m_destructionObservers) - observer->frameDestroyed(); + while (auto* destructionObserver = m_destructionObservers.takeAny()) + destructionObserver->frameDestroyed(); if (!isMainFrame()) m_mainFrame.selfOnlyDeref(); @@ -261,7 +234,7 @@ void Frame::removeDestructionObserver(FrameDestructionObserver* observer) m_destructionObservers.remove(observer); } -void Frame::setView(PassRefPtr<FrameView> view) +void Frame::setView(RefPtr<FrameView>&& view) { // We the custom scroll bars as early as possible to prevent m_doc->detach() // from messing with the view such that its scroll bars won't be torn down. @@ -272,35 +245,44 @@ void Frame::setView(PassRefPtr<FrameView> view) // Prepare for destruction now, so any unload event handlers get run and the DOMWindow is // notified. If we wait until the view is destroyed, then things won't be hooked up enough for // these calls to work. - if (!view && m_doc && m_doc->hasLivingRenderTree() && !m_doc->inPageCache()) + if (!view && m_doc && m_doc->pageCacheState() != Document::InPageCache) m_doc->prepareForDestruction(); if (m_view) m_view->unscheduleRelayout(); - eventHandler().clear(); + // This may be called during destruction, so need to do a null check. + if (m_eventHandler) + m_eventHandler->clear(); + + bool hadLivingRenderTree = m_doc ? m_doc->hasLivingRenderTree() : false; + if (hadLivingRenderTree) + m_doc->destroyRenderTree(); - m_view = view; + m_view = WTFMove(view); + if (hadLivingRenderTree && m_view) + m_doc->didBecomeCurrentDocumentInView(); + // Only one form submission is allowed per view of a part. // Since this part may be getting reused as a result of being // pulled from the back/forward cache, reset this flag. loader().resetMultipleFormSubmissionProtection(); - -#if USE(TILED_BACKING_STORE) - if (m_view && tiledBackingStore()) - m_view->setPaintsEntireContents(true); -#endif } -void Frame::setDocument(PassRefPtr<Document> newDocument) +void Frame::setDocument(RefPtr<Document>&& newDocument) { ASSERT(!newDocument || newDocument->frame() == this); - if (m_doc && m_doc->hasLivingRenderTree() && !m_doc->inPageCache()) + if (m_documentIsBeingReplaced) + return; + + m_documentIsBeingReplaced = true; + + if (m_doc && m_doc->pageCacheState() != Document::InPageCache) m_doc->prepareForDestruction(); - m_doc = newDocument.get(); + m_doc = newDocument.copyRef(); ASSERT(!m_doc || m_doc->domWindow()); ASSERT(!m_doc || m_doc->domWindow()->frame() == this); @@ -308,24 +290,41 @@ void Frame::setDocument(PassRefPtr<Document> newDocument) // that the document is not destroyed during this function call. if (newDocument) newDocument->didBecomeCurrentDocumentInFrame(); + + InspectorInstrumentation::frameDocumentUpdated(*this); + + m_documentIsBeingReplaced = false; } #if ENABLE(ORIENTATION_EVENTS) -void Frame::sendOrientationChangeEvent(int orientation) +void Frame::orientationChanged() +{ + Vector<Ref<Frame>> frames; + for (Frame* frame = this; frame; frame = frame->tree().traverseNext()) + frames.append(*frame); + + for (auto& frame : frames) { + if (Document* document = frame->document()) + document->dispatchWindowEvent(Event::create(eventNames().orientationchangeEvent, false, false)); + } +} + +int Frame::orientation() const { - m_orientation = orientation; - if (Document* doc = document()) - doc->dispatchWindowEvent(Event::create(eventNames().orientationchangeEvent, false, false)); + if (m_page) + return m_page->chrome().client().deviceOrientation(); + return 0; } #endif // ENABLE(ORIENTATION_EVENTS) -static PassOwnPtr<JSC::Yarr::RegularExpression> createRegExpForLabels(const Vector<String>& labels) +static JSC::Yarr::RegularExpression createRegExpForLabels(const Vector<String>& labels) { // REVIEW- version of this call in FrameMac.mm caches based on the NSArray ptrs being // the same across calls. We can't do that. - DEFINE_STATIC_LOCAL(JSC::Yarr::RegularExpression, wordRegExp, ("\\w", TextCaseSensitive)); - String pattern("("); + static NeverDestroyed<JSC::Yarr::RegularExpression> wordRegExp("\\w", TextCaseSensitive); + StringBuilder pattern; + pattern.append('('); unsigned int numLabels = labels.size(); unsigned int i; for (i = 0; i < numLabels; i++) { @@ -334,41 +333,41 @@ static PassOwnPtr<JSC::Yarr::RegularExpression> createRegExpForLabels(const Vect bool startsWithWordChar = false; bool endsWithWordChar = false; if (label.length()) { - startsWithWordChar = wordRegExp.match(label.substring(0, 1)) >= 0; - endsWithWordChar = wordRegExp.match(label.substring(label.length() - 1, 1)) >= 0; + startsWithWordChar = wordRegExp.get().match(label.substring(0, 1)) >= 0; + endsWithWordChar = wordRegExp.get().match(label.substring(label.length() - 1, 1)) >= 0; } if (i) - pattern.append("|"); + pattern.append('|'); // Search for word boundaries only if label starts/ends with "word characters". // If we always searched for word boundaries, this wouldn't work for languages // such as Japanese. if (startsWithWordChar) - pattern.append("\\b"); + pattern.appendLiteral("\\b"); pattern.append(label); if (endsWithWordChar) - pattern.append("\\b"); + pattern.appendLiteral("\\b"); } - pattern.append(")"); - return adoptPtr(new JSC::Yarr::RegularExpression(pattern, TextCaseInsensitive)); + pattern.append(')'); + return JSC::Yarr::RegularExpression(pattern.toString(), TextCaseInsensitive); } -String Frame::searchForLabelsAboveCell(JSC::Yarr::RegularExpression* regExp, HTMLTableCellElement* cell, size_t* resultDistanceFromStartOfCell) +String Frame::searchForLabelsAboveCell(const JSC::Yarr::RegularExpression& regExp, HTMLTableCellElement* cell, size_t* resultDistanceFromStartOfCell) { HTMLTableCellElement* aboveCell = cell->cellAbove(); if (aboveCell) { // search within the above cell we found for a match size_t lengthSearched = 0; - for (Text* textNode = TextNodeTraversal::firstWithin(aboveCell); textNode; textNode = TextNodeTraversal::next(textNode, aboveCell)) { + for (Text* textNode = TextNodeTraversal::firstWithin(*aboveCell); textNode; textNode = TextNodeTraversal::next(*textNode, aboveCell)) { if (!textNode->renderer() || textNode->renderer()->style().visibility() != VISIBLE) continue; // For each text chunk, run the regexp String nodeString = textNode->data(); - int pos = regExp->searchRev(nodeString); + int pos = regExp.searchRev(nodeString); if (pos >= 0) { if (resultDistanceFromStartOfCell) *resultDistanceFromStartOfCell = lengthSearched; - return nodeString.substring(pos, regExp->matchedLength()); + return nodeString.substring(pos, regExp.matchedLength()); } lengthSearched += nodeString.length(); } @@ -380,16 +379,18 @@ String Frame::searchForLabelsAboveCell(JSC::Yarr::RegularExpression* regExp, HTM return String(); } +// FIXME: This should take an Element&. String Frame::searchForLabelsBeforeElement(const Vector<String>& labels, Element* element, size_t* resultDistance, bool* resultIsInCellAbove) { - OwnPtr<JSC::Yarr::RegularExpression> regExp(createRegExpForLabels(labels)); + ASSERT(element); + JSC::Yarr::RegularExpression regExp = createRegExpForLabels(labels); // We stop searching after we've seen this many chars const unsigned int charsSearchedThreshold = 500; // This is the absolute max we search. We allow a little more slop than // charsSearchedThreshold, to make it more likely that we'll search whole nodes. const unsigned int maxCharsSearched = 600; // If the starting element is within a table, the cell that contains it - HTMLTableCellElement* startingTableCell = 0; + HTMLTableCellElement* startingTableCell = nullptr; bool searchedCellAbove = false; if (resultDistance) @@ -400,15 +401,15 @@ String Frame::searchForLabelsBeforeElement(const Vector<String>& labels, Element // walk backwards in the node tree, until another element, or form, or end of tree int unsigned lengthSearched = 0; Node* n; - for (n = NodeTraversal::previous(element); n && lengthSearched < charsSearchedThreshold; n = NodeTraversal::previous(n)) { + for (n = NodeTraversal::previous(*element); n && lengthSearched < charsSearchedThreshold; n = NodeTraversal::previous(*n)) { // We hit another form element or the start of the form - bail out - if (isHTMLFormElement(n) || (n->isHTMLElement() && toElement(n)->isFormControlElement())) + if (is<HTMLFormElement>(*n) || is<HTMLFormControlElement>(*n)) break; - if (n->hasTagName(tdTag) && !startingTableCell) { - startingTableCell = toHTMLTableCellElement(n); - } else if (n->hasTagName(trTag) && startingTableCell) { - String result = searchForLabelsAboveCell(regExp.get(), startingTableCell, resultDistance); + if (n->hasTagName(tdTag) && !startingTableCell) + startingTableCell = downcast<HTMLTableCellElement>(n); + else if (is<HTMLTableRowElement>(*n) && startingTableCell) { + String result = searchForLabelsAboveCell(regExp, startingTableCell, resultDistance); if (!result.isEmpty()) { if (resultIsInCellAbove) *resultIsInCellAbove = true; @@ -421,11 +422,11 @@ String Frame::searchForLabelsBeforeElement(const Vector<String>& labels, Element // add 100 for slop, to make it more likely that we'll search whole nodes if (lengthSearched + nodeString.length() > maxCharsSearched) nodeString = nodeString.right(charsSearchedThreshold - lengthSearched); - int pos = regExp->searchRev(nodeString); + int pos = regExp.searchRev(nodeString); if (pos >= 0) { if (resultDistance) *resultDistance = lengthSearched; - return nodeString.substring(pos, regExp->matchedLength()); + return nodeString.substring(pos, regExp.matchedLength()); } lengthSearched += nodeString.length(); } @@ -434,7 +435,7 @@ String Frame::searchForLabelsBeforeElement(const Vector<String>& labels, Element // If we started in a cell, but bailed because we found the start of the form or the // previous element, we still might need to search the row above us for a label. if (startingTableCell && !searchedCellAbove) { - String result = searchForLabelsAboveCell(regExp.get(), startingTableCell, resultDistance); + String result = searchForLabelsAboveCell(regExp, startingTableCell, resultDistance); if (!result.isEmpty()) { if (resultIsInCellAbove) *resultIsInCellAbove = true; @@ -455,7 +456,7 @@ static String matchLabelsAgainstString(const Vector<String>& labels, const Strin replace(mutableStringToMatch, JSC::Yarr::RegularExpression("\\d", TextCaseSensitive), " "); mutableStringToMatch.replace('_', ' '); - OwnPtr<JSC::Yarr::RegularExpression> regExp(createRegExpForLabels(labels)); + JSC::Yarr::RegularExpression regExp = createRegExpForLabels(labels); // Use the largest match we can find in the whole string int pos; int length; @@ -463,9 +464,9 @@ static String matchLabelsAgainstString(const Vector<String>& labels, const Strin int bestLength = -1; int start = 0; do { - pos = regExp->match(mutableStringToMatch, start); + pos = regExp.match(mutableStringToMatch, start); if (pos != -1) { - length = regExp->matchedLength(); + length = regExp.matchedLength(); if (length >= bestLength) { bestPos = pos; bestLength = length; @@ -489,7 +490,7 @@ String Frame::matchLabelsAgainstElement(const Vector<String>& labels, Element* e if (!resultFromNameAttribute.isEmpty()) return resultFromNameAttribute; - return matchLabelsAgainstString(labels, element->getAttribute(idAttr)); + return matchLabelsAgainstString(labels, element->attributeWithoutSynchronization(idAttr)); } #if PLATFORM(IOS) @@ -505,30 +506,30 @@ void Frame::scrollOverflowLayer(RenderLayer* layer, const IntRect& visibleRect, if (visibleRect.intersects(exposeRect)) return; - int x = layer->scrollXOffset(); + // FIXME: Why isn't this just calling RenderLayer::scrollRectToVisible()? + ScrollOffset scrollOffset = layer->scrollOffset(); int exposeLeft = exposeRect.x(); int exposeRight = exposeLeft + exposeRect.width(); - int clientWidth = box->clientWidth(); + int clientWidth = roundToInt(box->clientWidth()); if (exposeLeft <= 0) - x = std::max(0, x + exposeLeft - clientWidth / 2); + scrollOffset.setX(std::max(0, scrollOffset.x() + exposeLeft - clientWidth / 2)); else if (exposeRight >= clientWidth) - x = std::min(box->scrollWidth() - clientWidth, x + clientWidth / 2); + scrollOffset.setX(std::min(box->scrollWidth() - clientWidth, scrollOffset.x() + clientWidth / 2)); - int y = layer->scrollYOffset(); int exposeTop = exposeRect.y(); int exposeBottom = exposeTop + exposeRect.height(); - int clientHeight = box->clientHeight(); + int clientHeight = roundToInt(box->clientHeight()); if (exposeTop <= 0) - y = std::max(0, y + exposeTop - clientHeight / 2); + scrollOffset.setY(std::max(0, scrollOffset.y() + exposeTop - clientHeight / 2)); else if (exposeBottom >= clientHeight) - y = std::min(box->scrollHeight() - clientHeight, y + clientHeight / 2); + scrollOffset.setY(std::min(box->scrollHeight() - clientHeight, scrollOffset.y() + clientHeight / 2)); - layer->scrollToOffset(IntSize(x, y)); + layer->scrollToOffset(scrollOffset); selection().setCaretRectNeedsUpdate(); selection().updateAppearance(); } -void Frame::overflowAutoScrollTimerFired(Timer<Frame>*) +void Frame::overflowAutoScrollTimerFired() { if (!eventHandler().mousePressed() || checkOverflowScroll(PerformOverflowScroll) == OverflowScrollNone) { if (m_overflowAutoScrollTimer.isActive()) @@ -616,11 +617,13 @@ int Frame::checkOverflowScroll(OverflowScrollAction action) } } + Ref<Frame> protectedThis(*this); + if (action == PerformOverflowScroll && (deltaX || deltaY)) { - layer->scrollToOffset(IntSize(layer->scrollXOffset() + deltaX, layer->scrollYOffset() + deltaY)); + layer->scrollToOffset(layer->scrollOffset() + IntSize(deltaX, deltaY)); // Handle making selection. - VisiblePosition visiblePosition(renderer->positionForPoint(selectionPosition)); + VisiblePosition visiblePosition(renderer->positionForPoint(selectionPosition, nullptr)); if (visiblePosition.isNotNull()) { VisibleSelection visibleSelection = selection().selection(); visibleSelection.setExtent(visiblePosition); @@ -653,15 +656,17 @@ void Frame::setPrinting(bool printing, const FloatSize& pageSize, const FloatSiz ResourceCacheValidationSuppressor validationSuppressor(m_doc->cachedResourceLoader()); m_doc->setPrinting(printing); - view()->adjustMediaTypeForPrinting(printing); - - m_doc->styleResolverChanged(RecalcStyleImmediately); - if (shouldUsePrintingLayout()) { - view()->forceLayoutForPagination(pageSize, originalPageSize, maximumShrinkRatio, shouldAdjustViewSize); - } else { - view()->forceLayout(); - if (shouldAdjustViewSize == AdjustViewSize) - view()->adjustViewSize(); + if (auto* frameView = view()) { + frameView->adjustMediaTypeForPrinting(printing); + + m_doc->styleScope().didChangeStyleSheetEnvironment(); + if (shouldUsePrintingLayout()) + frameView->forceLayoutForPagination(pageSize, originalPageSize, maximumShrinkRatio, shouldAdjustViewSize); + else { + frameView->forceLayout(); + if (shouldAdjustViewSize == AdjustViewSize) + frameView->adjustViewSize(); + } } // Subframes of the one we're printing don't lay out to the page size. @@ -701,76 +706,52 @@ void Frame::injectUserScripts(UserScriptInjectionTime injectionTime) if (!m_page) return; - if (loader().stateMachine()->creatingInitialEmptyDocument() && !settings().shouldInjectUserScriptsInInitialEmptyDocument()) - return; - - const auto* userContentController = m_page->userContentController(); - if (!userContentController) - return; - - // Walk the hashtable. Inject by world. - const UserScriptMap* userScripts = userContentController->userScripts(); - if (!userScripts) + if (loader().stateMachine().creatingInitialEmptyDocument() && !settings().shouldInjectUserScriptsInInitialEmptyDocument()) return; - for (const auto& worldAndUserScript : *userScripts) - injectUserScriptsForWorld(*worldAndUserScript.key, *worldAndUserScript.value, injectionTime); -} - -void Frame::injectUserScriptsForWorld(DOMWrapperWorld& world, const UserScriptVector& userScripts, UserScriptInjectionTime injectionTime) -{ - if (userScripts.isEmpty()) - return; - - Document* doc = document(); - if (!doc) + Document* document = this->document(); + if (!document) return; - Vector<ScriptSourceCode> sourceCode; - unsigned count = userScripts.size(); - for (unsigned i = 0; i < count; ++i) { - UserScript* script = userScripts[i].get(); - if (script->injectedFrames() == InjectInTopFrameOnly && ownerElement()) - continue; + m_page->userContentProvider().forEachUserScript([&](DOMWrapperWorld& world, const UserScript& script) { + if (script.injectedFrames() == InjectInTopFrameOnly && ownerElement()) + return; - if (script->injectionTime() == injectionTime && UserContentURLPattern::matchesPatterns(doc->url(), script->whitelist(), script->blacklist())) - m_script->evaluateInWorld(ScriptSourceCode(script->source(), script->url()), world); - } + if (script.injectionTime() == injectionTime && UserContentURLPattern::matchesPatterns(document->url(), script.whitelist(), script.blacklist())) { + m_page->setAsRunningUserScripts(); + m_script->evaluateInWorld(ScriptSourceCode(script.source(), script.url()), world); + } + }); } RenderView* Frame::contentRenderer() const { - return document() ? document()->renderView() : 0; + return document() ? document()->renderView() : nullptr; } RenderWidget* Frame::ownerRenderer() const { - HTMLFrameOwnerElement* ownerElement = m_ownerElement; + auto* ownerElement = m_ownerElement; if (!ownerElement) - return 0; - auto object = ownerElement->renderer(); - if (!object) - return 0; + return nullptr; + auto* object = ownerElement->renderer(); // FIXME: If <object> is ever fixed to disassociate itself from frames // that it has started but canceled, then this can turn into an ASSERT - // since m_ownerElement would be 0 when the load is canceled. + // since m_ownerElement would be nullptr when the load is canceled. // https://bugs.webkit.org/show_bug.cgi?id=18585 - if (!object->isWidget()) - return 0; - return toRenderWidget(object); + if (!is<RenderWidget>(object)) + return nullptr; + return downcast<RenderWidget>(object); } -Frame* Frame::frameForWidget(const Widget* widget) +Frame* Frame::frameForWidget(const Widget& widget) { - ASSERT_ARG(widget, widget); - - if (RenderWidget* renderer = RenderWidget::find(widget)) + if (auto* renderer = RenderWidget::find(widget)) return renderer->frameOwnerElement().document().frame(); // Assume all widgets are either a FrameView or owned by a RenderWidget. // FIXME: That assumption is not right for scroll bars! - ASSERT_WITH_SECURITY_IMPLICATION(widget->isFrameView()); - return &toFrameView(widget)->frame(); + return &downcast<FrameView>(widget).frame(); } void Frame::clearTimers(FrameView *view, Document *document) @@ -798,35 +779,34 @@ void Frame::willDetachPage() // FIXME: It's unclear as to why this is called more than once, but it is, // so page() could be NULL. if (page() && page()->focusController().focusedFrame() == this) - page()->focusController().setFocusedFrame(0); + page()->focusController().setFocusedFrame(nullptr); if (page() && page()->scrollingCoordinator() && m_view) - page()->scrollingCoordinator()->willDestroyScrollableArea(m_view.get()); + page()->scrollingCoordinator()->willDestroyScrollableArea(*m_view); #if PLATFORM(IOS) if (WebThreadCountOfObservedContentModifiers() > 0 && m_page) - m_page->chrome().client().clearContentChangeObservers(this); + m_page->chrome().client().clearContentChangeObservers(*this); #endif script().clearScriptObjects(); script().updatePlatformScriptObjects(); + + // We promise that the Frame is always connected to a Page while the render tree is live. + // + // The render tree can be torn down in a few different ways, but the two important ones are: + // + // - When calling Frame::setView() with a null FrameView*. This is always done before calling + // Frame::willDetachPage (this function.) Hence the assertion below. + // + // - When adding a document to the page cache, the tree is torn down before instantiating + // the CachedPage+CachedFrame object tree. + ASSERT(!document() || !document()->renderView()); } void Frame::disconnectOwnerElement() { if (m_ownerElement) { - // We use the ownerElement's document to retrieve the cache, because the contentDocument for this - // frame is already detached (and can't access the top level AX cache). - // However, we pass in the current document to clearTextMarkerNodesInUse so we can identify the - // nodes inside this document that need to be removed from the cache. - - // We don't clear the AXObjectCache here because we don't want to clear the top level cache - // when a sub-frame is removed. -#if HAVE(ACCESSIBILITY) - if (AXObjectCache* cache = m_ownerElement->document().existingAXObjectCache()) - cache->clearTextMarkerNodesInUse(document()); -#endif - m_ownerElement->clearContentFrame(); if (m_page) m_page->decrementSubframeCount(); @@ -839,7 +819,7 @@ String Frame::displayStringModifiedByEncoding(const String& str) const return document() ? document()->displayStringModifiedByEncoding(str) : str; } -VisiblePosition Frame::visiblePositionForPoint(const IntPoint& framePoint) +VisiblePosition Frame::visiblePositionForPoint(const IntPoint& framePoint) const { HitTestResult result = eventHandler().hitTestResultAtPoint(framePoint, HitTestRequest::ReadOnly | HitTestRequest::Active); Node* node = result.innerNonSharedNode(); @@ -848,7 +828,7 @@ VisiblePosition Frame::visiblePositionForPoint(const IntPoint& framePoint) auto renderer = node->renderer(); if (!renderer) return VisiblePosition(); - VisiblePosition visiblePos = renderer->positionForPoint(result.localPoint()); + VisiblePosition visiblePos = renderer->positionForPoint(result.localPoint(), nullptr); if (visiblePos.isNull()) visiblePos = firstPositionInOrBeforeNode(node); return visiblePos; @@ -857,7 +837,7 @@ VisiblePosition Frame::visiblePositionForPoint(const IntPoint& framePoint) Document* Frame::documentAtPoint(const IntPoint& point) { if (!view()) - return 0; + return nullptr; IntPoint pt = view()->windowToContents(point); HitTestResult result = HitTestResult(pt); @@ -867,28 +847,33 @@ Document* Frame::documentAtPoint(const IntPoint& point) return result.innerNode() ? &result.innerNode()->document() : 0; } -PassRefPtr<Range> Frame::rangeForPoint(const IntPoint& framePoint) +RefPtr<Range> Frame::rangeForPoint(const IntPoint& framePoint) { VisiblePosition position = visiblePositionForPoint(framePoint); if (position.isNull()) - return 0; + return nullptr; + + Position deepPosition = position.deepEquivalent(); + Text* containerText = deepPosition.containerText(); + if (!containerText || !containerText->renderer() || containerText->renderer()->style().userSelect() == SELECT_NONE) + return nullptr; VisiblePosition previous = position.previous(); if (previous.isNotNull()) { RefPtr<Range> previousCharacterRange = makeRange(previous, position); LayoutRect rect = editor().firstRectForRange(previousCharacterRange.get()); if (rect.contains(framePoint)) - return previousCharacterRange.release(); + return previousCharacterRange; } VisiblePosition next = position.next(); if (RefPtr<Range> nextCharacterRange = makeRange(position, next)) { LayoutRect rect = editor().firstRectForRange(nextCharacterRange.get()); if (rect.contains(framePoint)) - return nextCharacterRange.release(); + return nextCharacterRange; } - return 0; + return nullptr; } void Frame::createView(const IntSize& viewportSize, const Color& backgroundColor, bool transparent, @@ -896,7 +881,6 @@ void Frame::createView(const IntSize& viewportSize, const Color& backgroundColor bool useFixedLayout, ScrollbarMode horizontalScrollbarMode, bool horizontalLock, ScrollbarMode verticalScrollbarMode, bool verticalLock) { - ASSERT(this); ASSERT(m_page); bool isMainFrame = this->isMainFrame(); @@ -904,13 +888,13 @@ void Frame::createView(const IntSize& viewportSize, const Color& backgroundColor if (isMainFrame && view()) view()->setParentVisible(false); - setView(0); + setView(nullptr); RefPtr<FrameView> frameView; if (isMainFrame) { frameView = FrameView::create(*this, viewportSize); frameView->setFixedLayoutSize(fixedLayoutSize); -#if USE(TILED_BACKING_STORE) +#if USE(COORDINATED_GRAPHICS) frameView->setFixedVisibleContentRect(fixedVisibleContentRect); #else UNUSED_PARAM(fixedVisibleContentRect); @@ -921,7 +905,7 @@ void Frame::createView(const IntSize& viewportSize, const Color& backgroundColor frameView->setScrollbarModes(horizontalScrollbarMode, verticalScrollbarMode, horizontalLock, verticalLock); - setView(frameView); + setView(frameView.copyRef()); if (backgroundColor.isValid()) frameView->updateBackgroundRecursively(backgroundColor, transparent); @@ -936,80 +920,14 @@ void Frame::createView(const IntSize& viewportSize, const Color& backgroundColor view()->setCanHaveScrollbars(owner->scrollingMode() != ScrollbarAlwaysOff); } -#if USE(TILED_BACKING_STORE) -void Frame::setTiledBackingStoreEnabled(bool enabled) -{ - if (!enabled) { - m_tiledBackingStore.clear(); - return; - } - if (m_tiledBackingStore) - return; - m_tiledBackingStore = adoptPtr(new TiledBackingStore(this)); - m_tiledBackingStore->setCommitTileUpdatesOnIdleEventLoop(true); - if (m_view) - m_view->setPaintsEntireContents(true); -} - -void Frame::tiledBackingStorePaintBegin() -{ - if (!m_view) - return; - m_view->updateLayoutAndStyleIfNeededRecursive(); -} - -void Frame::tiledBackingStorePaint(GraphicsContext* context, const IntRect& rect) -{ - if (!m_view) - return; - m_view->paintContents(context, rect); -} - -void Frame::tiledBackingStorePaintEnd(const Vector<IntRect>& paintedArea) -{ - if (!m_page || !m_view) - return; - unsigned size = paintedArea.size(); - // Request repaint from the system - for (unsigned n = 0; n < size; ++n) - m_page->chrome().invalidateContentsAndRootView(m_view->contentsToRootView(paintedArea[n]), false); -} - -IntRect Frame::tiledBackingStoreContentsRect() -{ - if (!m_view) - return IntRect(); - return IntRect(IntPoint(), m_view->contentsSize()); -} - -IntRect Frame::tiledBackingStoreVisibleRect() -{ - if (!m_page) - return IntRect(); - return m_page->chrome().client().visibleRectForTiledBackingStore(); -} - -Color Frame::tiledBackingStoreBackgroundColor() const -{ - if (!m_view) - return Color(); - return m_view->baseBackgroundColor(); -} -#endif - String Frame::layerTreeAsText(LayerTreeFlags flags) const { -#if USE(ACCELERATED_COMPOSITING) document()->updateLayout(); if (!contentRenderer()) return String(); return contentRenderer()->compositor().layerTreeAsText(flags); -#else - UNUSED_PARAM(flags); - return String(); -#endif } String Frame::trackedRepaintRectsAsText() const @@ -1044,14 +962,10 @@ void Frame::setPageAndTextZoomFactors(float pageZoomFactor, float textZoomFactor m_editor->dismissCorrectionPanelAsIgnored(); -#if ENABLE(SVG) // Respect SVGs zoomAndPan="disabled" property in standalone SVG documents. // FIXME: How to handle compound documents + zoomAndPan="disabled"? Needs SVG WG clarification. - if (document->isSVGDocument()) { - if (!toSVGDocument(document)->zoomAndPanEnabled()) - return; - } -#endif + if (is<SVGDocument>(*document) && !downcast<SVGDocument>(*document).zoomAndPanEnabled()) + return; if (m_pageZoomFactor != pageZoomFactor) { if (FrameView* view = this->view()) { @@ -1074,9 +988,6 @@ void Frame::setPageAndTextZoomFactors(float pageZoomFactor, float textZoomFactor if (document->renderView() && document->renderView()->needsLayout() && view->didFirstLayout()) view->layout(); } - - if (isMainFrame()) - pageCache()->markPagesForFullStyleRecalc(page); } float Frame::frameScaleFactor() const @@ -1100,30 +1011,33 @@ void Frame::suspendActiveDOMObjectsAndAnimations() return; // FIXME: Suspend/resume calls will not match if the frame is navigated, and gets a new document. - if (document()) { - document()->suspendScriptedAnimationControllerCallbacks(); - animation().suspendAnimationsForDocument(document()); - document()->suspendActiveDOMObjects(ActiveDOMObject::PageWillBeSuspended); - } + clearTimers(); // Suspends animations and pending relayouts. + if (m_doc) + m_doc->suspendScheduledTasks(ActiveDOMObject::PageWillBeSuspended); } void Frame::resumeActiveDOMObjectsAndAnimations() { - ASSERT(activeDOMObjectsAndAnimationsSuspended()); + if (!activeDOMObjectsAndAnimationsSuspended()) + return; m_activeDOMObjectsAndAnimationsSuspendedCount--; if (activeDOMObjectsAndAnimationsSuspended()) return; - if (document()) { - document()->resumeActiveDOMObjects(ActiveDOMObject::PageWillBeSuspended); - animation().resumeAnimationsForDocument(document()); - document()->resumeScriptedAnimationControllerCallbacks(); - } + if (!m_doc) + return; + + // FIXME: Suspend/resume calls will not match if the frame is navigated, and gets a new document. + m_doc->resumeScheduledTasks(ActiveDOMObject::PageWillBeSuspended); + + // Frame::clearTimers() suspended animations and pending relayouts. + animation().resumeAnimationsForDocument(m_doc.get()); + if (m_view) + m_view->scheduleRelayout(); } -#if USE(ACCELERATED_COMPOSITING) void Frame::deviceOrPageScaleFactorChanged() { for (RefPtr<Frame> child = tree().firstChild(); child; child = child->tree().nextSibling()) @@ -1132,7 +1046,6 @@ void Frame::deviceOrPageScaleFactorChanged() if (RenderView* root = contentRenderer()) root->compositor().deviceOrPageScaleFactorChanged(); } -#endif bool Frame::isURLAllowed(const URL& url) const { @@ -1151,4 +1064,9 @@ bool Frame::isURLAllowed(const URL& url) const return true; } +bool Frame::isAlwaysOnLoggingAllowed() const +{ + return page() && page()->isAlwaysOnLoggingAllowed(); +} + } // namespace WebCore |