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 defined(OS_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
DidFailProvisionalLoad()53 void CefRenderFrameObserver::DidFailProvisionalLoad() {
54 if (frame_) {
55 OnLoadError();
56 }
57 }
58
DidFinishLoad()59 void CefRenderFrameObserver::DidFinishLoad() {
60 if (frame_) {
61 frame_->OnDidFinishLoad();
62 }
63 }
64
WillDetach()65 void CefRenderFrameObserver::WillDetach() {
66 if (frame_) {
67 frame_->OnDetached();
68 frame_ = nullptr;
69 }
70 }
71
FocusedElementChanged(const blink::WebElement & element)72 void CefRenderFrameObserver::FocusedElementChanged(
73 const blink::WebElement& element) {
74 if (!frame_)
75 return;
76
77 blink::WebLocalFrame* frame = render_frame()->GetWebFrame();
78 CefRefPtr<CefBrowserImpl> browserPtr =
79 CefBrowserImpl::GetBrowserForMainFrame(frame->Top());
80 if (!browserPtr)
81 return;
82
83 CefRefPtr<CefRenderProcessHandler> handler;
84 CefRefPtr<CefApp> application = CefAppManager::Get()->GetApplication();
85 if (application)
86 handler = application->GetRenderProcessHandler();
87 if (!handler)
88 return;
89
90 CefRefPtr<CefFrameImpl> framePtr = browserPtr->GetWebFrameImpl(frame);
91
92 if (element.IsNull()) {
93 handler->OnFocusedNodeChanged(browserPtr.get(), framePtr.get(), nullptr);
94 return;
95 }
96
97 if (element.GetDocument().IsNull())
98 return;
99
100 CefRefPtr<CefDOMDocumentImpl> documentImpl =
101 new CefDOMDocumentImpl(browserPtr.get(), frame);
102 handler->OnFocusedNodeChanged(browserPtr.get(), framePtr.get(),
103 documentImpl->GetOrCreateNode(element));
104 documentImpl->Detach();
105 }
106
DraggableRegionsChanged()107 void CefRenderFrameObserver::DraggableRegionsChanged() {
108 if (frame_) {
109 frame_->OnDraggableRegionsChanged();
110 }
111 }
112
DidCreateScriptContext(v8::Handle<v8::Context> context,int world_id)113 void CefRenderFrameObserver::DidCreateScriptContext(
114 v8::Handle<v8::Context> context,
115 int world_id) {
116 if (!frame_)
117 return;
118
119 blink::WebLocalFrame* frame = render_frame()->GetWebFrame();
120 CefRefPtr<CefBrowserImpl> browserPtr =
121 CefBrowserImpl::GetBrowserForMainFrame(frame->Top());
122 if (!browserPtr)
123 return;
124
125 CefRefPtr<CefRenderProcessHandler> handler;
126 CefRefPtr<CefApp> application = CefAppManager::Get()->GetApplication();
127 if (application)
128 handler = application->GetRenderProcessHandler();
129 if (!handler)
130 return;
131
132 CefRefPtr<CefFrameImpl> framePtr = browserPtr->GetWebFrameImpl(frame);
133
134 v8::Isolate* isolate = blink::MainThreadIsolate();
135 v8::HandleScope handle_scope(isolate);
136 v8::Context::Scope scope(context);
137 v8::MicrotasksScope microtasks_scope(isolate,
138 v8::MicrotasksScope::kRunMicrotasks);
139
140 CefRefPtr<CefV8Context> contextPtr(new CefV8ContextImpl(isolate, context));
141
142 handler->OnContextCreated(browserPtr.get(), framePtr.get(), contextPtr);
143 }
144
WillReleaseScriptContext(v8::Handle<v8::Context> context,int world_id)145 void CefRenderFrameObserver::WillReleaseScriptContext(
146 v8::Handle<v8::Context> context,
147 int world_id) {
148 blink::WebLocalFrame* frame = render_frame()->GetWebFrame();
149 CefRefPtr<CefBrowserImpl> browserPtr =
150 CefBrowserImpl::GetBrowserForMainFrame(frame->Top());
151 if (browserPtr) {
152 CefRefPtr<CefApp> application = CefAppManager::Get()->GetApplication();
153 if (application) {
154 CefRefPtr<CefRenderProcessHandler> handler =
155 application->GetRenderProcessHandler();
156 if (handler) {
157 CefRefPtr<CefFrameImpl> framePtr = browserPtr->GetWebFrameImpl(frame);
158
159 v8::Isolate* isolate = blink::MainThreadIsolate();
160 v8::HandleScope handle_scope(isolate);
161
162 // The released context should not be used for script execution.
163 // Depending on how the context is released this may or may not already
164 // be set.
165 blink_glue::CefScriptForbiddenScope forbidScript;
166
167 CefRefPtr<CefV8Context> contextPtr(
168 new CefV8ContextImpl(isolate, context));
169
170 handler->OnContextReleased(browserPtr.get(), framePtr.get(),
171 contextPtr);
172 }
173 }
174 }
175
176 CefV8ReleaseContext(context);
177 }
178
OnDestruct()179 void CefRenderFrameObserver::OnDestruct() {
180 delete this;
181 }
182
OnMessageReceived(const IPC::Message & message)183 bool CefRenderFrameObserver::OnMessageReceived(const IPC::Message& message) {
184 if (frame_) {
185 return frame_->OnMessageReceived(message);
186 }
187 return false;
188 }
189
AttachFrame(CefFrameImpl * frame)190 void CefRenderFrameObserver::AttachFrame(CefFrameImpl* frame) {
191 DCHECK(frame);
192 DCHECK(!frame_);
193 frame_ = frame;
194 frame_->OnAttached();
195 }
196
OnLoadStart()197 void CefRenderFrameObserver::OnLoadStart() {
198 CefRefPtr<CefApp> app = CefAppManager::Get()->GetApplication();
199 if (app.get()) {
200 CefRefPtr<CefRenderProcessHandler> handler = app->GetRenderProcessHandler();
201 if (handler.get()) {
202 CefRefPtr<CefLoadHandler> load_handler = handler->GetLoadHandler();
203 if (load_handler.get()) {
204 blink::WebLocalFrame* frame = render_frame()->GetWebFrame();
205 CefRefPtr<CefBrowserImpl> browserPtr =
206 CefBrowserImpl::GetBrowserForMainFrame(frame->Top());
207 load_handler->OnLoadStart(browserPtr.get(), frame_, TT_EXPLICIT);
208 }
209 }
210 }
211 }
212
OnLoadError()213 void CefRenderFrameObserver::OnLoadError() {
214 CefRefPtr<CefApp> app = CefAppManager::Get()->GetApplication();
215 if (app.get()) {
216 CefRefPtr<CefRenderProcessHandler> handler = app->GetRenderProcessHandler();
217 if (handler.get()) {
218 CefRefPtr<CefLoadHandler> load_handler = handler->GetLoadHandler();
219 // Error codes were removed from DidFailProvisionalLoad() so we now always
220 // pass the same value.
221 if (load_handler.get()) {
222 const cef_errorcode_t errorCode =
223 static_cast<cef_errorcode_t>(net::ERR_ABORTED);
224 const std::string& errorText = net::ErrorToString(errorCode);
225 blink::WebLocalFrame* frame = render_frame()->GetWebFrame();
226 CefRefPtr<CefBrowserImpl> browserPtr =
227 CefBrowserImpl::GetBrowserForMainFrame(frame->Top());
228 load_handler->OnLoadError(browserPtr.get(), frame_, errorCode,
229 errorText, frame_->GetURL());
230 }
231 }
232 }
233 }
234
235 // Enable deprecation warnings on Windows. See http://crbug.com/585142.
236 #if defined(OS_WIN)
237 #if defined(__clang__)
238 #pragma GCC diagnostic pop
239 #else
240 #pragma warning(pop)
241 #endif
242 #endif
243