// Copyright 2014 The Chromium Embedded Framework Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be found // in the LICENSE file. #include "base/compiler_specific.h" // Enable deprecation warnings on Windows. See http://crbug.com/585142. #if defined(OS_WIN) #if defined(__clang__) #pragma GCC diagnostic push #pragma GCC diagnostic error "-Wdeprecated-declarations" #else #pragma warning(push) #pragma warning(default : 4996) #endif #endif #include "libcef/renderer/render_frame_observer.h" #include "libcef/common/content_client.h" #include "libcef/renderer/blink_glue.h" #include "libcef/renderer/browser_impl.h" #include "libcef/renderer/dom_document_impl.h" #include "libcef/renderer/v8_impl.h" #include "content/public/renderer/render_frame.h" #include "content/public/renderer/render_view.h" #include "third_party/blink/public/web/blink.h" #include "third_party/blink/public/web/web_document.h" #include "third_party/blink/public/web/web_local_frame.h" #include "third_party/blink/public/web/web_node.h" CefRenderFrameObserver::CefRenderFrameObserver( content::RenderFrame* render_frame) : content::RenderFrameObserver(render_frame) {} CefRenderFrameObserver::~CefRenderFrameObserver() {} void CefRenderFrameObserver::OnInterfaceRequestForFrame( const std::string& interface_name, mojo::ScopedMessagePipeHandle* interface_pipe) { registry_.TryBindInterface(interface_name, interface_pipe); } void CefRenderFrameObserver::DidCommitProvisionalLoad( bool is_same_document_navigation, ui::PageTransition transition) { if (!frame_) return; if (frame_->GetParent() == nullptr) { blink::WebLocalFrame* frame = render_frame()->GetWebFrame(); CefRefPtr browserPtr = CefBrowserImpl::GetBrowserForMainFrame(frame->Top()); browserPtr->OnLoadingStateChange(true); } OnLoadStart(); } void CefRenderFrameObserver::DidFailProvisionalLoad( const blink::WebURLError& error) { if (frame_) { OnLoadError(error); } } void CefRenderFrameObserver::DidFinishLoad() { if (frame_) { frame_->OnDidFinishLoad(); } } void CefRenderFrameObserver::FrameDetached() { if (frame_) { frame_->OnDetached(); frame_ = nullptr; } } void CefRenderFrameObserver::FrameFocused() { if (frame_) { frame_->OnFocused(); } } void CefRenderFrameObserver::FocusedElementChanged( const blink::WebElement& element) { if (!frame_) return; blink::WebLocalFrame* frame = render_frame()->GetWebFrame(); CefRefPtr browserPtr = CefBrowserImpl::GetBrowserForMainFrame(frame->Top()); if (!browserPtr) return; CefRefPtr handler; CefRefPtr application = CefContentClient::Get()->application(); if (application) handler = application->GetRenderProcessHandler(); if (!handler) return; CefRefPtr framePtr = browserPtr->GetWebFrameImpl(frame); if (element.IsNull()) { handler->OnFocusedNodeChanged(browserPtr.get(), framePtr.get(), nullptr); return; } if (element.GetDocument().IsNull()) return; CefRefPtr documentImpl = new CefDOMDocumentImpl(browserPtr.get(), frame); handler->OnFocusedNodeChanged(browserPtr.get(), framePtr.get(), documentImpl->GetOrCreateNode(element)); documentImpl->Detach(); } void CefRenderFrameObserver::DraggableRegionsChanged() { if (frame_) { frame_->OnDraggableRegionsChanged(); } } void CefRenderFrameObserver::DidCreateScriptContext( v8::Handle context, int world_id) { if (!frame_) return; blink::WebLocalFrame* frame = render_frame()->GetWebFrame(); CefRefPtr browserPtr = CefBrowserImpl::GetBrowserForMainFrame(frame->Top()); if (!browserPtr) return; CefRefPtr handler; CefRefPtr application = CefContentClient::Get()->application(); if (application) handler = application->GetRenderProcessHandler(); if (!handler) return; CefRefPtr framePtr = browserPtr->GetWebFrameImpl(frame); v8::Isolate* isolate = blink::MainThreadIsolate(); v8::HandleScope handle_scope(isolate); v8::Context::Scope scope(context); v8::MicrotasksScope microtasks_scope(isolate, v8::MicrotasksScope::kRunMicrotasks); CefRefPtr contextPtr(new CefV8ContextImpl(isolate, context)); handler->OnContextCreated(browserPtr.get(), framePtr.get(), contextPtr); } void CefRenderFrameObserver::WillReleaseScriptContext( v8::Handle context, int world_id) { blink::WebLocalFrame* frame = render_frame()->GetWebFrame(); CefRefPtr browserPtr = CefBrowserImpl::GetBrowserForMainFrame(frame->Top()); if (browserPtr) { CefRefPtr application = CefContentClient::Get()->application(); if (application) { CefRefPtr handler = application->GetRenderProcessHandler(); if (handler) { CefRefPtr framePtr = browserPtr->GetWebFrameImpl(frame); v8::Isolate* isolate = blink::MainThreadIsolate(); v8::HandleScope handle_scope(isolate); // The released context should not be used for script execution. // Depending on how the context is released this may or may not already // be set. blink_glue::CefScriptForbiddenScope forbidScript; CefRefPtr contextPtr( new CefV8ContextImpl(isolate, context)); handler->OnContextReleased(browserPtr.get(), framePtr.get(), contextPtr); } } } CefV8ReleaseContext(context); } void CefRenderFrameObserver::OnDestruct() { delete this; } bool CefRenderFrameObserver::OnMessageReceived(const IPC::Message& message) { if (frame_) { return frame_->OnMessageReceived(message); } return false; } void CefRenderFrameObserver::AttachFrame(CefFrameImpl* frame) { DCHECK(frame); DCHECK(!frame_); frame_ = frame; frame_->OnAttached(); } void CefRenderFrameObserver::OnLoadStart() { CefRefPtr app = CefContentClient::Get()->application(); if (app.get()) { CefRefPtr handler = app->GetRenderProcessHandler(); if (handler.get()) { CefRefPtr load_handler = handler->GetLoadHandler(); if (load_handler.get()) { blink::WebLocalFrame* frame = render_frame()->GetWebFrame(); CefRefPtr browserPtr = CefBrowserImpl::GetBrowserForMainFrame(frame->Top()); load_handler->OnLoadStart(browserPtr.get(), frame_, TT_EXPLICIT); } } } } void CefRenderFrameObserver::OnLoadError(const blink::WebURLError& error) { CefRefPtr app = CefContentClient::Get()->application(); if (app.get()) { CefRefPtr handler = app->GetRenderProcessHandler(); if (handler.get()) { CefRefPtr load_handler = handler->GetLoadHandler(); if (load_handler.get()) { const cef_errorcode_t errorCode = static_cast(error.reason()); const std::string& errorText = net::ErrorToString(error.reason()); const GURL& failedUrl = error.url(); blink::WebLocalFrame* frame = render_frame()->GetWebFrame(); CefRefPtr browserPtr = CefBrowserImpl::GetBrowserForMainFrame(frame->Top()); load_handler->OnLoadError(browserPtr.get(), frame_, errorCode, errorText, failedUrl.spec()); } } } } // Enable deprecation warnings on Windows. See http://crbug.com/585142. #if defined(OS_WIN) #if defined(__clang__) #pragma GCC diagnostic pop #else #pragma warning(pop) #endif #endif