void PageOverlay::update() { if (!m_frameImpl->frameWidget()->isAcceleratedCompositingActive()) return; LocalFrame* frame = m_frameImpl->frame(); if (!frame) return; if (!m_layer) { m_layer = GraphicsLayer::create(this); m_layer->setDrawsContent(true); if (WebDevToolsAgentImpl* devTools = m_frameImpl->devToolsAgentImpl()) devTools->willAddPageOverlay(m_layer.get()); // This is required for contents of overlay to stay in sync with the page // while scrolling. WebLayer* platformLayer = m_layer->platformLayer(); platformLayer->addMainThreadScrollingReasons( MainThreadScrollingReason::kPageOverlay); if (frame->isMainFrame()) { frame->host()->visualViewport().containerLayer()->addChild(m_layer.get()); } else { toWebFrameWidgetImpl(m_frameImpl->frameWidget()) ->rootGraphicsLayer() ->addChild(m_layer.get()); } } FloatSize size(frame->host()->visualViewport().size()); if (size != m_layer->size()) m_layer->setSize(size); m_layer->setNeedsDisplay(); }
void MainThreadDebugger::unmuteMetrics(int contextGroupId) { LocalFrame* frame = WeakIdentifierMap<LocalFrame>::lookup(contextGroupId); if (frame && frame->host()) { frame->host()->useCounter().unmuteForInspector(); frame->host()->deprecation().unmuteForInspector(); } }
void InspectorOverlay::scheduleUpdate() { if (isEmpty()) { if (m_pageOverlay) m_pageOverlay.reset(); return; } m_needsUpdate = true; FrameView* view = m_frameImpl->frameView(); LocalFrame* frame = m_frameImpl->frame(); if (view && frame) frame->host()->chromeClient().scheduleAnimation(view); }
void MainThreadDebugger::consoleAPIMessage( int contextGroupId, v8_inspector::V8ConsoleAPIType type, const v8_inspector::StringView& message, const v8_inspector::StringView& url, unsigned lineNumber, unsigned columnNumber, v8_inspector::V8StackTrace* stackTrace) { LocalFrame* frame = WeakIdentifierMap<LocalFrame>::lookup(contextGroupId); if (!frame) return; if (type == v8_inspector::V8ConsoleAPIType::kClear && frame->host()) frame->host()->consoleMessageStorage().clear(); // TODO(dgozman): we can save a copy of message and url here by making // FrameConsole work with StringView. std::unique_ptr<SourceLocation> location = SourceLocation::create(toCoreString(url), lineNumber, columnNumber, stackTrace ? stackTrace->clone() : nullptr, 0); frame->console().reportMessageToClient(ConsoleAPIMessageSource, consoleAPITypeToMessageLevel(type), toCoreString(message), location.get()); }
AtomicString V8CustomXPathNSResolver::lookupNamespaceURI(const String& prefix) { v8::Handle<v8::Function> lookupNamespaceURIFunc; v8::Handle<v8::String> lookupNamespaceURIName = v8AtomicString(m_isolate, "lookupNamespaceURI"); // Check if the resolver has a function property named lookupNamespaceURI. if (m_resolver->Has(lookupNamespaceURIName)) { v8::Handle<v8::Value> lookupNamespaceURI = m_resolver->Get(lookupNamespaceURIName); if (lookupNamespaceURI->IsFunction()) lookupNamespaceURIFunc = v8::Handle<v8::Function>::Cast(lookupNamespaceURI); } if (lookupNamespaceURIFunc.IsEmpty() && !m_resolver->IsFunction()) { LocalFrame* frame = callingDOMWindow(m_isolate)->frame(); if (frame && frame->host()) frame->host()->console().addMessage(JSMessageSource, ErrorMessageLevel, "XPathNSResolver does not have a lookupNamespaceURI method."); return nullAtom; } // Catch exceptions from calling the namespace resolver. v8::TryCatch tryCatch; tryCatch.SetVerbose(true); // Print exceptions to console. const int argc = 1; v8::Handle<v8::Value> argv[argc] = { v8String(m_isolate, prefix) }; v8::Handle<v8::Function> function = lookupNamespaceURIFunc.IsEmpty() ? v8::Handle<v8::Function>::Cast(m_resolver) : lookupNamespaceURIFunc; v8::Handle<v8::Value> retval = ScriptController::callFunction(callingExecutionContext(m_isolate), function, m_resolver, argc, argv, m_isolate); // Eat exceptions from namespace resolver and return an empty string. This will most likely cause NamespaceError. if (tryCatch.HasCaught()) return nullAtom; V8TRYCATCH_FOR_V8STRINGRESOURCE_RETURN(V8StringResource<WithNullCheck>, returnString, retval, nullAtom); return returnString; }
AtomicString V8CustomXPathNSResolver::lookupNamespaceURI(const String& prefix) { v8::Isolate* isolate = m_scriptState->isolate(); v8::Local<v8::Function> lookupNamespaceURIFunc; v8::Local<v8::String> lookupNamespaceURIName = v8AtomicString(isolate, "lookupNamespaceURI"); // Check if the resolver has a function property named lookupNamespaceURI. v8::Local<v8::Value> lookupNamespaceURI; if (m_resolver->Get(m_scriptState->context(), lookupNamespaceURIName) .ToLocal(&lookupNamespaceURI) && lookupNamespaceURI->IsFunction()) lookupNamespaceURIFunc = v8::Local<v8::Function>::Cast(lookupNamespaceURI); if (lookupNamespaceURIFunc.IsEmpty() && !m_resolver->IsFunction()) { LocalFrame* frame = toLocalDOMWindow(toDOMWindow(m_scriptState->context()))->frame(); if (frame && frame->host()) frame->console().addMessage(ConsoleMessage::create( JSMessageSource, ErrorMessageLevel, "XPathNSResolver does not have a lookupNamespaceURI method.")); return nullAtom; } // Catch exceptions from calling the namespace resolver. v8::TryCatch tryCatch(isolate); tryCatch.SetVerbose(true); // Print exceptions to console. const int argc = 1; v8::Local<v8::Value> argv[argc] = {v8String(isolate, prefix)}; v8::Local<v8::Function> function = lookupNamespaceURIFunc.IsEmpty() ? v8::Local<v8::Function>::Cast(m_resolver) : lookupNamespaceURIFunc; v8::Local<v8::Value> retval; // Eat exceptions from namespace resolver and return an empty string. This // will most likely cause NamespaceError. if (!V8ScriptRunner::callFunction( function, toExecutionContext(m_scriptState->context()), m_resolver, argc, argv, isolate) .ToLocal(&retval)) return nullAtom; TOSTRING_DEFAULT(V8StringResource<TreatNullAsNullString>, returnString, retval, nullAtom); return returnString; }
void InspectorOverlay::rebuildOverlayPage() { FrameView* view = m_frameImpl->frameView(); LocalFrame* frame = m_frameImpl->frame(); if (!view || !frame) return; IntRect visibleRectInDocument = view->getScrollableArea()->visibleContentRect(); IntSize viewportSize = frame->host()->visualViewport().size(); overlayMainFrame()->view()->resize(viewportSize); overlayPage()->frameHost().visualViewport().setSize(viewportSize); overlayMainFrame()->setPageZoomFactor(windowToViewportScale()); reset(viewportSize, visibleRectInDocument.location()); if (m_showReloadingBlanket) { evaluateInOverlay("showReloadingBlanket", ""); return; } drawNodeHighlight(); drawQuadHighlight(); drawPausedInDebuggerMessage(); drawViewSize(); }
float InspectorOverlay::windowToViewportScale() const { LocalFrame* frame = m_frameImpl->frame(); if (!frame) return 1.0f; return frame->host()->chromeClient().windowToViewportScalar(1.0f); }
void ContextMenuClientImpl::showContextMenu(const WebCore::ContextMenu* defaultMenu) { // Displaying the context menu in this function is a big hack as we don't // have context, i.e. whether this is being invoked via a script or in // response to user input (Mouse event WM_RBUTTONDOWN, // Keyboard events KeyVK_APPS, Shift+F10). Check if this is being invoked // in response to the above input events before popping up the context menu. if (!m_webView->contextMenuAllowed()) return; HitTestResult r = m_webView->page()->contextMenuController().hitTestResult(); LocalFrame* selectedFrame = r.innerNodeFrame(); WebContextMenuData data; IntPoint mousePoint = selectedFrame->view()->contentsToWindow(r.roundedPointInInnerNodeFrame()); // FIXME(bokan): crbug.com/371902 - We shouldn't be making these scale // related coordinate transformatios in an ad hoc way. PinchViewport& pinchViewport = selectedFrame->host()->pinchViewport(); mousePoint -= flooredIntSize(pinchViewport.visibleRect().location()); mousePoint.scale(m_webView->pageScaleFactor(), m_webView->pageScaleFactor()); data.mousePosition = mousePoint; // Compute edit flags. data.editFlags = WebContextMenuData::CanDoNone; if (toLocalFrame(m_webView->focusedWebCoreFrame())->editor().canUndo()) data.editFlags |= WebContextMenuData::CanUndo; if (toLocalFrame(m_webView->focusedWebCoreFrame())->editor().canRedo()) data.editFlags |= WebContextMenuData::CanRedo; if (toLocalFrame(m_webView->focusedWebCoreFrame())->editor().canCut()) data.editFlags |= WebContextMenuData::CanCut; if (toLocalFrame(m_webView->focusedWebCoreFrame())->editor().canCopy()) data.editFlags |= WebContextMenuData::CanCopy; if (toLocalFrame(m_webView->focusedWebCoreFrame())->editor().canPaste()) data.editFlags |= WebContextMenuData::CanPaste; if (toLocalFrame(m_webView->focusedWebCoreFrame())->editor().canDelete()) data.editFlags |= WebContextMenuData::CanDelete; // We can always select all... data.editFlags |= WebContextMenuData::CanSelectAll; data.editFlags |= WebContextMenuData::CanTranslate; // Links, Images, Media tags, and Image/Media-Links take preference over // all else. data.linkURL = r.absoluteLinkURL(); if (isHTMLCanvasElement(r.innerNonSharedNode())) { data.mediaType = WebContextMenuData::MediaTypeCanvas; } else if (!r.absoluteImageURL().isEmpty()) { data.srcURL = r.absoluteImageURL(); data.mediaType = WebContextMenuData::MediaTypeImage; data.mediaFlags |= WebContextMenuData::MediaCanPrint; } else if (!r.absoluteMediaURL().isEmpty()) { data.srcURL = r.absoluteMediaURL(); // We know that if absoluteMediaURL() is not empty, then this // is a media element. HTMLMediaElement* mediaElement = toHTMLMediaElement(r.innerNonSharedNode()); if (isHTMLVideoElement(*mediaElement)) data.mediaType = WebContextMenuData::MediaTypeVideo; else if (isHTMLAudioElement(*mediaElement)) data.mediaType = WebContextMenuData::MediaTypeAudio; if (mediaElement->error()) data.mediaFlags |= WebContextMenuData::MediaInError; if (mediaElement->paused()) data.mediaFlags |= WebContextMenuData::MediaPaused; if (mediaElement->muted()) data.mediaFlags |= WebContextMenuData::MediaMuted; if (mediaElement->loop()) data.mediaFlags |= WebContextMenuData::MediaLoop; if (mediaElement->supportsSave()) data.mediaFlags |= WebContextMenuData::MediaCanSave; if (mediaElement->hasAudio()) data.mediaFlags |= WebContextMenuData::MediaHasAudio; // Media controls can be toggled only for video player. If we toggle // controls for audio then the player disappears, and there is no way to // return it back. Don't set this bit for fullscreen video, since // toggling is ignored in that case. if (mediaElement->hasVideo() && !mediaElement->isFullscreen()) data.mediaFlags |= WebContextMenuData::MediaCanToggleControls; if (mediaElement->controls()) data.mediaFlags |= WebContextMenuData::MediaControls; } else if (isHTMLObjectElement(*r.innerNonSharedNode()) || isHTMLEmbedElement(*r.innerNonSharedNode())) { RenderObject* object = r.innerNonSharedNode()->renderer(); if (object && object->isWidget()) { Widget* widget = toRenderWidget(object)->widget(); if (widget && widget->isPluginContainer()) { data.mediaType = WebContextMenuData::MediaTypePlugin; WebPluginContainerImpl* plugin = toWebPluginContainerImpl(widget); WebString text = plugin->plugin()->selectionAsText(); if (!text.isEmpty()) { data.selectedText = text; data.editFlags |= WebContextMenuData::CanCopy; } data.editFlags &= ~WebContextMenuData::CanTranslate; data.linkURL = plugin->plugin()->linkAtPosition(data.mousePosition); if (plugin->plugin()->supportsPaginatedPrint()) data.mediaFlags |= WebContextMenuData::MediaCanPrint; HTMLPlugInElement* pluginElement = toHTMLPlugInElement(r.innerNonSharedNode()); data.srcURL = pluginElement->document().completeURL(pluginElement->url()); data.mediaFlags |= WebContextMenuData::MediaCanSave; // Add context menu commands that are supported by the plugin. if (plugin->plugin()->canRotateView()) data.mediaFlags |= WebContextMenuData::MediaCanRotate; } } } // An image can to be null for many reasons, like being blocked, no image // data received from server yet. data.hasImageContents = (data.mediaType == WebContextMenuData::MediaTypeImage) && r.image() && !(r.image()->isNull()); // If it's not a link, an image, a media element, or an image/media link, // show a selection menu or a more generic page menu. if (selectedFrame->document()->loader()) data.frameEncoding = selectedFrame->document()->encodingName(); // Send the frame and page URLs in any case. data.pageURL = urlFromFrame(m_webView->mainFrameImpl()->frame()); if (selectedFrame != m_webView->mainFrameImpl()->frame()) { data.frameURL = urlFromFrame(selectedFrame); RefPtr<HistoryItem> historyItem = selectedFrame->loader().currentItem(); if (historyItem) data.frameHistoryItem = WebHistoryItem(historyItem); } if (r.isSelected()) { if (!isHTMLInputElement(*r.innerNonSharedNode()) || !toHTMLInputElement(r.innerNonSharedNode())->isPasswordField()) data.selectedText = selectedFrame->selectedText().stripWhiteSpace(); } if (r.isContentEditable()) { data.isEditable = true; // When Chrome enables asynchronous spellchecking, its spellchecker adds spelling markers to misspelled // words and attaches suggestions to these markers in the background. Therefore, when a user right-clicks // a mouse on a word, Chrome just needs to find a spelling marker on the word instead of spellchecking it. if (selectedFrame->settings() && selectedFrame->settings()->asynchronousSpellCheckingEnabled()) { DocumentMarker marker; data.misspelledWord = selectMisspellingAsync(selectedFrame, marker); data.misspellingHash = marker.hash(); if (marker.description().length()) { Vector<String> suggestions; marker.description().split('\n', suggestions); data.dictionarySuggestions = suggestions; } else if (m_webView->spellCheckClient()) { int misspelledOffset, misspelledLength; m_webView->spellCheckClient()->spellCheck(data.misspelledWord, misspelledOffset, misspelledLength, &data.dictionarySuggestions); } } else { data.isSpellCheckingEnabled = toLocalFrame(m_webView->focusedWebCoreFrame())->spellChecker().isContinuousSpellCheckingEnabled(); // Spellchecking might be enabled for the field, but could be disabled on the node. if (toLocalFrame(m_webView->focusedWebCoreFrame())->spellChecker().isSpellCheckingEnabledInFocusedNode()) { data.misspelledWord = selectMisspelledWord(selectedFrame); if (m_webView->spellCheckClient()) { int misspelledOffset, misspelledLength; m_webView->spellCheckClient()->spellCheck( data.misspelledWord, misspelledOffset, misspelledLength, &data.dictionarySuggestions); if (!misspelledLength) data.misspelledWord.reset(); } } } HTMLFormElement* form = selectedFrame->selection().currentForm(); if (form && isHTMLInputElement(*r.innerNonSharedNode())) { HTMLInputElement& selectedElement = toHTMLInputElement(*r.innerNonSharedNode()); WebSearchableFormData ws = WebSearchableFormData(WebFormElement(form), WebInputElement(&selectedElement)); if (ws.url().isValid()) data.keywordURL = ws.url(); } } if (selectedFrame->editor().selectionHasStyle(CSSPropertyDirection, "ltr") != FalseTriState) data.writingDirectionLeftToRight |= WebContextMenuData::CheckableMenuItemChecked; if (selectedFrame->editor().selectionHasStyle(CSSPropertyDirection, "rtl") != FalseTriState) data.writingDirectionRightToLeft |= WebContextMenuData::CheckableMenuItemChecked; // Now retrieve the security info. DocumentLoader* dl = selectedFrame->loader().documentLoader(); WebDataSource* ds = WebDataSourceImpl::fromDocumentLoader(dl); if (ds) data.securityInfo = ds->response().securityInfo(); data.referrerPolicy = static_cast<WebReferrerPolicy>(selectedFrame->document()->referrerPolicy()); // Filter out custom menu elements and add them into the data. populateCustomMenuItems(defaultMenu, &data); // Extract suggested filename for saving file. if (isHTMLAnchorElement(r.URLElement())) { HTMLAnchorElement* anchor = toHTMLAnchorElement(r.URLElement()); data.suggestedFilename = anchor->fastGetAttribute(HTMLNames::downloadAttr); } data.node = r.innerNonSharedNode(); WebLocalFrameImpl* selectedWebFrame = WebLocalFrameImpl::fromFrame(selectedFrame); if (selectedWebFrame->client()) selectedWebFrame->client()->showContextMenu(data); }