• 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/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