• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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