LayoutUnit LayoutMedia::computePanelWidth(const LayoutRect& mediaRect) const { // TODO(mlamouri): we don't know if the main frame has an horizontal scrollbar // if it is out of process. See https://crbug.com/662480 if (document().page()->mainFrame()->isRemoteFrame()) return mediaRect.width(); FrameHost* frameHost = document().frameHost(); LocalFrame* mainFrame = document().page()->deprecatedLocalMainFrame(); FrameView* pageView = mainFrame ? mainFrame->view() : nullptr; if (!frameHost || !mainFrame || !pageView) return mediaRect.width(); if (pageView->horizontalScrollbarMode() != ScrollbarAlwaysOff) return mediaRect.width(); // On desktop, this will include scrollbars when they stay visible. const LayoutUnit visibleWidth(frameHost->visualViewport().visibleWidth()); const LayoutUnit absoluteXOffset( localToAbsolute( FloatPoint(mediaRect.location()), UseTransforms | ApplyContainerFlip | TraverseDocumentBoundaries) .x()); DCHECK_GE(visibleWidth - absoluteXOffset, 0); return std::min(mediaRect.width(), visibleWidth - absoluteXOffset); }
int Screen::availTop() const { if (!m_frame) return 0; FrameHost* host = m_frame->host(); if (host && host->settings().reportScreenSizeInPhysicalPixelsQuirk()) return lroundf(screenAvailableRect(m_frame->view()).y() * host->deviceScaleFactor()); return static_cast<int>(screenAvailableRect(m_frame->view()).y()); }
unsigned Screen::width() const { if (!m_frame) return 0; FrameHost* host = m_frame->host(); if (host && host->settings().reportScreenSizeInPhysicalPixelsQuirk()) return lroundf(screenRect(m_frame->view()).width() * host->deviceScaleFactor()); return static_cast<unsigned>(screenRect(m_frame->view()).width()); }
void UseCounter::count(const Document& document, Feature feature) { FrameHost* host = document.frameHost(); if (!host) return; ASSERT(host->useCounter().deprecationMessage(feature).isEmpty()); host->useCounter().recordMeasurement(feature); }
bool UseCounter::isCounted(Document& document, Feature feature) { Frame* frame = document.frame(); if (!frame) return false; FrameHost* host = frame->host(); if (!host) return false; return host->useCounter().hasRecordedMeasurement(feature); }
int Screen::width() const { if (!m_frame) return 0; FrameHost* host = m_frame->host(); if (!host) return 0; if (host->settings().reportScreenSizeInPhysicalPixelsQuirk()) return lroundf(host->chromeClient().screenInfo().rect.width * host->deviceScaleFactor()); return host->chromeClient().screenInfo().rect.width; }
int Screen::availTop() const { if (!m_frame) return 0; FrameHost* host = m_frame->host(); if (!host) return 0; if (host->settings().reportScreenSizeInPhysicalPixelsQuirk()) return lroundf(host->chromeClient().screenInfo().availableRect.y * host->deviceScaleFactor()); return static_cast<int>(host->chromeClient().screenInfo().availableRect.y); }
void UseCounter::count(const Frame* frame, Feature feature) { if (!frame) return; FrameHost* host = frame->host(); if (!host) return; ASSERT(host->useCounter().deprecationMessage(feature).isEmpty()); host->useCounter().recordMeasurement(feature); }
void UseCounter::countDeprecation(const Document& document, Feature feature) { FrameHost* host = document.frameHost(); if (!host) return; if (host->useCounter().recordMeasurement(feature)) { ASSERT(!host->useCounter().deprecationMessage(feature).isEmpty()); host->console().addMessage(DeprecationMessageSource, WarningMessageLevel, host->useCounter().deprecationMessage(feature)); } }
void Deprecation::warnOnDeprecatedProperties(const LocalFrame* frame, CSSPropertyID unresolvedProperty) { FrameHost* host = frame ? frame->host() : nullptr; if (!host || host->deprecation().isSuppressed(unresolvedProperty)) return; String message = deprecationMessage(unresolvedProperty); if (!message.isEmpty()) { host->deprecation().suppress(unresolvedProperty); frame->console().addMessage(ConsoleMessage::create(DeprecationMessageSource, WarningMessageLevel, message)); } }
void UseCounter::countDeprecation(const LocalFrame* frame, Feature feature) { if (!frame) return; FrameHost* host = frame->host(); if (!host) return; if (host->useCounter().recordMeasurement(feature)) { ASSERT(!host->useCounter().deprecationMessage(feature).isEmpty()); frame->console().addMessage(ConsoleMessage::create(DeprecationMessageSource, WarningMessageLevel, host->useCounter().deprecationMessage(feature))); } }
bool UseCounter::isCounted(Document& document, const String& string) { Frame* frame = document.frame(); if (!frame) return false; FrameHost* host = frame->host(); if (!host) return false; CSSPropertyID propertyID = cssPropertyID(string); if (propertyID == CSSPropertyInvalid) return false; return host->useCounter().isCounted(propertyID); }
void HTMLAnchorElement::handleClick(Event* event) { Frame* frame = document().frame(); if (!frame) return; FrameHost* host = frame->host(); if (!host) return; mojo::URLRequestPtr request = mojo::URLRequest::New(); request->url = href().string().toUTF8(); host->services().NavigatorHost()->RequestNavigate( mojo::TARGET_SOURCE_NODE, request.Pass()); event->setDefaultHandled(); }
bool BarProp::visible() const { if (!frame()) return false; FrameHost* host = frame()->host(); if (!host) return false; switch (m_type) { case Locationbar: case Personalbar: case Toolbar: return host->chromeClient().toolbarsVisible(); case Menubar: return host->chromeClient().menubarVisible(); case Scrollbars: return host->chromeClient().scrollbarsVisible(); case Statusbar: return host->chromeClient().statusbarVisible(); } ASSERT_NOT_REACHED(); return false; }
Storage* DOMWindowStorage::localStorage(ExceptionState& exceptionState) const { if (!m_window->isCurrentlyDisplayedInFrame()) return nullptr; Document* document = m_window->document(); if (!document) return nullptr; String accessDeniedMessage = "Access is denied for this document."; if (!document->securityOrigin()->canAccessLocalStorage()) { if (document->isSandboxed(SandboxOrigin)) exceptionState.throwSecurityError("The document is sandboxed and lacks the 'allow-same-origin' flag."); else if (document->url().protocolIs("data")) exceptionState.throwSecurityError("Storage is disabled inside 'data:' URLs."); else exceptionState.throwSecurityError(accessDeniedMessage); return nullptr; } if (m_localStorage) { if (!m_localStorage->area()->canAccessStorage(m_window->frame())) { exceptionState.throwSecurityError(accessDeniedMessage); return nullptr; } return m_localStorage; } // FIXME: Seems this check should be much higher? FrameHost* host = document->frameHost(); if (!host || !host->settings().localStorageEnabled()) return nullptr; StorageArea* storageArea = StorageNamespace::localStorageArea(document->securityOrigin()); if (!storageArea->canAccessStorage(m_window->frame())) { exceptionState.throwSecurityError(accessDeniedMessage); return nullptr; } m_localStorage = Storage::create(m_window->frame(), storageArea); return m_localStorage; }
static Frame* createNewWindow(LocalFrame& openerFrame, const FrameLoadRequest& request, const WindowFeatures& features, NavigationPolicy policy, bool& created) { FrameHost* oldHost = openerFrame.host(); if (!oldHost) return nullptr; Page* page = oldHost->chromeClient().createWindow(&openerFrame, request, features, policy); if (!page) return nullptr; FrameHost* host = &page->frameHost(); ASSERT(page->mainFrame()); LocalFrame& frame = *toLocalFrame(page->mainFrame()); if (request.frameName() != "_blank") frame.tree().setName(request.frameName()); host->chromeClient().setWindowFeatures(features); // 'x' and 'y' specify the location of the window, while 'width' and 'height' // specify the size of the viewport. We can only resize the window, so adjust // for the difference between the window size and the viewport size. IntRect windowRect = host->chromeClient().windowRect(); IntSize viewportSize = host->chromeClient().pageRect().size(); if (features.xSet) windowRect.setX(features.x); if (features.ySet) windowRect.setY(features.y); if (features.widthSet) windowRect.setWidth(features.width + (windowRect.width() - viewportSize.width())); if (features.heightSet) windowRect.setHeight(features.height + (windowRect.height() - viewportSize.height())); host->chromeClient().setWindowRectWithAdjustment(windowRect); host->chromeClient().show(policy); if (openerFrame.document()->isSandboxed(SandboxPropagatesToAuxiliaryBrowsingContexts)) frame.loader().forceSandboxFlags(openerFrame.securityContext()->getSandboxFlags()); // This call may suspend the execution by running nested message loop. InspectorInstrumentation::windowCreated(&openerFrame, &frame); created = true; return &frame; }
void FullscreenElementStack::webkitExitFullscreen() { // The exitFullscreen() method must run these steps: // 1. Let doc be the context object. (i.e. "this") Document* currentDoc = document(); ASSERT(currentDoc->isActive()); // 2. If doc's fullscreen element stack is empty, terminate these steps. if (m_fullScreenElementStack.isEmpty()) return; // 3. Let descendants be all the doc's descendant browsing context's documents with a non-empty fullscreen // element stack (if any), ordered so that the child of the doc is last and the document furthest // away from the doc is first. Deque<RefPtr<Document> > descendants; for (Frame* descendant = document()->frame() ? document()->frame()->tree().traverseNext() : 0; descendant; descendant = descendant->tree().traverseNext()) { if (fullscreenElementFrom(descendant->document())) descendants.prepend(descendant->document()); } // 4. For each descendant in descendants, empty descendant's fullscreen element stack, and queue a // task to fire an event named fullscreenchange with its bubbles attribute set to true on descendant. for (Deque<RefPtr<Document> >::iterator i = descendants.begin(); i != descendants.end(); ++i) { from(i->get())->clearFullscreenElementStack(); addDocumentToFullScreenChangeEventQueue(i->get()); } // 5. While doc is not null, run these substeps: Element* newTop = 0; while (currentDoc) { // 1. Pop the top element of doc's fullscreen element stack. from(currentDoc)->popFullscreenElementStack(); // If doc's fullscreen element stack is non-empty and the element now at the top is either // not in a document or its node document is not doc, repeat this substep. newTop = fullscreenElementFrom(currentDoc); if (newTop && (!newTop->inDocument() || newTop->document() != currentDoc)) continue; // 2. Queue a task to fire an event named fullscreenchange with its bubbles attribute set to true // on doc. addDocumentToFullScreenChangeEventQueue(currentDoc); // 3. If doc's fullscreen element stack is empty and doc's browsing context has a browsing context // container, set doc to that browsing context container's node document. if (!newTop && currentDoc->ownerElement()) { currentDoc = ¤tDoc->ownerElement()->document(); continue; } // 4. Otherwise, set doc to null. currentDoc = 0; } // 6. Return, and run the remaining steps asynchronously. // 7. Optionally, perform some animation. FrameHost* host = document()->frameHost(); // Speculative fix for engaget.com/videos per crbug.com/336239. // FIXME: This check is wrong. We ASSERT(document->isActive()) above // so this should be redundant and should be removed! if (!host) return; // Only exit out of full screen window mode if there are no remaining elements in the // full screen stack. if (!newTop) { host->chrome().client().exitFullScreenForElement(m_fullScreenElement.get()); return; } // Otherwise, notify the chrome of the new full screen element. host->chrome().client().enterFullScreenForElement(newTop); }
static Frame* createWindow(LocalFrame& openerFrame, LocalFrame& lookupFrame, const FrameLoadRequest& request, const WindowFeatures& features, NavigationPolicy policy, ShouldSetOpener shouldSetOpener, bool& created) { created = false; ASSERT(!features.dialog || request.frameName().isEmpty()); ASSERT(request.resourceRequest().requestorOrigin() || openerFrame.document()->url().isEmpty()); ASSERT(request.resourceRequest().frameType() == WebURLRequest::FrameTypeAuxiliary); if (!request.frameName().isEmpty() && request.frameName() != "_blank" && policy == NavigationPolicyIgnore) { if (Frame* frame = lookupFrame.findFrameForNavigation(request.frameName(), openerFrame)) { if (request.frameName() != "_self") { if (FrameHost* host = frame->host()) { if (host == openerFrame.host()) frame->page()->focusController().setFocusedFrame(frame); else host->chromeClient().focus(); } } return frame; } } // Sandboxed frames cannot open new auxiliary browsing contexts. if (openerFrame.document()->isSandboxed(SandboxPopups)) { // FIXME: This message should be moved off the console once a solution to https://bugs.webkit.org/show_bug.cgi?id=103274 exists. openerFrame.document()->addConsoleMessage(ConsoleMessage::create(SecurityMessageSource, ErrorMessageLevel, "Blocked opening '" + request.resourceRequest().url().elidedString() + "' in a new window because the request was made in a sandboxed frame whose 'allow-popups' permission is not set.")); return nullptr; } if (openerFrame.settings() && !openerFrame.settings()->supportsMultipleWindows()) return openerFrame.tree().top(); FrameHost* oldHost = openerFrame.host(); if (!oldHost) return nullptr; Page* page = oldHost->chromeClient().createWindow(&openerFrame, request, features, policy, shouldSetOpener); if (!page) return nullptr; FrameHost* host = &page->frameHost(); ASSERT(page->mainFrame()); Frame& frame = *page->mainFrame(); if (request.frameName() != "_blank") frame.tree().setName(request.frameName()); host->chromeClient().setWindowFeatures(features); // 'x' and 'y' specify the location of the window, while 'width' and 'height' // specify the size of the viewport. We can only resize the window, so adjust // for the difference between the window size and the viewport size. IntRect windowRect = host->chromeClient().windowRect(); IntSize viewportSize = host->chromeClient().pageRect().size(); if (features.xSet) windowRect.setX(features.x); if (features.ySet) windowRect.setY(features.y); if (features.widthSet) windowRect.setWidth(features.width + (windowRect.width() - viewportSize.width())); if (features.heightSet) windowRect.setHeight(features.height + (windowRect.height() - viewportSize.height())); host->chromeClient().setWindowRectWithAdjustment(windowRect); host->chromeClient().show(policy); // TODO(japhet): There's currently no way to set sandbox flags on a RemoteFrame and have it propagate // to the real frame in a different process. See crbug.com/483584. if (frame.isLocalFrame() && openerFrame.document()->isSandboxed(SandboxPropagatesToAuxiliaryBrowsingContexts)) toLocalFrame(&frame)->loader().forceSandboxFlags(openerFrame.document()->sandboxFlags()); created = true; return &frame; }
// https://fullscreen.spec.whatwg.org/#exit-fullscreen void Fullscreen::exitFullscreen(Document& document) { // The exitFullscreen() method must run these steps: // 1. Let doc be the context object. (i.e. "this") if (!document.isActive()) return; // 2. If doc's fullscreen element stack is empty, terminate these steps. if (!fullscreenElementFrom(document)) return; // 3. Let descendants be all the doc's descendant browsing context's documents // with a non-empty fullscreen element stack (if any), ordered so that the // child of the doc is last and the document furthest away from the doc is // first. HeapDeque<Member<Document>> descendants; for (Frame* descendant = document.frame() ? document.frame()->tree().traverseNext() : nullptr; descendant; descendant = descendant->tree().traverseNext()) { if (!descendant->isLocalFrame()) continue; DCHECK(toLocalFrame(descendant)->document()); if (fullscreenElementFrom(*toLocalFrame(descendant)->document())) descendants.prepend(toLocalFrame(descendant)->document()); } // 4. For each descendant in descendants, empty descendant's fullscreen // element stack, and queue a task to fire an event named fullscreenchange // with its bubbles attribute set to true on descendant. for (auto& descendant : descendants) { DCHECK(descendant); RequestType requestType = from(*descendant).m_fullscreenElementStack.last().second; from(*descendant).clearFullscreenElementStack(); from(document).enqueueChangeEvent(*descendant, requestType); } // 5. While doc is not null, run these substeps: Element* newTop = nullptr; for (Document* currentDoc = &document; currentDoc;) { RequestType requestType = from(*currentDoc).m_fullscreenElementStack.last().second; // 1. Pop the top element of doc's fullscreen element stack. from(*currentDoc).popFullscreenElementStack(); // If doc's fullscreen element stack is non-empty and the element now at // the top is either not in a document or its node document is not doc, // repeat this substep. newTop = fullscreenElementFrom(*currentDoc); if (newTop && (!newTop->isConnected() || newTop->document() != currentDoc)) continue; // 2. Queue a task to fire an event named fullscreenchange with its bubbles // attribute set to true on doc. from(document).enqueueChangeEvent(*currentDoc, requestType); // 3. If doc's fullscreen element stack is empty and doc's browsing context // has a browsing context container, set doc to that browsing context // container's node document. // // OOPIF: If browsing context container's document is in another // process, keep moving up the ancestor chain and looking for a // browsing context container with a local document. // TODO(alexmos): Deal with nested fullscreen cases, see // https://crbug.com/617369. if (!newTop) { Frame* frame = currentDoc->frame()->tree().parent(); while (frame && frame->isRemoteFrame()) frame = frame->tree().parent(); if (frame) { currentDoc = toLocalFrame(frame)->document(); continue; } } // 4. Otherwise, set doc to null. currentDoc = nullptr; } // 6. Return, and run the remaining steps asynchronously. // 7. Optionally, perform some animation. FrameHost* host = document.frameHost(); // Speculative fix for engaget.com/videos per crbug.com/336239. // FIXME: This check is wrong. We DCHECK(document->isActive()) above // so this should be redundant and should be removed! if (!host) return; // Only exit out of full screen window mode if there are no remaining elements // in the full screen stack. if (!newTop) { // FIXME: if the frame exiting fullscreen is not the frame that entered // fullscreen (but a parent frame for example), // m_currentFullScreenElement might be null. We want to pass an element // that is part of the document so we will pass the documentElement in // that case. This should be fix by exiting fullscreen for a frame // instead of an element, see https://crbug.com/441259 Element* currentFullScreenElement = currentFullScreenElementFrom(document); host->chromeClient().exitFullscreenForElement( currentFullScreenElement ? currentFullScreenElement : document.documentElement()); return; } // Otherwise, notify the chrome of the new full screen element. host->chromeClient().enterFullscreenForElement(newTop); }
void Fullscreen::exitFullscreen() { // The exitFullscreen() method must run these steps: // 1. Let doc be the context object. (i.e. "this") Document* currentDoc = document(); if (!currentDoc->isActive()) return; // 2. If doc's fullscreen element stack is empty, terminate these steps. if (m_fullScreenElementStack.isEmpty()) return; // 3. Let descendants be all the doc's descendant browsing context's documents with a non-empty fullscreen // element stack (if any), ordered so that the child of the doc is last and the document furthest // away from the doc is first. WillBeHeapDeque<RefPtrWillBeMember<Document> > descendants; for (Frame* descendant = document()->frame() ? document()->frame()->tree().traverseNext() : 0; descendant; descendant = descendant->tree().traverseNext()) { if (!descendant->isLocalFrame()) continue; ASSERT(toLocalFrame(descendant)->document()); if (fullscreenElementFrom(*toLocalFrame(descendant)->document())) descendants.prepend(toLocalFrame(descendant)->document()); } // 4. For each descendant in descendants, empty descendant's fullscreen element stack, and queue a // task to fire an event named fullscreenchange with its bubbles attribute set to true on descendant. for (WillBeHeapDeque<RefPtrWillBeMember<Document> >::iterator i = descendants.begin(); i != descendants.end(); ++i) { ASSERT(*i); RequestType requestType = from(**i).m_fullScreenElementStack.last().second; from(**i).clearFullscreenElementStack(); enqueueChangeEvent(**i, requestType); } // 5. While doc is not null, run these substeps: Element* newTop = 0; while (currentDoc) { RequestType requestType = from(*currentDoc).m_fullScreenElementStack.last().second; // 1. Pop the top element of doc's fullscreen element stack. from(*currentDoc).popFullscreenElementStack(); // If doc's fullscreen element stack is non-empty and the element now at the top is either // not in a document or its node document is not doc, repeat this substep. newTop = fullscreenElementFrom(*currentDoc); if (newTop && (!newTop->inDocument() || newTop->document() != currentDoc)) continue; // 2. Queue a task to fire an event named fullscreenchange with its bubbles attribute set to true // on doc. enqueueChangeEvent(*currentDoc, requestType); // 3. If doc's fullscreen element stack is empty and doc's browsing context has a browsing context // container, set doc to that browsing context container's node document. if (!newTop && currentDoc->ownerElement()) { currentDoc = ¤tDoc->ownerElement()->document(); continue; } // 4. Otherwise, set doc to null. currentDoc = 0; } // 6. Return, and run the remaining steps asynchronously. // 7. Optionally, perform some animation. FrameHost* host = document()->frameHost(); // Speculative fix for engaget.com/videos per crbug.com/336239. // FIXME: This check is wrong. We ASSERT(document->isActive()) above // so this should be redundant and should be removed! if (!host) return; // Only exit out of full screen window mode if there are no remaining elements in the // full screen stack. if (!newTop) { // FIXME: if the frame exiting fullscreen is not the frame that entered // fullscreen (but a parent frame for example), m_fullScreenElement // might be null. We want to pass an element that is part of the // document so we will pass the documentElement in that case. // This should be fix by exiting fullscreen for a frame instead of an // element, see https://crbug.com/441259 host->chrome().client().exitFullScreenForElement( m_fullScreenElement ? m_fullScreenElement.get() : document()->documentElement()); return; } // Otherwise, notify the chrome of the new full screen element. host->chrome().client().enterFullScreenForElement(newTop); }
static Frame* createWindow(Frame* openerFrame, Frame* lookupFrame, const FrameLoadRequest& request, const WindowFeatures& features, NavigationPolicy policy, ShouldSendReferrer shouldSendReferrer, bool& created) { ASSERT(!features.dialog || request.frameName().isEmpty()); if (!request.frameName().isEmpty() && request.frameName() != "_blank" && policy == NavigationPolicyIgnore) { if (Frame* frame = lookupFrame->loader().findFrameForNavigation(request.frameName(), openerFrame->document())) { if (request.frameName() != "_self") frame->page()->focusController().setFocusedFrame(frame); created = false; return frame; } } // Sandboxed frames cannot open new auxiliary browsing contexts. if (openerFrame->document()->isSandboxed(SandboxPopups)) { // FIXME: This message should be moved off the console once a solution to https://bugs.webkit.org/show_bug.cgi?id=103274 exists. openerFrame->document()->addConsoleMessage(SecurityMessageSource, ErrorMessageLevel, "Blocked opening '" + request.resourceRequest().url().elidedString() + "' in a new window because the request was made in a sandboxed frame whose 'allow-popups' permission is not set."); return 0; } if (openerFrame->settings() && !openerFrame->settings()->supportsMultipleWindows()) { created = false; return openerFrame->tree().top(); } Page* oldPage = openerFrame->page(); if (!oldPage) return 0; Page* page = oldPage->chrome().client().createWindow(openerFrame, request, features, policy, shouldSendReferrer); if (!page) return 0; FrameHost* host = &page->frameHost(); Frame* frame = page->mainFrame(); frame->loader().forceSandboxFlags(openerFrame->document()->sandboxFlags()); if (request.frameName() != "_blank") frame->tree().setName(request.frameName()); host->chrome().setWindowFeatures(features); // 'x' and 'y' specify the location of the window, while 'width' and 'height' // specify the size of the viewport. We can only resize the window, so adjust // for the difference between the window size and the viewport size. FloatRect windowRect = host->chrome().windowRect(); FloatSize viewportSize = host->chrome().pageRect().size(); if (features.xSet) windowRect.setX(features.x); if (features.ySet) windowRect.setY(features.y); if (features.widthSet) windowRect.setWidth(features.width + (windowRect.width() - viewportSize.width())); if (features.heightSet) windowRect.setHeight(features.height + (windowRect.height() - viewportSize.height())); // Ensure non-NaN values, minimum size as well as being within valid screen area. FloatRect newWindowRect = DOMWindow::adjustWindowRect(frame, windowRect); host->chrome().setWindowRect(newWindowRect); host->chrome().show(policy); created = true; return frame; }