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