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