• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2020 The Chromium Embedded Framework Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "libcef/browser/browser_host_base.h"
6 
7 #include "libcef/browser/browser_info_manager.h"
8 #include "libcef/browser/browser_platform_delegate.h"
9 #include "libcef/browser/context.h"
10 #include "libcef/browser/image_impl.h"
11 #include "libcef/browser/navigation_entry_impl.h"
12 #include "libcef/browser/thread_util.h"
13 #include "libcef/common/net/url_util.h"
14 
15 #include "base/logging.h"
16 #include "chrome/browser/spellchecker/spellcheck_factory.h"
17 #include "chrome/browser/spellchecker/spellcheck_service.h"
18 #include "components/favicon/core/favicon_url.h"
19 #include "components/spellcheck/common/spellcheck_features.h"
20 #include "content/public/browser/browser_context.h"
21 #include "content/public/browser/download_manager.h"
22 #include "content/public/browser/download_request_utils.h"
23 #include "content/public/browser/navigation_entry.h"
24 #include "ui/gfx/image/image_skia.h"
25 
26 #if defined(OS_MAC)
27 #include "components/spellcheck/browser/spellcheck_platform.h"
28 #endif
29 
30 namespace {
31 
32 // Associates a CefBrowserHostBase instance with a WebContents. This object will
33 // be deleted automatically when the WebContents is destroyed.
34 class WebContentsUserDataAdapter : public base::SupportsUserData::Data {
35  public:
Register(CefRefPtr<CefBrowserHostBase> browser)36   static void Register(CefRefPtr<CefBrowserHostBase> browser) {
37     new WebContentsUserDataAdapter(browser);
38   }
39 
Get(const content::WebContents * web_contents)40   static CefRefPtr<CefBrowserHostBase> Get(
41       const content::WebContents* web_contents) {
42     WebContentsUserDataAdapter* adapter =
43         static_cast<WebContentsUserDataAdapter*>(
44             web_contents->GetUserData(UserDataKey()));
45     if (adapter)
46       return adapter->browser_;
47     return nullptr;
48   }
49 
50  private:
WebContentsUserDataAdapter(CefRefPtr<CefBrowserHostBase> browser)51   WebContentsUserDataAdapter(CefRefPtr<CefBrowserHostBase> browser)
52       : browser_(browser) {
53     auto web_contents = browser->GetWebContents();
54     DCHECK(web_contents);
55     web_contents->SetUserData(UserDataKey(), base::WrapUnique(this));
56   }
57 
UserDataKey()58   static void* UserDataKey() {
59     // We just need a unique constant. Use the address of a static that
60     // COMDAT folding won't touch in an optimizing linker.
61     static int data_key = 0;
62     return reinterpret_cast<void*>(&data_key);
63   }
64 
65   CefRefPtr<CefBrowserHostBase> browser_;
66 };
67 
68 }  // namespace
69 
70 // static
GetBrowserForHost(const content::RenderViewHost * host)71 CefRefPtr<CefBrowserHostBase> CefBrowserHostBase::GetBrowserForHost(
72     const content::RenderViewHost* host) {
73   DCHECK(host);
74   CEF_REQUIRE_UIT();
75   content::WebContents* web_contents = content::WebContents::FromRenderViewHost(
76       const_cast<content::RenderViewHost*>(host));
77   if (web_contents)
78     return GetBrowserForContents(web_contents);
79   return nullptr;
80 }
81 
82 // static
GetBrowserForHost(const content::RenderFrameHost * host)83 CefRefPtr<CefBrowserHostBase> CefBrowserHostBase::GetBrowserForHost(
84     const content::RenderFrameHost* host) {
85   DCHECK(host);
86   CEF_REQUIRE_UIT();
87   content::WebContents* web_contents =
88       content::WebContents::FromRenderFrameHost(
89           const_cast<content::RenderFrameHost*>(host));
90   if (web_contents)
91     return GetBrowserForContents(web_contents);
92   return nullptr;
93 }
94 
95 // static
GetBrowserForContents(const content::WebContents * contents)96 CefRefPtr<CefBrowserHostBase> CefBrowserHostBase::GetBrowserForContents(
97     const content::WebContents* contents) {
98   DCHECK(contents);
99   CEF_REQUIRE_UIT();
100   return WebContentsUserDataAdapter::Get(contents);
101 }
102 
103 // static
GetBrowserForFrameTreeNode(int frame_tree_node_id)104 CefRefPtr<CefBrowserHostBase> CefBrowserHostBase::GetBrowserForFrameTreeNode(
105     int frame_tree_node_id) {
106   // Use the thread-safe approach.
107   auto info =
108       CefBrowserInfoManager::GetInstance()->GetBrowserInfoForFrameTreeNode(
109           frame_tree_node_id);
110   if (info) {
111     auto browser = info->browser();
112     if (!browser) {
113       LOG(WARNING) << "Found browser id " << info->browser_id()
114                    << " but no browser object matching frame tree node id "
115                    << frame_tree_node_id;
116     }
117     return browser;
118   }
119 
120   return nullptr;
121 }
122 
123 // static
GetBrowserForFrameRoute(int render_process_id,int render_routing_id)124 CefRefPtr<CefBrowserHostBase> CefBrowserHostBase::GetBrowserForFrameRoute(
125     int render_process_id,
126     int render_routing_id) {
127   if (render_process_id == -1 || render_routing_id == MSG_ROUTING_NONE)
128     return nullptr;
129 
130   if (CEF_CURRENTLY_ON_UIT()) {
131     // Use the non-thread-safe but potentially faster approach.
132     content::RenderFrameHost* render_frame_host =
133         content::RenderFrameHost::FromID(render_process_id, render_routing_id);
134     if (!render_frame_host)
135       return nullptr;
136     return GetBrowserForHost(render_frame_host);
137   } else {
138     // Use the thread-safe approach.
139     bool is_guest_view = false;
140     auto info =
141         CefBrowserInfoManager::GetInstance()->GetBrowserInfoForFrameRoute(
142             render_process_id, render_routing_id, &is_guest_view);
143     if (info && !is_guest_view) {
144       auto browser = info->browser();
145       if (!browser) {
146         LOG(WARNING) << "Found browser id " << info->browser_id()
147                      << " but no browser object matching frame process id "
148                      << render_process_id << " and routing id "
149                      << render_routing_id;
150       }
151       return browser;
152     }
153     return nullptr;
154   }
155 }
156 
CefBrowserHostBase(const CefBrowserSettings & settings,CefRefPtr<CefClient> client,std::unique_ptr<CefBrowserPlatformDelegate> platform_delegate,scoped_refptr<CefBrowserInfo> browser_info,CefRefPtr<CefRequestContextImpl> request_context)157 CefBrowserHostBase::CefBrowserHostBase(
158     const CefBrowserSettings& settings,
159     CefRefPtr<CefClient> client,
160     std::unique_ptr<CefBrowserPlatformDelegate> platform_delegate,
161     scoped_refptr<CefBrowserInfo> browser_info,
162     CefRefPtr<CefRequestContextImpl> request_context)
163     : settings_(settings),
164       client_(client),
165       platform_delegate_(std::move(platform_delegate)),
166       browser_info_(browser_info),
167       request_context_(request_context),
168       is_views_hosted_(platform_delegate_->IsViewsHosted()) {
169   CEF_REQUIRE_UIT();
170   DCHECK(!browser_info_->browser().get());
171   browser_info_->SetBrowser(this);
172 
173   contents_delegate_ =
174       std::make_unique<CefBrowserContentsDelegate>(browser_info_);
175   contents_delegate_->AddObserver(this);
176 }
177 
InitializeBrowser()178 void CefBrowserHostBase::InitializeBrowser() {
179   CEF_REQUIRE_UIT();
180 
181   // Associate the WebContents with this browser object.
182   DCHECK(GetWebContents());
183   WebContentsUserDataAdapter::Register(this);
184 }
185 
DestroyBrowser()186 void CefBrowserHostBase::DestroyBrowser() {
187   CEF_REQUIRE_UIT();
188 
189   devtools_manager_.reset(nullptr);
190 
191   platform_delegate_.reset(nullptr);
192 
193   contents_delegate_->RemoveObserver(this);
194   contents_delegate_->ObserveWebContents(nullptr);
195 
196   CefBrowserInfoManager::GetInstance()->RemoveBrowserInfo(browser_info_);
197   browser_info_->SetBrowser(nullptr);
198 }
199 
GetBrowser()200 CefRefPtr<CefBrowser> CefBrowserHostBase::GetBrowser() {
201   return this;
202 }
203 
GetClient()204 CefRefPtr<CefClient> CefBrowserHostBase::GetClient() {
205   return client_;
206 }
207 
GetRequestContext()208 CefRefPtr<CefRequestContext> CefBrowserHostBase::GetRequestContext() {
209   return request_context_;
210 }
211 
HasView()212 bool CefBrowserHostBase::HasView() {
213   return is_views_hosted_;
214 }
215 
StartDownload(const CefString & url)216 void CefBrowserHostBase::StartDownload(const CefString& url) {
217   if (!CEF_CURRENTLY_ON_UIT()) {
218     CEF_POST_TASK(
219         CEF_UIT, base::BindOnce(&CefBrowserHostBase::StartDownload, this, url));
220     return;
221   }
222 
223   GURL gurl = GURL(url.ToString());
224   if (gurl.is_empty() || !gurl.is_valid())
225     return;
226 
227   auto web_contents = GetWebContents();
228   if (!web_contents)
229     return;
230 
231   auto browser_context = web_contents->GetBrowserContext();
232   if (!browser_context)
233     return;
234 
235   content::DownloadManager* manager =
236       content::BrowserContext::GetDownloadManager(browser_context);
237   if (!manager)
238     return;
239 
240   std::unique_ptr<download::DownloadUrlParameters> params(
241       content::DownloadRequestUtils::CreateDownloadForWebContentsMainFrame(
242           web_contents, gurl, MISSING_TRAFFIC_ANNOTATION));
243   manager->DownloadUrl(std::move(params));
244 }
245 
DownloadImage(const CefString & image_url,bool is_favicon,uint32 max_image_size,bool bypass_cache,CefRefPtr<CefDownloadImageCallback> callback)246 void CefBrowserHostBase::DownloadImage(
247     const CefString& image_url,
248     bool is_favicon,
249     uint32 max_image_size,
250     bool bypass_cache,
251     CefRefPtr<CefDownloadImageCallback> callback) {
252   if (!CEF_CURRENTLY_ON_UIT()) {
253     CEF_POST_TASK(
254         CEF_UIT,
255         base::BindOnce(&CefBrowserHostBase::DownloadImage, this, image_url,
256                        is_favicon, max_image_size, bypass_cache, callback));
257     return;
258   }
259 
260   if (!callback)
261     return;
262 
263   GURL gurl = GURL(image_url.ToString());
264   if (gurl.is_empty() || !gurl.is_valid())
265     return;
266 
267   auto web_contents = GetWebContents();
268   if (!web_contents)
269     return;
270 
271   web_contents->DownloadImage(
272       gurl, is_favicon, max_image_size,
273       max_image_size * gfx::ImageSkia::GetMaxSupportedScale(), bypass_cache,
274       base::BindOnce(
275           [](uint32 max_image_size,
276              CefRefPtr<CefDownloadImageCallback> callback, int id,
277              int http_status_code, const GURL& image_url,
278              const std::vector<SkBitmap>& bitmaps,
279              const std::vector<gfx::Size>& sizes) {
280             CEF_REQUIRE_UIT();
281 
282             CefRefPtr<CefImageImpl> image_impl;
283 
284             if (!bitmaps.empty()) {
285               image_impl = new CefImageImpl();
286               image_impl->AddBitmaps(max_image_size, bitmaps);
287             }
288 
289             callback->OnDownloadImageFinished(
290                 image_url.spec(), http_status_code, image_impl.get());
291           },
292           max_image_size, callback));
293 }
294 
SendDevToolsMessage(const void * message,size_t message_size)295 bool CefBrowserHostBase::SendDevToolsMessage(const void* message,
296                                              size_t message_size) {
297   if (!message || message_size == 0)
298     return false;
299 
300   if (!CEF_CURRENTLY_ON_UIT()) {
301     std::string message_str(static_cast<const char*>(message), message_size);
302     CEF_POST_TASK(
303         CEF_UIT,
304         base::BindOnce(
305             [](CefRefPtr<CefBrowserHostBase> self, std::string message_str) {
306               self->SendDevToolsMessage(message_str.data(), message_str.size());
307             },
308             CefRefPtr<CefBrowserHostBase>(this), std::move(message_str)));
309     return false;
310   }
311 
312   if (!EnsureDevToolsManager())
313     return false;
314   return devtools_manager_->SendDevToolsMessage(message, message_size);
315 }
316 
ExecuteDevToolsMethod(int message_id,const CefString & method,CefRefPtr<CefDictionaryValue> params)317 int CefBrowserHostBase::ExecuteDevToolsMethod(
318     int message_id,
319     const CefString& method,
320     CefRefPtr<CefDictionaryValue> params) {
321   if (!CEF_CURRENTLY_ON_UIT()) {
322     CEF_POST_TASK(
323         CEF_UIT, base::BindOnce(base::IgnoreResult(
324                                     &CefBrowserHostBase::ExecuteDevToolsMethod),
325                                 this, message_id, method, params));
326     return 0;
327   }
328 
329   if (!EnsureDevToolsManager())
330     return 0;
331   return devtools_manager_->ExecuteDevToolsMethod(message_id, method, params);
332 }
333 
AddDevToolsMessageObserver(CefRefPtr<CefDevToolsMessageObserver> observer)334 CefRefPtr<CefRegistration> CefBrowserHostBase::AddDevToolsMessageObserver(
335     CefRefPtr<CefDevToolsMessageObserver> observer) {
336   if (!observer)
337     return nullptr;
338   auto registration = CefDevToolsManager::CreateRegistration(observer);
339   InitializeDevToolsRegistrationOnUIThread(registration);
340   return registration.get();
341 }
342 
GetNavigationEntries(CefRefPtr<CefNavigationEntryVisitor> visitor,bool current_only)343 void CefBrowserHostBase::GetNavigationEntries(
344     CefRefPtr<CefNavigationEntryVisitor> visitor,
345     bool current_only) {
346   DCHECK(visitor.get());
347   if (!visitor.get())
348     return;
349 
350   if (!CEF_CURRENTLY_ON_UIT()) {
351     CEF_POST_TASK(
352         CEF_UIT, base::BindOnce(&CefBrowserHostBase::GetNavigationEntries, this,
353                                 visitor, current_only));
354     return;
355   }
356 
357   auto web_contents = GetWebContents();
358   if (!web_contents)
359     return;
360 
361   content::NavigationController& controller = web_contents->GetController();
362   const int total = controller.GetEntryCount();
363   const int current = controller.GetCurrentEntryIndex();
364 
365   if (current_only) {
366     // Visit only the current entry.
367     CefRefPtr<CefNavigationEntryImpl> entry =
368         new CefNavigationEntryImpl(controller.GetEntryAtIndex(current));
369     visitor->Visit(entry.get(), true, current, total);
370     entry->Detach(nullptr);
371   } else {
372     // Visit all entries.
373     bool cont = true;
374     for (int i = 0; i < total && cont; ++i) {
375       CefRefPtr<CefNavigationEntryImpl> entry =
376           new CefNavigationEntryImpl(controller.GetEntryAtIndex(i));
377       cont = visitor->Visit(entry.get(), (i == current), i, total);
378       entry->Detach(nullptr);
379     }
380   }
381 }
382 
GetVisibleNavigationEntry()383 CefRefPtr<CefNavigationEntry> CefBrowserHostBase::GetVisibleNavigationEntry() {
384   if (!CEF_CURRENTLY_ON_UIT()) {
385     NOTREACHED() << "called on invalid thread";
386     return nullptr;
387   }
388 
389   content::NavigationEntry* entry = nullptr;
390   auto web_contents = GetWebContents();
391   if (web_contents)
392     entry = web_contents->GetController().GetVisibleEntry();
393 
394   if (!entry)
395     return nullptr;
396 
397   return new CefNavigationEntryImpl(entry);
398 }
399 
ReplaceMisspelling(const CefString & word)400 void CefBrowserHostBase::ReplaceMisspelling(const CefString& word) {
401   if (!CEF_CURRENTLY_ON_UIT()) {
402     CEF_POST_TASK(
403         CEF_UIT,
404         base::BindOnce(&CefBrowserHostBase::ReplaceMisspelling, this, word));
405     return;
406   }
407 
408   auto web_contents = GetWebContents();
409   if (web_contents)
410     web_contents->ReplaceMisspelling(word);
411 }
412 
AddWordToDictionary(const CefString & word)413 void CefBrowserHostBase::AddWordToDictionary(const CefString& word) {
414   if (!CEF_CURRENTLY_ON_UIT()) {
415     CEF_POST_TASK(
416         CEF_UIT,
417         base::BindOnce(&CefBrowserHostBase::AddWordToDictionary, this, word));
418     return;
419   }
420 
421   auto web_contents = GetWebContents();
422   if (!web_contents)
423     return;
424 
425   SpellcheckService* spellcheck = nullptr;
426   content::BrowserContext* browser_context = web_contents->GetBrowserContext();
427   if (browser_context) {
428     spellcheck = SpellcheckServiceFactory::GetForContext(browser_context);
429     if (spellcheck)
430       spellcheck->GetCustomDictionary()->AddWord(word);
431   }
432 #if defined(OS_MAC)
433   if (spellcheck && spellcheck::UseBrowserSpellChecker()) {
434     spellcheck_platform::AddWord(spellcheck->platform_spell_checker(), word);
435   }
436 #endif
437 }
438 
SendKeyEvent(const CefKeyEvent & event)439 void CefBrowserHostBase::SendKeyEvent(const CefKeyEvent& event) {
440   if (!CEF_CURRENTLY_ON_UIT()) {
441     CEF_POST_TASK(CEF_UIT, base::BindOnce(&CefBrowserHostBase::SendKeyEvent,
442                                           this, event));
443     return;
444   }
445 
446   if (platform_delegate_)
447     platform_delegate_->SendKeyEvent(event);
448 }
449 
SendMouseClickEvent(const CefMouseEvent & event,MouseButtonType type,bool mouseUp,int clickCount)450 void CefBrowserHostBase::SendMouseClickEvent(const CefMouseEvent& event,
451                                              MouseButtonType type,
452                                              bool mouseUp,
453                                              int clickCount) {
454   if (!CEF_CURRENTLY_ON_UIT()) {
455     CEF_POST_TASK(CEF_UIT,
456                   base::BindOnce(&CefBrowserHostBase::SendMouseClickEvent, this,
457                                  event, type, mouseUp, clickCount));
458     return;
459   }
460 
461   if (platform_delegate_) {
462     platform_delegate_->SendMouseClickEvent(event, type, mouseUp, clickCount);
463   }
464 }
465 
SendMouseMoveEvent(const CefMouseEvent & event,bool mouseLeave)466 void CefBrowserHostBase::SendMouseMoveEvent(const CefMouseEvent& event,
467                                             bool mouseLeave) {
468   if (!CEF_CURRENTLY_ON_UIT()) {
469     CEF_POST_TASK(CEF_UIT,
470                   base::BindOnce(&CefBrowserHostBase::SendMouseMoveEvent, this,
471                                  event, mouseLeave));
472     return;
473   }
474 
475   if (platform_delegate_) {
476     platform_delegate_->SendMouseMoveEvent(event, mouseLeave);
477   }
478 }
479 
SendMouseWheelEvent(const CefMouseEvent & event,int deltaX,int deltaY)480 void CefBrowserHostBase::SendMouseWheelEvent(const CefMouseEvent& event,
481                                              int deltaX,
482                                              int deltaY) {
483   if (deltaX == 0 && deltaY == 0) {
484     // Nothing to do.
485     return;
486   }
487 
488   if (!CEF_CURRENTLY_ON_UIT()) {
489     CEF_POST_TASK(CEF_UIT,
490                   base::BindOnce(&CefBrowserHostBase::SendMouseWheelEvent, this,
491                                  event, deltaX, deltaY));
492     return;
493   }
494 
495   if (platform_delegate_) {
496     platform_delegate_->SendMouseWheelEvent(event, deltaX, deltaY);
497   }
498 }
499 
GetHost()500 CefRefPtr<CefBrowserHost> CefBrowserHostBase::GetHost() {
501   return this;
502 }
503 
CanGoBack()504 bool CefBrowserHostBase::CanGoBack() {
505   base::AutoLock lock_scope(state_lock_);
506   return can_go_back_;
507 }
508 
GoBack()509 void CefBrowserHostBase::GoBack() {
510   auto callback = base::BindOnce(&CefBrowserHostBase::GoBack, this);
511   if (!CEF_CURRENTLY_ON_UIT()) {
512     CEF_POST_TASK(CEF_UIT, std::move(callback));
513     return;
514   }
515 
516   if (browser_info_->IsNavigationLocked(std::move(callback))) {
517     return;
518   }
519 
520   auto wc = GetWebContents();
521   if (wc && wc->GetController().CanGoBack()) {
522     wc->GetController().GoBack();
523   }
524 }
525 
CanGoForward()526 bool CefBrowserHostBase::CanGoForward() {
527   base::AutoLock lock_scope(state_lock_);
528   return can_go_forward_;
529 }
530 
GoForward()531 void CefBrowserHostBase::GoForward() {
532   auto callback = base::BindOnce(&CefBrowserHostBase::GoForward, this);
533   if (!CEF_CURRENTLY_ON_UIT()) {
534     CEF_POST_TASK(CEF_UIT, std::move(callback));
535     return;
536   }
537 
538   if (browser_info_->IsNavigationLocked(std::move(callback))) {
539     return;
540   }
541 
542   auto wc = GetWebContents();
543   if (wc && wc->GetController().CanGoForward()) {
544     wc->GetController().GoForward();
545   }
546 }
547 
IsLoading()548 bool CefBrowserHostBase::IsLoading() {
549   base::AutoLock lock_scope(state_lock_);
550   return is_loading_;
551 }
552 
Reload()553 void CefBrowserHostBase::Reload() {
554   auto callback = base::BindOnce(&CefBrowserHostBase::Reload, this);
555   if (!CEF_CURRENTLY_ON_UIT()) {
556     CEF_POST_TASK(CEF_UIT, std::move(callback));
557     return;
558   }
559 
560   if (browser_info_->IsNavigationLocked(std::move(callback))) {
561     return;
562   }
563 
564   auto wc = GetWebContents();
565   if (wc) {
566     wc->GetController().Reload(content::ReloadType::NORMAL, true);
567   }
568 }
569 
ReloadIgnoreCache()570 void CefBrowserHostBase::ReloadIgnoreCache() {
571   auto callback = base::BindOnce(&CefBrowserHostBase::ReloadIgnoreCache, this);
572   if (!CEF_CURRENTLY_ON_UIT()) {
573     CEF_POST_TASK(CEF_UIT, std::move(callback));
574     return;
575   }
576 
577   if (browser_info_->IsNavigationLocked(std::move(callback))) {
578     return;
579   }
580 
581   auto wc = GetWebContents();
582   if (wc) {
583     wc->GetController().Reload(content::ReloadType::BYPASSING_CACHE, true);
584   }
585 }
586 
StopLoad()587 void CefBrowserHostBase::StopLoad() {
588   auto callback = base::BindOnce(&CefBrowserHostBase::StopLoad, this);
589   if (!CEF_CURRENTLY_ON_UIT()) {
590     CEF_POST_TASK(CEF_UIT, std::move(callback));
591     return;
592   }
593 
594   if (browser_info_->IsNavigationLocked(std::move(callback))) {
595     return;
596   }
597 
598   auto wc = GetWebContents();
599   if (wc) {
600     wc->Stop();
601   }
602 }
603 
GetIdentifier()604 int CefBrowserHostBase::GetIdentifier() {
605   return browser_id();
606 }
607 
IsSame(CefRefPtr<CefBrowser> that)608 bool CefBrowserHostBase::IsSame(CefRefPtr<CefBrowser> that) {
609   auto impl = static_cast<CefBrowserHostBase*>(that.get());
610   return (impl == this);
611 }
612 
HasDocument()613 bool CefBrowserHostBase::HasDocument() {
614   base::AutoLock lock_scope(state_lock_);
615   return has_document_;
616 }
617 
IsPopup()618 bool CefBrowserHostBase::IsPopup() {
619   return browser_info_->is_popup();
620 }
621 
GetMainFrame()622 CefRefPtr<CefFrame> CefBrowserHostBase::GetMainFrame() {
623   return GetFrame(CefFrameHostImpl::kMainFrameId);
624 }
625 
GetFocusedFrame()626 CefRefPtr<CefFrame> CefBrowserHostBase::GetFocusedFrame() {
627   return GetFrame(CefFrameHostImpl::kFocusedFrameId);
628 }
629 
GetFrame(int64 identifier)630 CefRefPtr<CefFrame> CefBrowserHostBase::GetFrame(int64 identifier) {
631   if (identifier == CefFrameHostImpl::kInvalidFrameId) {
632     return nullptr;
633   } else if (identifier == CefFrameHostImpl::kMainFrameId) {
634     return browser_info_->GetMainFrame();
635   } else if (identifier == CefFrameHostImpl::kFocusedFrameId) {
636     base::AutoLock lock_scope(state_lock_);
637     if (!focused_frame_) {
638       // The main frame is focused by default.
639       return browser_info_->GetMainFrame();
640     }
641     return focused_frame_;
642   }
643 
644   return browser_info_->GetFrameForId(identifier);
645 }
646 
GetFrame(const CefString & name)647 CefRefPtr<CefFrame> CefBrowserHostBase::GetFrame(const CefString& name) {
648   for (const auto& frame : browser_info_->GetAllFrames()) {
649     if (frame->GetName() == name)
650       return frame;
651   }
652   return nullptr;
653 }
654 
GetFrameCount()655 size_t CefBrowserHostBase::GetFrameCount() {
656   return browser_info_->GetAllFrames().size();
657 }
658 
GetFrameIdentifiers(std::vector<int64> & identifiers)659 void CefBrowserHostBase::GetFrameIdentifiers(std::vector<int64>& identifiers) {
660   if (identifiers.size() > 0)
661     identifiers.clear();
662 
663   const auto frames = browser_info_->GetAllFrames();
664   if (frames.empty())
665     return;
666 
667   identifiers.reserve(frames.size());
668   for (const auto& frame : frames) {
669     identifiers.push_back(frame->GetIdentifier());
670   }
671 }
672 
GetFrameNames(std::vector<CefString> & names)673 void CefBrowserHostBase::GetFrameNames(std::vector<CefString>& names) {
674   if (names.size() > 0)
675     names.clear();
676 
677   const auto frames = browser_info_->GetAllFrames();
678   if (frames.empty())
679     return;
680 
681   names.reserve(frames.size());
682   for (const auto& frame : frames) {
683     names.push_back(frame->GetName());
684   }
685 }
686 
OnStateChanged(CefBrowserContentsState state_changed)687 void CefBrowserHostBase::OnStateChanged(CefBrowserContentsState state_changed) {
688   // Make sure that CefBrowser state is consistent before the associated
689   // CefClient callback is executed.
690   base::AutoLock lock_scope(state_lock_);
691   if ((state_changed & CefBrowserContentsState::kNavigation) ==
692       CefBrowserContentsState::kNavigation) {
693     is_loading_ = contents_delegate_->is_loading();
694     can_go_back_ = contents_delegate_->can_go_back();
695     can_go_forward_ = contents_delegate_->can_go_forward();
696   }
697   if ((state_changed & CefBrowserContentsState::kDocument) ==
698       CefBrowserContentsState::kDocument) {
699     has_document_ = contents_delegate_->has_document();
700   }
701   if ((state_changed & CefBrowserContentsState::kFullscreen) ==
702       CefBrowserContentsState::kFullscreen) {
703     is_fullscreen_ = contents_delegate_->is_fullscreen();
704   }
705   if ((state_changed & CefBrowserContentsState::kFocusedFrame) ==
706       CefBrowserContentsState::kFocusedFrame) {
707     focused_frame_ = contents_delegate_->focused_frame();
708   }
709 }
710 
OnWebContentsDestroyed(content::WebContents * web_contents)711 void CefBrowserHostBase::OnWebContentsDestroyed(
712     content::WebContents* web_contents) {}
713 
GetFrameForHost(const content::RenderFrameHost * host)714 CefRefPtr<CefFrame> CefBrowserHostBase::GetFrameForHost(
715     const content::RenderFrameHost* host) {
716   CEF_REQUIRE_UIT();
717   if (!host)
718     return nullptr;
719 
720   return browser_info_->GetFrameForHost(host);
721 }
722 
GetFrameForFrameTreeNode(int frame_tree_node_id)723 CefRefPtr<CefFrame> CefBrowserHostBase::GetFrameForFrameTreeNode(
724     int frame_tree_node_id) {
725   return browser_info_->GetFrameForFrameTreeNode(frame_tree_node_id, nullptr);
726 }
727 
AddObserver(Observer * observer)728 void CefBrowserHostBase::AddObserver(Observer* observer) {
729   CEF_REQUIRE_UIT();
730   observers_.AddObserver(observer);
731 }
732 
RemoveObserver(Observer * observer)733 void CefBrowserHostBase::RemoveObserver(Observer* observer) {
734   CEF_REQUIRE_UIT();
735   observers_.RemoveObserver(observer);
736 }
737 
HasObserver(Observer * observer) const738 bool CefBrowserHostBase::HasObserver(Observer* observer) const {
739   CEF_REQUIRE_UIT();
740   return observers_.HasObserver(observer);
741 }
742 
LoadMainFrameURL(const content::OpenURLParams & params)743 void CefBrowserHostBase::LoadMainFrameURL(
744     const content::OpenURLParams& params) {
745   auto callback =
746       base::BindOnce(&CefBrowserHostBase::LoadMainFrameURL, this, params);
747   if (!CEF_CURRENTLY_ON_UIT()) {
748     CEF_POST_TASK(CEF_UIT, std::move(callback));
749     return;
750   }
751 
752   if (browser_info_->IsNavigationLocked(std::move(callback))) {
753     return;
754   }
755 
756   if (Navigate(params)) {
757     OnSetFocus(FOCUS_SOURCE_NAVIGATION);
758   }
759 }
760 
Navigate(const content::OpenURLParams & params)761 bool CefBrowserHostBase::Navigate(const content::OpenURLParams& params) {
762   CEF_REQUIRE_UIT();
763   auto web_contents = GetWebContents();
764   if (web_contents) {
765     GURL gurl = params.url;
766     if (!url_util::FixupGURL(gurl))
767       return false;
768 
769     web_contents->GetController().LoadURL(
770         gurl, params.referrer, params.transition, params.extra_headers);
771     return true;
772   }
773   return false;
774 }
775 
OnDidFinishLoad(CefRefPtr<CefFrameHostImpl> frame,const GURL & validated_url,int http_status_code)776 void CefBrowserHostBase::OnDidFinishLoad(CefRefPtr<CefFrameHostImpl> frame,
777                                          const GURL& validated_url,
778                                          int http_status_code) {
779   frame->RefreshAttributes();
780 
781   contents_delegate_->OnLoadEnd(frame, validated_url, http_status_code);
782 }
783 
ViewText(const std::string & text)784 void CefBrowserHostBase::ViewText(const std::string& text) {
785   if (!CEF_CURRENTLY_ON_UIT()) {
786     CEF_POST_TASK(CEF_UIT,
787                   base::BindOnce(&CefBrowserHostBase::ViewText, this, text));
788     return;
789   }
790 
791   if (platform_delegate_)
792     platform_delegate_->ViewText(text);
793 }
794 
MaybeAllowNavigation(content::RenderFrameHost * opener,bool is_guest_view,const content::OpenURLParams & params)795 bool CefBrowserHostBase::MaybeAllowNavigation(
796     content::RenderFrameHost* opener,
797     bool is_guest_view,
798     const content::OpenURLParams& params) {
799   return true;
800 }
801 
OnAfterCreated()802 void CefBrowserHostBase::OnAfterCreated() {
803   CEF_REQUIRE_UIT();
804   if (client_) {
805     if (auto handler = client_->GetLifeSpanHandler()) {
806       handler->OnAfterCreated(this);
807     }
808   }
809 }
810 
OnBeforeClose()811 void CefBrowserHostBase::OnBeforeClose() {
812   CEF_REQUIRE_UIT();
813   if (client_) {
814     if (auto handler = client_->GetLifeSpanHandler()) {
815       handler->OnBeforeClose(this);
816     }
817   }
818 }
819 
OnBrowserDestroyed()820 void CefBrowserHostBase::OnBrowserDestroyed() {
821   CEF_REQUIRE_UIT();
822   for (auto& observer : observers_)
823     observer.OnBrowserDestroyed(this);
824 }
825 
browser_id() const826 int CefBrowserHostBase::browser_id() const {
827   return browser_info_->browser_id();
828 }
829 
GetBackgroundColor() const830 SkColor CefBrowserHostBase::GetBackgroundColor() const {
831   // Don't use |platform_delegate_| because it's not thread-safe.
832   return CefContext::Get()->GetBackgroundColor(
833       &settings_, IsWindowless() ? STATE_ENABLED : STATE_DISABLED);
834 }
835 
IsWindowless() const836 bool CefBrowserHostBase::IsWindowless() const {
837   return false;
838 }
839 
GetWebContents() const840 content::WebContents* CefBrowserHostBase::GetWebContents() const {
841   CEF_REQUIRE_UIT();
842   return contents_delegate_->web_contents();
843 }
844 
GetBrowserContext() const845 content::BrowserContext* CefBrowserHostBase::GetBrowserContext() const {
846   CEF_REQUIRE_UIT();
847   auto web_contents = GetWebContents();
848   if (web_contents)
849     return web_contents->GetBrowserContext();
850   return nullptr;
851 }
852 
853 #if defined(TOOLKIT_VIEWS)
GetWindowWidget() const854 views::Widget* CefBrowserHostBase::GetWindowWidget() const {
855   CEF_REQUIRE_UIT();
856   if (!platform_delegate_)
857     return nullptr;
858   return platform_delegate_->GetWindowWidget();
859 }
860 
GetBrowserView() const861 CefRefPtr<CefBrowserView> CefBrowserHostBase::GetBrowserView() const {
862   CEF_REQUIRE_UIT();
863   if (is_views_hosted_ && platform_delegate_)
864     return platform_delegate_->GetBrowserView();
865   return nullptr;
866 }
867 #endif  // defined(TOOLKIT_VIEWS)
868 
EnsureDevToolsManager()869 bool CefBrowserHostBase::EnsureDevToolsManager() {
870   CEF_REQUIRE_UIT();
871   if (!contents_delegate_->web_contents())
872     return false;
873 
874   if (!devtools_manager_) {
875     devtools_manager_.reset(new CefDevToolsManager(this));
876   }
877   return true;
878 }
879 
InitializeDevToolsRegistrationOnUIThread(CefRefPtr<CefRegistration> registration)880 void CefBrowserHostBase::InitializeDevToolsRegistrationOnUIThread(
881     CefRefPtr<CefRegistration> registration) {
882   if (!CEF_CURRENTLY_ON_UIT()) {
883     CEF_POST_TASK(
884         CEF_UIT,
885         base::BindOnce(
886             &CefBrowserHostBase::InitializeDevToolsRegistrationOnUIThread, this,
887             registration));
888     return;
889   }
890 
891   if (!EnsureDevToolsManager())
892     return;
893   devtools_manager_->InitializeRegistrationOnUIThread(registration);
894 }
895