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