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