1 // Copyright 2014 The Chromium Embedded Framework Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be found
3 // in the LICENSE file.
4
5 #include "base/compiler_specific.h"
6
7 // Enable deprecation warnings on Windows. See http://crbug.com/585142.
8 #if BUILDFLAG(IS_WIN)
9 #if defined(__clang__)
10 #pragma GCC diagnostic push
11 #pragma GCC diagnostic error "-Wdeprecated-declarations"
12 #else
13 #pragma warning(push)
14 #pragma warning(default : 4996)
15 #endif
16 #endif
17
18 #include "libcef/renderer/render_frame_observer.h"
19
20 #include "libcef/common/app_manager.h"
21 #include "libcef/renderer/blink_glue.h"
22 #include "libcef/renderer/browser_impl.h"
23 #include "libcef/renderer/dom_document_impl.h"
24 #include "libcef/renderer/v8_impl.h"
25
26 #include "content/public/renderer/render_frame.h"
27 #include "content/public/renderer/render_view.h"
28 #include "third_party/blink/public/web/blink.h"
29 #include "third_party/blink/public/web/web_document.h"
30 #include "third_party/blink/public/web/web_local_frame.h"
31 #include "third_party/blink/public/web/web_node.h"
32
CefRenderFrameObserver(content::RenderFrame * render_frame)33 CefRenderFrameObserver::CefRenderFrameObserver(
34 content::RenderFrame* render_frame)
35 : content::RenderFrameObserver(render_frame) {}
36
37 CefRenderFrameObserver::~CefRenderFrameObserver() = default;
38
DidCommitProvisionalLoad(ui::PageTransition transition)39 void CefRenderFrameObserver::DidCommitProvisionalLoad(
40 ui::PageTransition transition) {
41 if (!frame_)
42 return;
43
44 if (frame_->GetParent() == nullptr) {
45 blink::WebLocalFrame* frame = render_frame()->GetWebFrame();
46 CefRefPtr<CefBrowserImpl> browserPtr =
47 CefBrowserImpl::GetBrowserForMainFrame(frame->Top());
48 browserPtr->OnLoadingStateChange(true);
49 }
50 OnLoadStart();
51 }
52
WasShown()53 void CefRenderFrameObserver::WasShown() {
54 if (frame_) {
55 frame_->OnWasShown();
56 }
57 }
58
DidFailProvisionalLoad()59 void CefRenderFrameObserver::DidFailProvisionalLoad() {
60 if (frame_) {
61 OnLoadError();
62 }
63 }
64
DidFinishLoad()65 void CefRenderFrameObserver::DidFinishLoad() {
66 if (frame_) {
67 frame_->OnDidFinishLoad();
68 }
69 }
70
WillDetach()71 void CefRenderFrameObserver::WillDetach() {
72 if (frame_) {
73 frame_->OnDetached();
74 frame_ = nullptr;
75 }
76 }
77
FocusedElementChanged(const blink::WebElement & element)78 void CefRenderFrameObserver::FocusedElementChanged(
79 const blink::WebElement& element) {
80 if (!frame_)
81 return;
82
83 blink::WebLocalFrame* frame = render_frame()->GetWebFrame();
84 CefRefPtr<CefBrowserImpl> browserPtr =
85 CefBrowserImpl::GetBrowserForMainFrame(frame->Top());
86 if (!browserPtr)
87 return;
88
89 CefRefPtr<CefRenderProcessHandler> handler;
90 CefRefPtr<CefApp> application = CefAppManager::Get()->GetApplication();
91 if (application)
92 handler = application->GetRenderProcessHandler();
93 if (!handler)
94 return;
95
96 CefRefPtr<CefFrameImpl> framePtr = browserPtr->GetWebFrameImpl(frame);
97
98 if (element.IsNull()) {
99 handler->OnFocusedNodeChanged(browserPtr.get(), framePtr.get(), nullptr);
100 return;
101 }
102
103 if (element.GetDocument().IsNull())
104 return;
105
106 CefRefPtr<CefDOMDocumentImpl> documentImpl =
107 new CefDOMDocumentImpl(browserPtr.get(), frame);
108 handler->OnFocusedNodeChanged(browserPtr.get(), framePtr.get(),
109 documentImpl->GetOrCreateNode(element));
110 documentImpl->Detach();
111 }
112
DraggableRegionsChanged()113 void CefRenderFrameObserver::DraggableRegionsChanged() {
114 if (frame_) {
115 frame_->OnDraggableRegionsChanged();
116 }
117 }
118
DidCreateScriptContext(v8::Handle<v8::Context> context,int world_id)119 void CefRenderFrameObserver::DidCreateScriptContext(
120 v8::Handle<v8::Context> context,
121 int world_id) {
122 if (!frame_)
123 return;
124
125 blink::WebLocalFrame* frame = render_frame()->GetWebFrame();
126 CefRefPtr<CefBrowserImpl> browserPtr =
127 CefBrowserImpl::GetBrowserForMainFrame(frame->Top());
128 if (!browserPtr)
129 return;
130
131 CefRefPtr<CefRenderProcessHandler> handler;
132 CefRefPtr<CefApp> application = CefAppManager::Get()->GetApplication();
133 if (application)
134 handler = application->GetRenderProcessHandler();
135
136 CefRefPtr<CefFrameImpl> framePtr = browserPtr->GetWebFrameImpl(frame);
137
138 if (handler) {
139 v8::Isolate* isolate = blink::MainThreadIsolate();
140 v8::HandleScope handle_scope(isolate);
141 v8::Context::Scope scope(context);
142 v8::MicrotasksScope microtasks_scope(isolate,
143 v8::MicrotasksScope::kRunMicrotasks);
144
145 CefRefPtr<CefV8Context> contextPtr(new CefV8ContextImpl(isolate, context));
146
147 handler->OnContextCreated(browserPtr.get(), framePtr.get(), contextPtr);
148 }
149
150 // Do this last, in case the client callback modified the window object.
151 framePtr->OnContextCreated();
152 }
153
WillReleaseScriptContext(v8::Handle<v8::Context> context,int world_id)154 void CefRenderFrameObserver::WillReleaseScriptContext(
155 v8::Handle<v8::Context> context,
156 int world_id) {
157 blink::WebLocalFrame* frame = render_frame()->GetWebFrame();
158 CefRefPtr<CefBrowserImpl> browserPtr =
159 CefBrowserImpl::GetBrowserForMainFrame(frame->Top());
160 if (browserPtr) {
161 CefRefPtr<CefApp> application = CefAppManager::Get()->GetApplication();
162 if (application) {
163 CefRefPtr<CefRenderProcessHandler> handler =
164 application->GetRenderProcessHandler();
165 if (handler) {
166 CefRefPtr<CefFrameImpl> framePtr = browserPtr->GetWebFrameImpl(frame);
167
168 v8::Isolate* isolate = blink::MainThreadIsolate();
169 v8::HandleScope handle_scope(isolate);
170
171 // The released context should not be used for script execution.
172 // Depending on how the context is released this may or may not already
173 // be set.
174 blink_glue::CefScriptForbiddenScope forbidScript;
175
176 CefRefPtr<CefV8Context> contextPtr(
177 new CefV8ContextImpl(isolate, context));
178
179 handler->OnContextReleased(browserPtr.get(), framePtr.get(),
180 contextPtr);
181 }
182 }
183 }
184
185 CefV8ReleaseContext(context);
186 }
187
OnDestruct()188 void CefRenderFrameObserver::OnDestruct() {
189 delete this;
190 }
191
OnInterfaceRequestForFrame(const std::string & interface_name,mojo::ScopedMessagePipeHandle * interface_pipe)192 void CefRenderFrameObserver::OnInterfaceRequestForFrame(
193 const std::string& interface_name,
194 mojo::ScopedMessagePipeHandle* interface_pipe) {
195 registry_.TryBindInterface(interface_name, interface_pipe);
196 }
197
OnAssociatedInterfaceRequestForFrame(const std::string & interface_name,mojo::ScopedInterfaceEndpointHandle * handle)198 bool CefRenderFrameObserver::OnAssociatedInterfaceRequestForFrame(
199 const std::string& interface_name,
200 mojo::ScopedInterfaceEndpointHandle* handle) {
201 return associated_interfaces_.TryBindInterface(interface_name, handle);
202 }
203
AttachFrame(CefFrameImpl * frame)204 void CefRenderFrameObserver::AttachFrame(CefFrameImpl* frame) {
205 DCHECK(frame);
206 DCHECK(!frame_);
207 frame_ = frame;
208 frame_->OnAttached();
209 }
210
OnLoadStart()211 void CefRenderFrameObserver::OnLoadStart() {
212 CefRefPtr<CefApp> app = CefAppManager::Get()->GetApplication();
213 if (app.get()) {
214 CefRefPtr<CefRenderProcessHandler> handler = app->GetRenderProcessHandler();
215 if (handler.get()) {
216 CefRefPtr<CefLoadHandler> load_handler = handler->GetLoadHandler();
217 if (load_handler.get()) {
218 blink::WebLocalFrame* frame = render_frame()->GetWebFrame();
219 CefRefPtr<CefBrowserImpl> browserPtr =
220 CefBrowserImpl::GetBrowserForMainFrame(frame->Top());
221 load_handler->OnLoadStart(browserPtr.get(), frame_, TT_EXPLICIT);
222 }
223 }
224 }
225 }
226
OnLoadError()227 void CefRenderFrameObserver::OnLoadError() {
228 CefRefPtr<CefApp> app = CefAppManager::Get()->GetApplication();
229 if (app.get()) {
230 CefRefPtr<CefRenderProcessHandler> handler = app->GetRenderProcessHandler();
231 if (handler.get()) {
232 CefRefPtr<CefLoadHandler> load_handler = handler->GetLoadHandler();
233 // Error codes were removed from DidFailProvisionalLoad() so we now always
234 // pass the same value.
235 if (load_handler.get()) {
236 const cef_errorcode_t errorCode =
237 static_cast<cef_errorcode_t>(net::ERR_ABORTED);
238 const std::string& errorText = net::ErrorToString(errorCode);
239 blink::WebLocalFrame* frame = render_frame()->GetWebFrame();
240 CefRefPtr<CefBrowserImpl> browserPtr =
241 CefBrowserImpl::GetBrowserForMainFrame(frame->Top());
242 load_handler->OnLoadError(browserPtr.get(), frame_, errorCode,
243 errorText, frame_->GetURL());
244 }
245 }
246 }
247 }
248
249 // Enable deprecation warnings on Windows. See http://crbug.com/585142.
250 #if BUILDFLAG(IS_WIN)
251 #if defined(__clang__)
252 #pragma GCC diagnostic pop
253 #else
254 #pragma warning(pop)
255 #endif
256 #endif
257