1 // Copyright (c) 2012 The Chromium Embedded Framework Authors.
2 // Portions copyright (c) 2011 The Chromium Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5
6 #include "libcef/renderer/browser_impl.h"
7
8 #include <string>
9 #include <vector>
10
11 #include "libcef/common/app_manager.h"
12 #include "libcef/common/cef_messages.h"
13 #include "libcef/renderer/blink_glue.h"
14 #include "libcef/renderer/browser_manager.h"
15 #include "libcef/renderer/render_frame_util.h"
16 #include "libcef/renderer/thread_util.h"
17
18 #include "base/strings/string_util.h"
19 #include "base/strings/utf_string_conversions.h"
20 #include "content/public/renderer/document_state.h"
21 #include "content/public/renderer/render_frame.h"
22 #include "content/public/renderer/render_view.h"
23 #include "content/renderer/navigation_state.h"
24 #include "third_party/blink/public/platform/web_string.h"
25 #include "third_party/blink/public/platform/web_url_error.h"
26 #include "third_party/blink/public/platform/web_url_response.h"
27 #include "third_party/blink/public/web/web_document.h"
28 #include "third_party/blink/public/web/web_frame.h"
29 #include "third_party/blink/public/web/web_frame_content_dumper.h"
30 #include "third_party/blink/public/web/web_local_frame.h"
31 #include "third_party/blink/public/web/web_security_policy.h"
32 #include "third_party/blink/public/web/web_view.h"
33
34 // CefBrowserImpl static methods.
35 // -----------------------------------------------------------------------------
36
37 // static
GetBrowserForView(content::RenderView * view)38 CefRefPtr<CefBrowserImpl> CefBrowserImpl::GetBrowserForView(
39 content::RenderView* view) {
40 return CefBrowserManager::Get()->GetBrowserForView(view);
41 }
42
43 // static
GetBrowserForMainFrame(blink::WebFrame * frame)44 CefRefPtr<CefBrowserImpl> CefBrowserImpl::GetBrowserForMainFrame(
45 blink::WebFrame* frame) {
46 return CefBrowserManager::Get()->GetBrowserForMainFrame(frame);
47 }
48
49 // CefBrowser methods.
50 // -----------------------------------------------------------------------------
51
GetHost()52 CefRefPtr<CefBrowserHost> CefBrowserImpl::GetHost() {
53 NOTREACHED() << "GetHost cannot be called from the render process";
54 return nullptr;
55 }
56
CanGoBack()57 bool CefBrowserImpl::CanGoBack() {
58 CEF_REQUIRE_RT_RETURN(false);
59
60 return blink_glue::CanGoBack(GetWebView());
61 }
62
GoBack()63 void CefBrowserImpl::GoBack() {
64 CEF_REQUIRE_RT_RETURN_VOID();
65
66 blink_glue::GoBack(GetWebView());
67 }
68
CanGoForward()69 bool CefBrowserImpl::CanGoForward() {
70 CEF_REQUIRE_RT_RETURN(false);
71
72 return blink_glue::CanGoForward(GetWebView());
73 }
74
GoForward()75 void CefBrowserImpl::GoForward() {
76 CEF_REQUIRE_RT_RETURN_VOID();
77
78 blink_glue::GoForward(GetWebView());
79 }
80
IsLoading()81 bool CefBrowserImpl::IsLoading() {
82 CEF_REQUIRE_RT_RETURN(false);
83
84 if (GetWebView()) {
85 blink::WebFrame* main_frame = GetWebView()->MainFrame();
86 if (main_frame)
87 return main_frame->ToWebLocalFrame()->IsLoading();
88 }
89 return false;
90 }
91
Reload()92 void CefBrowserImpl::Reload() {
93 CEF_REQUIRE_RT_RETURN_VOID();
94
95 if (GetWebView()) {
96 blink::WebFrame* main_frame = GetWebView()->MainFrame();
97 if (main_frame && main_frame->IsWebLocalFrame()) {
98 main_frame->ToWebLocalFrame()->StartReload(
99 blink::WebFrameLoadType::kReload);
100 }
101 }
102 }
103
ReloadIgnoreCache()104 void CefBrowserImpl::ReloadIgnoreCache() {
105 CEF_REQUIRE_RT_RETURN_VOID();
106
107 if (GetWebView()) {
108 blink::WebFrame* main_frame = GetWebView()->MainFrame();
109 if (main_frame && main_frame->IsWebLocalFrame()) {
110 main_frame->ToWebLocalFrame()->StartReload(
111 blink::WebFrameLoadType::kReloadBypassingCache);
112 }
113 }
114 }
115
StopLoad()116 void CefBrowserImpl::StopLoad() {
117 CEF_REQUIRE_RT_RETURN_VOID();
118
119 if (GetWebView()) {
120 blink::WebFrame* main_frame = GetWebView()->MainFrame();
121 if (main_frame && main_frame->IsWebLocalFrame()) {
122 main_frame->ToWebLocalFrame()->DeprecatedStopLoading();
123 }
124 }
125 }
126
GetIdentifier()127 int CefBrowserImpl::GetIdentifier() {
128 CEF_REQUIRE_RT_RETURN(0);
129
130 return browser_id();
131 }
132
IsSame(CefRefPtr<CefBrowser> that)133 bool CefBrowserImpl::IsSame(CefRefPtr<CefBrowser> that) {
134 CEF_REQUIRE_RT_RETURN(false);
135
136 CefBrowserImpl* impl = static_cast<CefBrowserImpl*>(that.get());
137 return (impl == this);
138 }
139
IsPopup()140 bool CefBrowserImpl::IsPopup() {
141 CEF_REQUIRE_RT_RETURN(false);
142
143 return is_popup();
144 }
145
HasDocument()146 bool CefBrowserImpl::HasDocument() {
147 CEF_REQUIRE_RT_RETURN(false);
148
149 if (GetWebView()) {
150 blink::WebFrame* main_frame = GetWebView()->MainFrame();
151 if (main_frame && main_frame->IsWebLocalFrame()) {
152 return !main_frame->ToWebLocalFrame()->GetDocument().IsNull();
153 }
154 }
155 return false;
156 }
157
GetMainFrame()158 CefRefPtr<CefFrame> CefBrowserImpl::GetMainFrame() {
159 CEF_REQUIRE_RT_RETURN(nullptr);
160
161 if (GetWebView()) {
162 blink::WebFrame* main_frame = GetWebView()->MainFrame();
163 if (main_frame && main_frame->IsWebLocalFrame()) {
164 return GetWebFrameImpl(main_frame->ToWebLocalFrame()).get();
165 }
166 }
167 return nullptr;
168 }
169
GetFocusedFrame()170 CefRefPtr<CefFrame> CefBrowserImpl::GetFocusedFrame() {
171 CEF_REQUIRE_RT_RETURN(nullptr);
172
173 if (GetWebView() && GetWebView()->FocusedFrame()) {
174 return GetWebFrameImpl(GetWebView()->FocusedFrame()).get();
175 }
176 return nullptr;
177 }
178
GetFrame(int64 identifier)179 CefRefPtr<CefFrame> CefBrowserImpl::GetFrame(int64 identifier) {
180 CEF_REQUIRE_RT_RETURN(nullptr);
181
182 return GetWebFrameImpl(identifier).get();
183 }
184
GetFrame(const CefString & name)185 CefRefPtr<CefFrame> CefBrowserImpl::GetFrame(const CefString& name) {
186 CEF_REQUIRE_RT_RETURN(nullptr);
187
188 blink::WebView* web_view = GetWebView();
189 if (web_view) {
190 const blink::WebString& frame_name =
191 blink::WebString::FromUTF16(name.ToString16());
192 // Search by assigned frame name (Frame::name).
193 blink::WebFrame* frame = web_view->MainFrame();
194 if (frame && frame->IsWebLocalFrame())
195 frame = frame->ToWebLocalFrame()->FindFrameByName(frame_name);
196 if (!frame) {
197 // Search by unique frame name (Frame::uniqueName).
198 const std::string& searchname = name;
199 for (blink::WebFrame* cur_frame = web_view->MainFrame(); cur_frame;
200 cur_frame = cur_frame->TraverseNext()) {
201 if (cur_frame->IsWebLocalFrame() &&
202 render_frame_util::GetName(cur_frame->ToWebLocalFrame()) ==
203 searchname) {
204 frame = cur_frame;
205 break;
206 }
207 }
208 }
209 if (frame && frame->IsWebLocalFrame())
210 return GetWebFrameImpl(frame->ToWebLocalFrame()).get();
211 }
212
213 return nullptr;
214 }
215
GetFrameCount()216 size_t CefBrowserImpl::GetFrameCount() {
217 CEF_REQUIRE_RT_RETURN(0);
218
219 int count = 0;
220
221 if (GetWebView()) {
222 for (blink::WebFrame* frame = GetWebView()->MainFrame(); frame;
223 frame = frame->TraverseNext()) {
224 count++;
225 }
226 }
227
228 return count;
229 }
230
GetFrameIdentifiers(std::vector<int64> & identifiers)231 void CefBrowserImpl::GetFrameIdentifiers(std::vector<int64>& identifiers) {
232 CEF_REQUIRE_RT_RETURN_VOID();
233
234 if (identifiers.size() > 0)
235 identifiers.clear();
236
237 if (GetWebView()) {
238 for (blink::WebFrame* frame = GetWebView()->MainFrame(); frame;
239 frame = frame->TraverseNext()) {
240 if (frame->IsWebLocalFrame())
241 identifiers.push_back(
242 render_frame_util::GetIdentifier(frame->ToWebLocalFrame()));
243 }
244 }
245 }
246
GetFrameNames(std::vector<CefString> & names)247 void CefBrowserImpl::GetFrameNames(std::vector<CefString>& names) {
248 CEF_REQUIRE_RT_RETURN_VOID();
249
250 if (names.size() > 0)
251 names.clear();
252
253 if (GetWebView()) {
254 for (blink::WebFrame* frame = GetWebView()->MainFrame(); frame;
255 frame = frame->TraverseNext()) {
256 if (frame->IsWebLocalFrame())
257 names.push_back(render_frame_util::GetName(frame->ToWebLocalFrame()));
258 }
259 }
260 }
261
262 // CefBrowserImpl public methods.
263 // -----------------------------------------------------------------------------
264
CefBrowserImpl(content::RenderView * render_view,int browser_id,bool is_popup,bool is_windowless)265 CefBrowserImpl::CefBrowserImpl(content::RenderView* render_view,
266 int browser_id,
267 bool is_popup,
268 bool is_windowless)
269 : blink::WebViewObserver(render_view->GetWebView()),
270 browser_id_(browser_id),
271 is_popup_(is_popup),
272 is_windowless_(is_windowless) {}
273
~CefBrowserImpl()274 CefBrowserImpl::~CefBrowserImpl() {}
275
GetWebFrameImpl(blink::WebLocalFrame * frame)276 CefRefPtr<CefFrameImpl> CefBrowserImpl::GetWebFrameImpl(
277 blink::WebLocalFrame* frame) {
278 DCHECK(frame);
279 int64_t frame_id = render_frame_util::GetIdentifier(frame);
280
281 // Frames are re-used between page loads. Only add the frame to the map once.
282 FrameMap::const_iterator it = frames_.find(frame_id);
283 if (it != frames_.end())
284 return it->second;
285
286 CefRefPtr<CefFrameImpl> framePtr(new CefFrameImpl(this, frame, frame_id));
287 frames_.insert(std::make_pair(frame_id, framePtr));
288
289 return framePtr;
290 }
291
GetWebFrameImpl(int64_t frame_id)292 CefRefPtr<CefFrameImpl> CefBrowserImpl::GetWebFrameImpl(int64_t frame_id) {
293 if (frame_id == blink_glue::kInvalidFrameId) {
294 if (GetWebView()) {
295 blink::WebFrame* main_frame = GetWebView()->MainFrame();
296 if (main_frame && main_frame->IsWebLocalFrame()) {
297 return GetWebFrameImpl(main_frame->ToWebLocalFrame());
298 }
299 }
300 return nullptr;
301 }
302
303 // Check if we already know about the frame.
304 FrameMap::const_iterator it = frames_.find(frame_id);
305 if (it != frames_.end())
306 return it->second;
307
308 if (GetWebView()) {
309 // Check if the frame exists but we don't know about it yet.
310 for (blink::WebFrame* frame = GetWebView()->MainFrame(); frame;
311 frame = frame->TraverseNext()) {
312 if (frame->IsWebLocalFrame() &&
313 render_frame_util::GetIdentifier(frame->ToWebLocalFrame()) ==
314 frame_id) {
315 return GetWebFrameImpl(frame->ToWebLocalFrame());
316 }
317 }
318 }
319
320 return nullptr;
321 }
322
AddFrameObject(int64_t frame_id,CefTrackNode * tracked_object)323 void CefBrowserImpl::AddFrameObject(int64_t frame_id,
324 CefTrackNode* tracked_object) {
325 CefRefPtr<CefTrackManager> manager;
326
327 if (!frame_objects_.empty()) {
328 FrameObjectMap::const_iterator it = frame_objects_.find(frame_id);
329 if (it != frame_objects_.end())
330 manager = it->second;
331 }
332
333 if (!manager.get()) {
334 manager = new CefTrackManager();
335 frame_objects_.insert(std::make_pair(frame_id, manager));
336 }
337
338 manager->Add(tracked_object);
339 }
340
341 // RenderViewObserver methods.
342 // -----------------------------------------------------------------------------
343
OnDestruct()344 void CefBrowserImpl::OnDestruct() {
345 // Notify that the browser window has been destroyed.
346 CefRefPtr<CefApp> app = CefAppManager::Get()->GetApplication();
347 if (app.get()) {
348 CefRefPtr<CefRenderProcessHandler> handler = app->GetRenderProcessHandler();
349 if (handler.get())
350 handler->OnBrowserDestroyed(this);
351 }
352
353 CefBrowserManager::Get()->OnBrowserDestroyed(this);
354 }
355
FrameDetached(int64_t frame_id)356 void CefBrowserImpl::FrameDetached(int64_t frame_id) {
357 if (!frames_.empty()) {
358 // Remove the frame from the map.
359 FrameMap::iterator it = frames_.find(frame_id);
360 if (it != frames_.end()) {
361 frames_.erase(it);
362 }
363 }
364
365 if (!frame_objects_.empty()) {
366 // Remove any tracked objects associated with the frame.
367 FrameObjectMap::iterator it = frame_objects_.find(frame_id);
368 if (it != frame_objects_.end())
369 frame_objects_.erase(it);
370 }
371 }
372
OnLoadingStateChange(bool isLoading)373 void CefBrowserImpl::OnLoadingStateChange(bool isLoading) {
374 CefRefPtr<CefApp> app = CefAppManager::Get()->GetApplication();
375 if (app.get()) {
376 CefRefPtr<CefRenderProcessHandler> handler = app->GetRenderProcessHandler();
377 if (handler.get()) {
378 CefRefPtr<CefLoadHandler> load_handler = handler->GetLoadHandler();
379 if (load_handler.get()) {
380 blink::WebView* web_view = GetWebView();
381 const bool canGoBack = blink_glue::CanGoBack(web_view);
382 const bool canGoForward = blink_glue::CanGoForward(web_view);
383
384 // Don't call OnLoadingStateChange multiple times with the same status.
385 // This can occur in cases where there are multiple highest-level
386 // LocalFrames in-process for the same browser.
387 if (last_loading_state_ &&
388 last_loading_state_->IsMatch(isLoading, canGoBack, canGoForward)) {
389 return;
390 }
391
392 load_handler->OnLoadingStateChange(this, isLoading, canGoBack,
393 canGoForward);
394 last_loading_state_.reset(
395 new LoadingState(isLoading, canGoBack, canGoForward));
396 }
397 }
398 }
399 }
400