• 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/chrome/chrome_browser_host_impl.h"
6 
7 #include "libcef/browser/browser_platform_delegate.h"
8 #include "libcef/browser/chrome/browser_platform_delegate_chrome.h"
9 #include "libcef/browser/thread_util.h"
10 #include "libcef/browser/views/browser_view_impl.h"
11 #include "libcef/common/net/url_util.h"
12 #include "libcef/features/runtime_checks.h"
13 
14 #include "base/logging.h"
15 #include "base/notreached.h"
16 #include "chrome/browser/printing/print_view_manager_common.h"
17 #include "chrome/browser/profiles/profile.h"
18 #include "chrome/browser/ui/browser.h"
19 #include "chrome/browser/ui/browser_commands.h"
20 #include "chrome/browser/ui/browser_navigator.h"
21 #include "chrome/browser/ui/browser_tabstrip.h"
22 #include "chrome/browser/ui/browser_window.h"
23 #include "chrome/browser/ui/tabs/tab_strip_model.h"
24 #include "chrome/common/pref_names.h"
25 
26 #if defined(TOOLKIT_VIEWS)
27 #include "libcef/browser/chrome/views/chrome_browser_frame.h"
28 #include "libcef/browser/chrome/views/chrome_browser_view.h"
29 #endif
30 
31 // static
Create(const CefBrowserCreateParams & params)32 CefRefPtr<ChromeBrowserHostImpl> ChromeBrowserHostImpl::Create(
33     const CefBrowserCreateParams& params) {
34   auto browser = CreateBrowser(params);
35 
36   GURL url = url_util::MakeGURL(params.url, /*fixup=*/true);
37   if (url.is_empty()) {
38     // Chrome will navigate to kChromeUINewTabURL by default. We want to keep
39     // the current CEF behavior of not navigating at all. Use a special URL that
40     // will be recognized in HandleNonNavigationAboutURL.
41     url = GURL("chrome://ignore/");
42   }
43 
44   // Add a new tab. This will indirectly create a new tab WebContents and
45   // call ChromeBrowserDelegate::OnWebContentsCreated to create the associated
46   // ChromeBrowserHostImpl.
47   chrome::AddTabAt(browser, url, /*index=*/TabStripModel::kNoTab,
48                    /*foreground=*/true);
49 
50   // The new tab WebContents.
51   auto web_contents = browser->tab_strip_model()->GetActiveWebContents();
52   CHECK(web_contents);
53 
54   // The associated ChromeBrowserHostImpl.
55   auto browser_host =
56       ChromeBrowserHostImpl::GetBrowserForContents(web_contents);
57   CHECK(browser_host);
58 
59   return browser_host;
60 }
61 
62 // static
GetBrowserForHost(const content::RenderViewHost * host)63 CefRefPtr<ChromeBrowserHostImpl> ChromeBrowserHostImpl::GetBrowserForHost(
64     const content::RenderViewHost* host) {
65   REQUIRE_CHROME_RUNTIME();
66   auto browser = CefBrowserHostBase::GetBrowserForHost(host);
67   return static_cast<ChromeBrowserHostImpl*>(browser.get());
68 }
69 
70 // static
GetBrowserForHost(const content::RenderFrameHost * host)71 CefRefPtr<ChromeBrowserHostImpl> ChromeBrowserHostImpl::GetBrowserForHost(
72     const content::RenderFrameHost* host) {
73   REQUIRE_CHROME_RUNTIME();
74   auto browser = CefBrowserHostBase::GetBrowserForHost(host);
75   return static_cast<ChromeBrowserHostImpl*>(browser.get());
76 }
77 
78 // static
GetBrowserForContents(const content::WebContents * contents)79 CefRefPtr<ChromeBrowserHostImpl> ChromeBrowserHostImpl::GetBrowserForContents(
80     const content::WebContents* contents) {
81   REQUIRE_CHROME_RUNTIME();
82   auto browser = CefBrowserHostBase::GetBrowserForContents(contents);
83   return static_cast<ChromeBrowserHostImpl*>(browser.get());
84 }
85 
86 // static
GetBrowserForGlobalId(const content::GlobalRenderFrameHostId & global_id)87 CefRefPtr<ChromeBrowserHostImpl> ChromeBrowserHostImpl::GetBrowserForGlobalId(
88     const content::GlobalRenderFrameHostId& global_id) {
89   REQUIRE_CHROME_RUNTIME();
90   auto browser = CefBrowserHostBase::GetBrowserForGlobalId(global_id);
91   return static_cast<ChromeBrowserHostImpl*>(browser.get());
92 }
93 
94 ChromeBrowserHostImpl::~ChromeBrowserHostImpl() = default;
95 
AddNewContents(std::unique_ptr<content::WebContents> contents)96 void ChromeBrowserHostImpl::AddNewContents(
97     std::unique_ptr<content::WebContents> contents) {
98   DCHECK(contents);
99   DCHECK(!browser_);
100 
101   // We should already be associated with the WebContents.
102   DCHECK_EQ(GetWebContents(), contents.get());
103 
104   CefBrowserCreateParams params;
105   params.request_context = request_context();
106 #if defined(TOOLKIT_VIEWS)
107   params.browser_view = GetBrowserView();
108 #endif
109 
110   // Create the new Browser representation.
111   auto browser = CreateBrowser(params);
112 
113   // Add the WebContents to the Browser.
114   browser->tab_strip_model()->AddWebContents(
115       std::move(contents), /*index=*/TabStripModel::kNoTab,
116       ui::PageTransition::PAGE_TRANSITION_AUTO_TOPLEVEL,
117       TabStripModel::ADD_ACTIVE);
118 
119   SetBrowser(browser);
120 }
121 
OnWebContentsDestroyed(content::WebContents * web_contents)122 void ChromeBrowserHostImpl::OnWebContentsDestroyed(
123     content::WebContents* web_contents) {
124   platform_delegate_->WebContentsDestroyed(web_contents);
125   DestroyBrowser();
126 }
127 
OnSetFocus(cef_focus_source_t source)128 void ChromeBrowserHostImpl::OnSetFocus(cef_focus_source_t source) {
129   if (!CEF_CURRENTLY_ON_UIT()) {
130     CEF_POST_TASK(CEF_UIT, base::BindOnce(&ChromeBrowserHostImpl::OnSetFocus,
131                                           this, source));
132     return;
133   }
134 
135   if (contents_delegate_->OnSetFocus(source))
136     return;
137 
138   if (browser_) {
139     const int tab_index = GetCurrentTabIndex();
140     if (tab_index != TabStripModel::kNoTab) {
141       chrome::SelectNumberedTab(browser_, tab_index);
142     }
143   }
144 }
145 
CloseBrowser(bool force_close)146 void ChromeBrowserHostImpl::CloseBrowser(bool force_close) {
147   // Always do this asynchronously because TabStripModel is not re-entrant.
148   CEF_POST_TASK(CEF_UIT, base::BindOnce(&ChromeBrowserHostImpl::DoCloseBrowser,
149                                         this, force_close));
150 }
151 
TryCloseBrowser()152 bool ChromeBrowserHostImpl::TryCloseBrowser() {
153   // TODO(chrome): Handle the case where the browser may not close immediately.
154   CloseBrowser(true);
155   return true;
156 }
157 
SetFocus(bool focus)158 void ChromeBrowserHostImpl::SetFocus(bool focus) {
159   if (focus) {
160     OnSetFocus(FOCUS_SOURCE_SYSTEM);
161   }
162 }
163 
GetWindowHandle()164 CefWindowHandle ChromeBrowserHostImpl::GetWindowHandle() {
165   NOTIMPLEMENTED();
166   return kNullWindowHandle;
167 }
168 
GetOpenerWindowHandle()169 CefWindowHandle ChromeBrowserHostImpl::GetOpenerWindowHandle() {
170   NOTIMPLEMENTED();
171   return kNullWindowHandle;
172 }
173 
GetZoomLevel()174 double ChromeBrowserHostImpl::GetZoomLevel() {
175   NOTIMPLEMENTED();
176   return 0.0;
177 }
178 
SetZoomLevel(double zoomLevel)179 void ChromeBrowserHostImpl::SetZoomLevel(double zoomLevel) {
180   NOTIMPLEMENTED();
181 }
182 
RunFileDialog(FileDialogMode mode,const CefString & title,const CefString & default_file_path,const std::vector<CefString> & accept_filters,int selected_accept_filter,CefRefPtr<CefRunFileDialogCallback> callback)183 void ChromeBrowserHostImpl::RunFileDialog(
184     FileDialogMode mode,
185     const CefString& title,
186     const CefString& default_file_path,
187     const std::vector<CefString>& accept_filters,
188     int selected_accept_filter,
189     CefRefPtr<CefRunFileDialogCallback> callback) {
190   NOTIMPLEMENTED();
191   callback->OnFileDialogDismissed(0, {});
192 }
193 
Print()194 void ChromeBrowserHostImpl::Print() {
195   if (!CEF_CURRENTLY_ON_UIT()) {
196     CEF_POST_TASK(CEF_UIT, base::BindOnce(&ChromeBrowserHostImpl::Print, this));
197     return;
198   }
199 
200   if (browser_) {
201     // Like chrome::Print() but specifying the WebContents.
202     printing::StartPrint(GetWebContents(),
203                          /*print_renderer=*/mojo::NullAssociatedRemote(),
204                          browser_->profile()->GetPrefs()->GetBoolean(
205                              prefs::kPrintPreviewDisabled),
206                          /*has_selection=*/false);
207   }
208 }
209 
PrintToPDF(const CefString & path,const CefPdfPrintSettings & settings,CefRefPtr<CefPdfPrintCallback> callback)210 void ChromeBrowserHostImpl::PrintToPDF(
211     const CefString& path,
212     const CefPdfPrintSettings& settings,
213     CefRefPtr<CefPdfPrintCallback> callback) {
214   NOTIMPLEMENTED();
215   callback->OnPdfPrintFinished(CefString(), false);
216 }
217 
Find(const CefString & searchText,bool forward,bool matchCase,bool findNext)218 void ChromeBrowserHostImpl::Find(const CefString& searchText,
219                                  bool forward,
220                                  bool matchCase,
221                                  bool findNext) {
222   NOTIMPLEMENTED();
223 }
224 
StopFinding(bool clearSelection)225 void ChromeBrowserHostImpl::StopFinding(bool clearSelection) {
226   NOTIMPLEMENTED();
227 }
228 
ShowDevTools(const CefWindowInfo & windowInfo,CefRefPtr<CefClient> client,const CefBrowserSettings & settings,const CefPoint & inspect_element_at)229 void ChromeBrowserHostImpl::ShowDevTools(const CefWindowInfo& windowInfo,
230                                          CefRefPtr<CefClient> client,
231                                          const CefBrowserSettings& settings,
232                                          const CefPoint& inspect_element_at) {
233   NOTIMPLEMENTED();
234 }
235 
CloseDevTools()236 void ChromeBrowserHostImpl::CloseDevTools() {
237   NOTIMPLEMENTED();
238 }
239 
HasDevTools()240 bool ChromeBrowserHostImpl::HasDevTools() {
241   NOTIMPLEMENTED();
242   return false;
243 }
244 
IsWindowRenderingDisabled()245 bool ChromeBrowserHostImpl::IsWindowRenderingDisabled() {
246   return false;
247 }
248 
WasResized()249 void ChromeBrowserHostImpl::WasResized() {
250   NOTIMPLEMENTED();
251 }
252 
WasHidden(bool hidden)253 void ChromeBrowserHostImpl::WasHidden(bool hidden) {
254   NOTIMPLEMENTED();
255 }
256 
NotifyScreenInfoChanged()257 void ChromeBrowserHostImpl::NotifyScreenInfoChanged() {
258   NOTIMPLEMENTED();
259 }
260 
Invalidate(PaintElementType type)261 void ChromeBrowserHostImpl::Invalidate(PaintElementType type) {
262   NOTIMPLEMENTED();
263 }
264 
SendExternalBeginFrame()265 void ChromeBrowserHostImpl::SendExternalBeginFrame() {
266   NOTIMPLEMENTED();
267 }
268 
SendTouchEvent(const CefTouchEvent & event)269 void ChromeBrowserHostImpl::SendTouchEvent(const CefTouchEvent& event) {
270   NOTIMPLEMENTED();
271 }
272 
SendCaptureLostEvent()273 void ChromeBrowserHostImpl::SendCaptureLostEvent() {
274   NOTIMPLEMENTED();
275 }
276 
NotifyMoveOrResizeStarted()277 void ChromeBrowserHostImpl::NotifyMoveOrResizeStarted() {
278   NOTIMPLEMENTED();
279 }
280 
GetWindowlessFrameRate()281 int ChromeBrowserHostImpl::GetWindowlessFrameRate() {
282   return 0;
283 }
284 
SetWindowlessFrameRate(int frame_rate)285 void ChromeBrowserHostImpl::SetWindowlessFrameRate(int frame_rate) {}
286 
ImeSetComposition(const CefString & text,const std::vector<CefCompositionUnderline> & underlines,const CefRange & replacement_range,const CefRange & selection_range)287 void ChromeBrowserHostImpl::ImeSetComposition(
288     const CefString& text,
289     const std::vector<CefCompositionUnderline>& underlines,
290     const CefRange& replacement_range,
291     const CefRange& selection_range) {
292   NOTIMPLEMENTED();
293 }
294 
ImeCommitText(const CefString & text,const CefRange & replacement_range,int relative_cursor_pos)295 void ChromeBrowserHostImpl::ImeCommitText(const CefString& text,
296                                           const CefRange& replacement_range,
297                                           int relative_cursor_pos) {
298   NOTIMPLEMENTED();
299 }
ImeFinishComposingText(bool keep_selection)300 void ChromeBrowserHostImpl::ImeFinishComposingText(bool keep_selection) {
301   NOTIMPLEMENTED();
302 }
303 
ImeCancelComposition()304 void ChromeBrowserHostImpl::ImeCancelComposition() {
305   NOTIMPLEMENTED();
306 }
307 
DragTargetDragEnter(CefRefPtr<CefDragData> drag_data,const CefMouseEvent & event,DragOperationsMask allowed_ops)308 void ChromeBrowserHostImpl::DragTargetDragEnter(
309     CefRefPtr<CefDragData> drag_data,
310     const CefMouseEvent& event,
311     DragOperationsMask allowed_ops) {
312   NOTIMPLEMENTED();
313 }
314 
DragTargetDragOver(const CefMouseEvent & event,DragOperationsMask allowed_ops)315 void ChromeBrowserHostImpl::DragTargetDragOver(const CefMouseEvent& event,
316                                                DragOperationsMask allowed_ops) {
317   NOTIMPLEMENTED();
318 }
319 
DragTargetDragLeave()320 void ChromeBrowserHostImpl::DragTargetDragLeave() {
321   NOTIMPLEMENTED();
322 }
323 
DragTargetDrop(const CefMouseEvent & event)324 void ChromeBrowserHostImpl::DragTargetDrop(const CefMouseEvent& event) {
325   NOTIMPLEMENTED();
326 }
327 
DragSourceSystemDragEnded()328 void ChromeBrowserHostImpl::DragSourceSystemDragEnded() {
329   NOTIMPLEMENTED();
330 }
331 
DragSourceEndedAt(int x,int y,DragOperationsMask op)332 void ChromeBrowserHostImpl::DragSourceEndedAt(int x,
333                                               int y,
334                                               DragOperationsMask op) {
335   NOTIMPLEMENTED();
336 }
337 
SetAudioMuted(bool mute)338 void ChromeBrowserHostImpl::SetAudioMuted(bool mute) {
339   NOTIMPLEMENTED();
340 }
341 
IsAudioMuted()342 bool ChromeBrowserHostImpl::IsAudioMuted() {
343   NOTIMPLEMENTED();
344   return false;
345 }
346 
SetAccessibilityState(cef_state_t accessibility_state)347 void ChromeBrowserHostImpl::SetAccessibilityState(
348     cef_state_t accessibility_state) {
349   NOTIMPLEMENTED();
350 }
351 
SetAutoResizeEnabled(bool enabled,const CefSize & min_size,const CefSize & max_size)352 void ChromeBrowserHostImpl::SetAutoResizeEnabled(bool enabled,
353                                                  const CefSize& min_size,
354                                                  const CefSize& max_size) {
355   NOTIMPLEMENTED();
356 }
357 
GetExtension()358 CefRefPtr<CefExtension> ChromeBrowserHostImpl::GetExtension() {
359   return nullptr;
360 }
361 
IsBackgroundHost()362 bool ChromeBrowserHostImpl::IsBackgroundHost() {
363   return false;
364 }
365 
Navigate(const content::OpenURLParams & params)366 bool ChromeBrowserHostImpl::Navigate(const content::OpenURLParams& params) {
367   CEF_REQUIRE_UIT();
368   if (GetCurrentTabIndex() == TabStripModel::kNoTab) {
369     // We can't navigate via the Browser because we don't have a current tab.
370     return CefBrowserHostBase::Navigate(params);
371   }
372 
373   if (browser_) {
374     GURL gurl = params.url;
375     if (!url_util::FixupGURL(gurl))
376       return false;
377 
378     // This is generally equivalent to calling Browser::OpenURL, except:
379     // 1. It doesn't trigger a call to CefRequestHandler::OnOpenURLFromTab, and
380     // 2. It navigates in this CefBrowserHost's WebContents instead of
381     //    (a) creating a new WebContents, or (b) using the Browser's active
382     //    WebContents (which may not be the same), and
383     // 3. There is no risk of triggering chrome's popup blocker.
384     NavigateParams nav_params(browser_, gurl, params.transition);
385     nav_params.FillNavigateParamsFromOpenURLParams(params);
386 
387     // Always navigate in the current tab.
388     nav_params.disposition = WindowOpenDisposition::CURRENT_TAB;
389     nav_params.source_contents = GetWebContents();
390 
391     nav_params.tabstrip_add_types = TabStripModel::ADD_NONE;
392     if (params.user_gesture)
393       nav_params.window_action = NavigateParams::SHOW_WINDOW;
394     ::Navigate(&nav_params);
395     return true;
396   }
397   return false;
398 }
399 
ChromeBrowserHostImpl(const CefBrowserSettings & settings,CefRefPtr<CefClient> client,std::unique_ptr<CefBrowserPlatformDelegate> platform_delegate,scoped_refptr<CefBrowserInfo> browser_info,CefRefPtr<CefRequestContextImpl> request_context)400 ChromeBrowserHostImpl::ChromeBrowserHostImpl(
401     const CefBrowserSettings& settings,
402     CefRefPtr<CefClient> client,
403     std::unique_ptr<CefBrowserPlatformDelegate> platform_delegate,
404     scoped_refptr<CefBrowserInfo> browser_info,
405     CefRefPtr<CefRequestContextImpl> request_context)
406     : CefBrowserHostBase(settings,
407                          client,
408                          std::move(platform_delegate),
409                          browser_info,
410                          request_context) {}
411 
412 // static
CreateBrowser(const CefBrowserCreateParams & params)413 Browser* ChromeBrowserHostImpl::CreateBrowser(
414     const CefBrowserCreateParams& params) {
415   // Get or create the request context and profile.
416   CefRefPtr<CefRequestContextImpl> request_context_impl =
417       CefRequestContextImpl::GetOrCreateForRequestContext(
418           params.request_context);
419   CHECK(request_context_impl);
420   auto cef_browser_context = request_context_impl->GetBrowserContext();
421   CHECK(cef_browser_context);
422   auto profile = cef_browser_context->AsProfile();
423   CHECK(profile);
424 
425   Browser::CreateParams chrome_params =
426       Browser::CreateParams(profile, /*user_gesture=*/false);
427 
428   // Pass |params| to cef::BrowserDelegate::Create from the Browser constructor.
429   chrome_params.cef_params = base::MakeRefCounted<DelegateCreateParams>(params);
430 
431 #if defined(TOOLKIT_VIEWS)
432   // Configure Browser creation to use the existing Views-based
433   // Widget/BrowserFrame (ChromeBrowserFrame) and BrowserView/BrowserWindow
434   // (ChromeBrowserView). See views/chrome_browser_frame.h for related
435   // documentation.
436   ChromeBrowserView* chrome_browser_view = nullptr;
437   if (params.browser_view) {
438     // Don't show most controls.
439     chrome_params.type = Browser::TYPE_POPUP;
440     // Don't show title bar or address.
441     chrome_params.trusted_source = true;
442 
443     auto view_impl =
444         static_cast<CefBrowserViewImpl*>(params.browser_view.get());
445 
446     chrome_browser_view =
447         static_cast<ChromeBrowserView*>(view_impl->root_view());
448     chrome_params.window = chrome_browser_view;
449 
450     auto chrome_widget =
451         static_cast<ChromeBrowserFrame*>(chrome_browser_view->GetWidget());
452     chrome_browser_view->set_frame(chrome_widget);
453   }
454 #endif  // defined(TOOLKIT_VIEWS)
455 
456   // Create the Browser. This will indirectly create the ChomeBrowserDelegate.
457   // The same params will be used to create a new Browser if the tab is dragged
458   // out of the existing Browser. The returned Browser is owned by the
459   // associated BrowserView.
460   auto browser = Browser::Create(chrome_params);
461 
462   bool show_browser = true;
463 
464 #if defined(TOOLKIT_VIEWS)
465   if (chrome_browser_view) {
466     // Initialize the BrowserFrame and BrowserView and create the controls that
467     // require access to the Browser.
468     chrome_browser_view->InitBrowser(base::WrapUnique(browser),
469                                      params.browser_view);
470 
471     // Don't show the browser by default.
472     show_browser = false;
473   }
474 #endif
475 
476   if (show_browser) {
477     browser->window()->Show();
478   }
479 
480   return browser;
481 }
482 
Attach(content::WebContents * web_contents,CefRefPtr<ChromeBrowserHostImpl> opener)483 void ChromeBrowserHostImpl::Attach(content::WebContents* web_contents,
484                                    CefRefPtr<ChromeBrowserHostImpl> opener) {
485   DCHECK(web_contents);
486 
487   if (opener) {
488     // Give the opener browser's platform delegate an opportunity to modify the
489     // new browser's platform delegate.
490     opener->platform_delegate_->PopupWebContentsCreated(
491         settings_, client_, web_contents, platform_delegate_.get(),
492         /*is_devtools_popup=*/false);
493   }
494 
495   platform_delegate_->WebContentsCreated(web_contents,
496                                          /*own_web_contents=*/false);
497   contents_delegate_->ObserveWebContents(web_contents);
498 
499   // Associate the platform delegate with this browser.
500   platform_delegate_->BrowserCreated(this);
501 
502   // Associate the base class with the WebContents.
503   InitializeBrowser();
504 
505   // Notify that the browser has been created. These must be delivered in the
506   // expected order.
507 
508   // 1. Notify the browser's LifeSpanHandler. This must always be the first
509   // notification for the browser.
510   {
511     // The WebContents won't be added to the Browser's TabStripModel until later
512     // in the current call stack. Block navigation until that time.
513     auto navigation_lock = browser_info_->CreateNavigationLock();
514     OnAfterCreated();
515   }
516 
517   // 2. Notify the platform delegate. With Views this will result in a call to
518   // CefBrowserViewDelegate::OnBrowserCreated().
519   platform_delegate_->NotifyBrowserCreated();
520 
521   if (opener && opener->platform_delegate_) {
522     // 3. Notify the opener browser's platform delegate. With Views this will
523     // result in a call to CefBrowserViewDelegate::OnPopupBrowserViewCreated().
524     opener->platform_delegate_->PopupBrowserCreated(
525         this,
526         /*is_devtools_popup=*/false);
527   }
528 }
529 
SetBrowser(Browser * browser)530 void ChromeBrowserHostImpl::SetBrowser(Browser* browser) {
531   CEF_REQUIRE_UIT();
532   browser_ = browser;
533   static_cast<CefBrowserPlatformDelegateChrome*>(platform_delegate_.get())
534       ->set_chrome_browser(browser);
535 }
536 
WindowDestroyed()537 void ChromeBrowserHostImpl::WindowDestroyed() {
538   CEF_REQUIRE_UIT();
539 #if defined(TOOLKIT_VIEWS)
540   if (browser_ && is_views_hosted_) {
541     auto chrome_browser_view =
542         static_cast<ChromeBrowserView*>(browser_->window());
543     chrome_browser_view->Destroyed();
544   }
545 #endif
546 
547   platform_delegate_->CloseHostWindow();
548 }
549 
DestroyBrowser()550 void ChromeBrowserHostImpl::DestroyBrowser() {
551   CEF_REQUIRE_UIT();
552   browser_ = nullptr;
553 
554   OnBeforeClose();
555   OnBrowserDestroyed();
556 
557   // Disassociate the platform delegate from this browser.
558   platform_delegate_->BrowserDestroyed(this);
559 
560   CefBrowserHostBase::DestroyBrowser();
561 }
562 
DoCloseBrowser(bool force_close)563 void ChromeBrowserHostImpl::DoCloseBrowser(bool force_close) {
564   CEF_REQUIRE_UIT();
565   if (browser_) {
566     // Like chrome::CloseTab() but specifying the WebContents.
567     const int tab_index = GetCurrentTabIndex();
568     if (tab_index != TabStripModel::kNoTab) {
569       // TODO(chrome): Handle the case where this method returns false,
570       // indicating that the contents were not closed immediately.
571       browser_->tab_strip_model()->CloseWebContentsAt(
572           tab_index, TabStripModel::CLOSE_CREATE_HISTORICAL_TAB |
573                          TabStripModel::CLOSE_USER_GESTURE);
574     }
575   }
576 }
577 
GetCurrentTabIndex() const578 int ChromeBrowserHostImpl::GetCurrentTabIndex() const {
579   CEF_REQUIRE_UIT();
580   if (browser_) {
581     return browser_->tab_strip_model()->GetIndexOfWebContents(GetWebContents());
582   }
583   return TabStripModel::kNoTab;
584 }
585