1 // Copyright 2012 The Chromium 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 "chrome/browser/ui/browser_commands.h"
6 
7 #include <memory>
8 #include <utility>
9 #include <vector>
10 
11 #include "base/command_line.h"
12 #include "base/metrics/histogram_functions.h"
13 #include "base/metrics/histogram_macros.h"
14 #include "base/metrics/user_metrics.h"
15 #include "base/strings/utf_string_conversions.h"
16 #include "build/build_config.h"
17 #include "chrome/app/chrome_command_ids.h"
18 #include "chrome/browser/apps/app_service/app_launch_params.h"
19 #include "chrome/browser/apps/app_service/app_service_proxy.h"
20 #include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
21 #include "chrome/browser/apps/app_service/browser_app_launcher.h"
22 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
23 #include "chrome/browser/browser_process.h"
24 #include "chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.h"
25 #include "chrome/browser/chrome_content_browser_client.h"
26 #include "chrome/browser/devtools/devtools_window.h"
27 #include "chrome/browser/dom_distiller/tab_utils.h"
28 #include "chrome/browser/favicon/favicon_utils.h"
29 #include "chrome/browser/lifetime/application_lifetime.h"
30 #include "chrome/browser/media/router/media_router_feature.h"
31 #include "chrome/browser/prefs/incognito_mode_prefs.h"
32 #include "chrome/browser/profiles/profile.h"
33 #include "chrome/browser/sessions/session_service_factory.h"
34 #include "chrome/browser/sessions/tab_restore_service_factory.h"
35 #include "chrome/browser/translate/chrome_translate_client.h"
36 #include "chrome/browser/ui/accelerator_utils.h"
37 #include "chrome/browser/ui/autofill/payments/manage_migration_ui_controller.h"
38 #include "chrome/browser/ui/autofill/payments/save_card_bubble_controller_impl.h"
39 #include "chrome/browser/ui/bookmarks/bookmark_stats.h"
40 #include "chrome/browser/ui/bookmarks/bookmark_utils.h"
41 #include "chrome/browser/ui/bookmarks/bookmark_utils_desktop.h"
42 #include "chrome/browser/ui/browser.h"
43 #include "chrome/browser/ui/browser_command_controller.h"
44 #include "chrome/browser/ui/browser_dialogs.h"
45 #include "chrome/browser/ui/browser_live_tab_context.h"
46 #include "chrome/browser/ui/browser_navigator_params.h"
47 #include "chrome/browser/ui/browser_tabstrip.h"
48 #include "chrome/browser/ui/browser_window.h"
49 #include "chrome/browser/ui/chrome_pages.h"
50 #include "chrome/browser/ui/commander/commander.h"
51 #include "chrome/browser/ui/exclusive_access/fullscreen_controller.h"
52 #include "chrome/browser/ui/find_bar/find_bar.h"
53 #include "chrome/browser/ui/find_bar/find_bar_controller.h"
54 #include "chrome/browser/ui/location_bar/location_bar.h"
55 #include "chrome/browser/ui/passwords/manage_passwords_ui_controller.h"
56 #include "chrome/browser/ui/qrcode_generator/qrcode_generator_bubble_controller.h"
57 #include "chrome/browser/ui/read_later/reading_list_model_factory.h"
58 #include "chrome/browser/ui/scoped_tabbed_browser_displayer.h"
59 #include "chrome/browser/ui/send_tab_to_self/send_tab_to_self_bubble_controller.h"
60 #include "chrome/browser/ui/status_bubble.h"
61 #include "chrome/browser/ui/tab_contents/core_tab_helper.h"
62 #include "chrome/browser/ui/tab_dialogs.h"
63 #include "chrome/browser/ui/tabs/tab_group.h"
64 #include "chrome/browser/ui/tabs/tab_group_model.h"
65 #include "chrome/browser/ui/translate/translate_bubble_view_state_transition.h"
66 #include "chrome/browser/ui/user_education/reopen_tab_in_product_help.h"
67 #include "chrome/browser/ui/user_education/reopen_tab_in_product_help_factory.h"
68 #include "chrome/browser/ui/web_applications/app_browser_controller.h"
69 #include "chrome/browser/upgrade_detector/upgrade_detector.h"
70 #include "chrome/browser/web_applications/components/app_registrar.h"
71 #include "chrome/browser/web_applications/components/web_app_constants.h"
72 #include "chrome/browser/web_applications/components/web_app_id.h"
73 #include "chrome/browser/web_applications/components/web_app_provider_base.h"
74 #include "chrome/common/buildflags.h"
75 #include "chrome/common/content_restriction.h"
76 #include "chrome/common/pref_names.h"
77 #include "chrome/common/url_constants.h"
78 #include "components/bookmarks/browser/bookmark_model.h"
79 #include "components/bookmarks/browser/bookmark_utils.h"
80 #include "components/bookmarks/common/bookmark_pref_names.h"
81 #include "components/browsing_data/content/browsing_data_helper.h"
82 #include "components/dom_distiller/core/url_utils.h"
83 #include "components/favicon/content/content_favicon_driver.h"
84 #include "components/find_in_page/find_tab_helper.h"
85 #include "components/find_in_page/find_types.h"
86 #include "components/google/core/common/google_util.h"
87 #include "components/media_router/browser/media_router_dialog_controller.h"  // nogncheck
88 #include "components/media_router/browser/media_router_metrics.h"
89 #include "components/omnibox/browser/omnibox_prefs.h"
90 #include "components/prefs/pref_service.h"
91 #include "components/reading_list/core/reading_list_entry.h"
92 #include "components/reading_list/core/reading_list_model.h"
93 #include "components/services/app_service/public/mojom/types.mojom.h"
94 #include "components/sessions/core/live_tab_context.h"
95 #include "components/sessions/core/tab_restore_service.h"
96 #include "components/tab_groups/tab_group_id.h"
97 #include "components/tab_groups/tab_group_visual_data.h"
98 #include "components/translate/core/browser/language_state.h"
99 #include "components/version_info/version_info.h"
100 #include "components/web_modal/web_contents_modal_dialog_manager.h"
101 #include "components/zoom/page_zoom.h"
102 #include "components/zoom/zoom_controller.h"
103 #include "content/public/browser/browsing_data_remover.h"
104 #include "content/public/browser/devtools_agent_host.h"
105 #include "content/public/browser/navigation_controller.h"
106 #include "content/public/browser/navigation_entry.h"
107 #include "content/public/browser/page_navigator.h"
108 #include "content/public/browser/render_view_host.h"
109 #include "content/public/browser/render_widget_host_view.h"
110 #include "content/public/browser/web_contents.h"
111 #include "content/public/common/content_switches.h"
112 #include "content/public/common/url_constants.h"
113 #include "content/public/common/url_utils.h"
114 #include "content/public/common/user_agent.h"
115 #include "extensions/buildflags/buildflags.h"
116 #include "net/base/escape.h"
117 #include "printing/buildflags/buildflags.h"
118 #include "rlz/buildflags/buildflags.h"
119 #include "ui/base/clipboard/clipboard_buffer.h"
120 #include "ui/base/clipboard/scoped_clipboard_writer.h"
121 #include "ui/base/window_open_disposition.h"
122 #include "ui/events/keycodes/keyboard_codes.h"
123 #include "url/gurl.h"
124 #include "url/url_constants.h"
125 
126 #if BUILDFLAG(ENABLE_EXTENSIONS)
127 #include "chrome/browser/ui/extensions/app_launch_params.h"
128 #include "chrome/browser/ui/extensions/application_launch.h"
129 #include "chrome/browser/ui/extensions/settings_api_bubble_helpers.h"
130 #include "chrome/browser/web_applications/components/web_app_helpers.h"
131 #include "chrome/common/extensions/extension_metrics.h"
132 #include "chrome/common/extensions/manifest_handlers/app_launch_info.h"
133 #include "extensions/browser/extension_registry.h"
134 #include "extensions/browser/extension_system.h"
135 #include "extensions/common/extension.h"
136 #include "extensions/common/extension_set.h"
137 #endif
138 
139 #if BUILDFLAG(ENABLE_PRINTING)
140 #include "chrome/browser/printing/print_view_manager_common.h"
141 #include "mojo/public/cpp/bindings/associated_remote.h"
142 #if BUILDFLAG(ENABLE_PRINT_PREVIEW)
143 #include "chrome/browser/printing/print_preview_dialog_controller.h"
144 #endif  // BUILDFLAG(ENABLE_PRINT_PREVIEW)
145 #endif  // BUILDFLAG(ENABLE_PRINTING)
146 
147 #if BUILDFLAG(ENABLE_RLZ)
148 #include "components/rlz/rlz_tracker.h"  // nogncheck
149 #endif
150 
151 namespace {
152 
153 const char kOsOverrideForTabletSite[] = "Linux; Android 9; Chrome tablet";
154 const char kChPlatformOverrideForTabletSite[] = "Android";
155 
TranslateBubbleResultToUiEvent(ShowTranslateBubbleResult result)156 translate::TranslateBubbleUiEvent TranslateBubbleResultToUiEvent(
157     ShowTranslateBubbleResult result) {
158   switch (result) {
159     default:
160       NOTREACHED();
161       FALLTHROUGH;
162     case ShowTranslateBubbleResult::SUCCESS:
163       return translate::TranslateBubbleUiEvent::BUBBLE_SHOWN;
164     case ShowTranslateBubbleResult::BROWSER_WINDOW_NOT_VALID:
165       return translate::TranslateBubbleUiEvent::
166           BUBBLE_NOT_SHOWN_WINDOW_NOT_VALID;
167     case ShowTranslateBubbleResult::BROWSER_WINDOW_MINIMIZED:
168       return translate::TranslateBubbleUiEvent::
169           BUBBLE_NOT_SHOWN_WINDOW_MINIMIZED;
170     case ShowTranslateBubbleResult::BROWSER_WINDOW_NOT_ACTIVE:
171       return translate::TranslateBubbleUiEvent::
172           BUBBLE_NOT_SHOWN_WINDOW_NOT_ACTIVE;
173     case ShowTranslateBubbleResult::WEB_CONTENTS_NOT_ACTIVE:
174       return translate::TranslateBubbleUiEvent::
175           BUBBLE_NOT_SHOWN_WEB_CONTENTS_NOT_ACTIVE;
176     case ShowTranslateBubbleResult::EDITABLE_FIELD_IS_ACTIVE:
177       return translate::TranslateBubbleUiEvent::
178           BUBBLE_NOT_SHOWN_EDITABLE_FIELD_IS_ACTIVE;
179   }
180 }
181 
182 // Creates a new tabbed browser window, with the same size, type and profile as
183 // |original_browser|'s window, inserts |contents| into it, and shows it.
CreateAndShowNewWindowWithContents(std::unique_ptr<content::WebContents> contents,const Browser * original_browser)184 void CreateAndShowNewWindowWithContents(
185     std::unique_ptr<content::WebContents> contents,
186     const Browser* original_browser) {
187   Browser* new_browser = nullptr;
188   if (original_browser->deprecated_is_app()) {
189     new_browser = Browser::Create(Browser::CreateParams::CreateForApp(
190         original_browser->app_name(), original_browser->is_trusted_source(),
191         gfx::Rect(), original_browser->profile(), true));
192   } else {
193     new_browser = Browser::Create(Browser::CreateParams(
194         original_browser->type(), original_browser->profile(), true));
195   }
196   // Preserve the size of the original window. The new window has already
197   // been given an offset by the OS, so we shouldn't copy the old bounds.
198   BrowserWindow* new_window = new_browser->window();
199   new_window->SetBounds(
200       gfx::Rect(new_window->GetRestoredBounds().origin(),
201                 original_browser->window()->GetRestoredBounds().size()));
202 
203   // We need to show the browser now.  Otherwise ContainerWin assumes the
204   // WebContents is invisible and won't size it.
205   new_browser->window()->Show();
206 
207   // The page transition below is only for the purpose of inserting the tab.
208   new_browser->tab_strip_model()->AddWebContents(std::move(contents), -1,
209                                                  ui::PAGE_TRANSITION_LINK,
210                                                  TabStripModel::ADD_ACTIVE);
211 }
212 
GetActiveTabURLAndTitleToSave(Browser * browser,GURL * url,base::string16 * title)213 bool GetActiveTabURLAndTitleToSave(Browser* browser,
214                                    GURL* url,
215                                    base::string16* title) {
216   content::WebContents* web_contents =
217       browser->tab_strip_model()->GetActiveWebContents();
218   // |web_contents| can be nullptr if the last tab in the browser was closed
219   // but the browser wasn't closed yet. https://crbug.com/799668
220   if (!web_contents)
221     return false;
222   chrome::GetURLAndTitleToBookmark(web_contents, url, title);
223   return true;
224 }
225 
GetReadingListModel(Browser * browser)226 ReadingListModel* GetReadingListModel(Browser* browser) {
227   ReadingListModel* model =
228       ReadingListModelFactory::GetForBrowserContext(browser->profile());
229   if (!model || !model->loaded())
230     return nullptr;  // Ignore requests until model has loaded.
231   return model;
232 }
233 
234 }  // namespace
235 
236 using base::UserMetricsAction;
237 using bookmarks::BookmarkModel;
238 using content::NavigationController;
239 using content::NavigationEntry;
240 using content::OpenURLParams;
241 using content::Referrer;
242 using content::WebContents;
243 
244 namespace chrome {
245 namespace {
246 
247 #if BUILDFLAG(ENABLE_EXTENSIONS)
GetExtensionForBrowser(Browser * browser)248 const extensions::Extension* GetExtensionForBrowser(Browser* browser) {
249   return extensions::ExtensionRegistry::Get(browser->profile())
250       ->GetExtensionById(
251           web_app::GetAppIdFromApplicationName(browser->app_name()),
252           extensions::ExtensionRegistry::EVERYTHING);
253 }
254 #endif
255 
256 // Based on |disposition|, creates a new tab as necessary, and returns the
257 // appropriate tab to navigate.  If that tab is the |current_tab|, reverts the
258 // location bar contents, since all browser-UI-triggered navigations should
259 // revert any omnibox edits in the |current_tab|.
GetTabAndRevertIfNecessaryHelper(Browser * browser,WindowOpenDisposition disposition,WebContents * current_tab)260 WebContents* GetTabAndRevertIfNecessaryHelper(Browser* browser,
261                                               WindowOpenDisposition disposition,
262                                               WebContents* current_tab) {
263   switch (disposition) {
264     case WindowOpenDisposition::NEW_FOREGROUND_TAB:
265     case WindowOpenDisposition::NEW_BACKGROUND_TAB: {
266       std::unique_ptr<WebContents> new_tab = current_tab->Clone();
267       WebContents* raw_new_tab = new_tab.get();
268       if (disposition == WindowOpenDisposition::NEW_BACKGROUND_TAB)
269         new_tab->WasHidden();
270       const int index =
271           browser->tab_strip_model()->GetIndexOfWebContents(current_tab);
272       const auto group = browser->tab_strip_model()->GetTabGroupForTab(index);
273       browser->tab_strip_model()->AddWebContents(
274           std::move(new_tab), -1, ui::PAGE_TRANSITION_LINK,
275           (disposition == WindowOpenDisposition::NEW_FOREGROUND_TAB)
276               ? TabStripModel::ADD_ACTIVE
277               : TabStripModel::ADD_NONE,
278           group);
279       return raw_new_tab;
280     }
281     case WindowOpenDisposition::NEW_WINDOW: {
282       std::unique_ptr<WebContents> new_tab = current_tab->Clone();
283       WebContents* raw_new_tab = new_tab.get();
284       Browser* new_browser =
285           Browser::Create(Browser::CreateParams(browser->profile(), true));
286       new_browser->tab_strip_model()->AddWebContents(std::move(new_tab), -1,
287                                                      ui::PAGE_TRANSITION_LINK,
288                                                      TabStripModel::ADD_ACTIVE);
289       new_browser->window()->Show();
290       return raw_new_tab;
291     }
292     default:
293       browser->window()->GetLocationBar()->Revert();
294       return current_tab;
295   }
296 }
297 
298 // Like the above, but auto-computes the current tab
GetTabAndRevertIfNecessary(Browser * browser,WindowOpenDisposition disposition)299 WebContents* GetTabAndRevertIfNecessary(Browser* browser,
300                                         WindowOpenDisposition disposition) {
301   WebContents* activate_tab =
302       browser->tab_strip_model()->GetActiveWebContents();
303   return GetTabAndRevertIfNecessaryHelper(browser, disposition, activate_tab);
304 }
305 
ReloadInternal(Browser * browser,WindowOpenDisposition disposition,bool bypass_cache)306 void ReloadInternal(Browser* browser,
307                     WindowOpenDisposition disposition,
308                     bool bypass_cache) {
309   const WebContents* active_contents =
310       browser->tab_strip_model()->GetActiveWebContents();
311   const auto& selected_indices =
312       browser->tab_strip_model()->selection_model().selected_indices();
313   for (int index : selected_indices) {
314     WebContents* selected_tab =
315         browser->tab_strip_model()->GetWebContentsAt(index);
316     WebContents* new_tab =
317         GetTabAndRevertIfNecessaryHelper(browser, disposition, selected_tab);
318 
319     // If the selected_tab is the activated page, give the focus to it, as this
320     // is caused by a user action
321     if (selected_tab == active_contents &&
322         !new_tab->FocusLocationBarByDefault()) {
323       new_tab->Focus();
324     }
325 
326     DevToolsWindow* devtools =
327         DevToolsWindow::GetInstanceForInspectedWebContents(new_tab);
328     constexpr content::ReloadType kBypassingType =
329         content::ReloadType::BYPASSING_CACHE;
330     constexpr content::ReloadType kNormalType = content::ReloadType::NORMAL;
331     if (!devtools || !devtools->ReloadInspectedWebContents(bypass_cache)) {
332       new_tab->GetController().Reload(
333           bypass_cache ? kBypassingType : kNormalType, true);
334     }
335   }
336 }
337 
IsShowingWebContentsModalDialog(Browser * browser)338 bool IsShowingWebContentsModalDialog(Browser* browser) {
339   WebContents* web_contents =
340       browser->tab_strip_model()->GetActiveWebContents();
341   if (!web_contents)
342     return false;
343 
344   // TODO(gbillock): This is currently called in production by the CanPrint
345   // method, and may be too restrictive if we allow print preview to overlap.
346   // Re-assess how to queue print preview after we know more about popup
347   // management policy.
348   const web_modal::WebContentsModalDialogManager* manager =
349       web_modal::WebContentsModalDialogManager::FromWebContents(web_contents);
350   return manager && manager->IsDialogActive();
351 }
352 
353 #if BUILDFLAG(ENABLE_BASIC_PRINT_DIALOG)
PrintPreviewShowing(const Browser * browser)354 bool PrintPreviewShowing(const Browser* browser) {
355 #if BUILDFLAG(ENABLE_PRINT_PREVIEW)
356   WebContents* contents = browser->tab_strip_model()->GetActiveWebContents();
357   printing::PrintPreviewDialogController* controller =
358       printing::PrintPreviewDialogController::GetInstance();
359   return controller && (controller->GetPrintPreviewForContents(contents) ||
360                         controller->is_creating_print_preview_dialog());
361 #else
362   return false;
363 #endif
364 }
365 #endif  // BUILDFLAG(ENABLE_BASIC_PRINT_DIALOG)
366 
367 }  // namespace
368 
IsCommandEnabled(Browser * browser,int command)369 bool IsCommandEnabled(Browser* browser, int command) {
370   return browser->command_controller()->IsCommandEnabled(command);
371 }
372 
SupportsCommand(Browser * browser,int command)373 bool SupportsCommand(Browser* browser, int command) {
374   return browser->command_controller()->SupportsCommand(command);
375 }
376 
ExecuteCommand(Browser * browser,int command,base::TimeTicks time_stamp)377 bool ExecuteCommand(Browser* browser, int command, base::TimeTicks time_stamp) {
378   return browser->command_controller()->ExecuteCommand(command, time_stamp);
379 }
380 
ExecuteCommandWithDisposition(Browser * browser,int command,WindowOpenDisposition disposition)381 bool ExecuteCommandWithDisposition(Browser* browser,
382                                    int command,
383                                    WindowOpenDisposition disposition) {
384   return browser->command_controller()->ExecuteCommandWithDisposition(
385       command, disposition);
386 }
387 
UpdateCommandEnabled(Browser * browser,int command,bool enabled)388 void UpdateCommandEnabled(Browser* browser, int command, bool enabled) {
389   browser->command_controller()->UpdateCommandEnabled(command, enabled);
390 }
391 
AddCommandObserver(Browser * browser,int command,CommandObserver * observer)392 void AddCommandObserver(Browser* browser,
393                         int command,
394                         CommandObserver* observer) {
395   browser->command_controller()->AddCommandObserver(command, observer);
396 }
397 
RemoveCommandObserver(Browser * browser,int command,CommandObserver * observer)398 void RemoveCommandObserver(Browser* browser,
399                            int command,
400                            CommandObserver* observer) {
401   browser->command_controller()->RemoveCommandObserver(command, observer);
402 }
403 
GetContentRestrictions(const Browser * browser)404 int GetContentRestrictions(const Browser* browser) {
405   int content_restrictions = 0;
406   WebContents* current_tab = browser->tab_strip_model()->GetActiveWebContents();
407   if (current_tab) {
408     CoreTabHelper* core_tab_helper =
409         CoreTabHelper::FromWebContents(current_tab);
410     content_restrictions = core_tab_helper->content_restrictions();
411     NavigationEntry* last_committed_entry =
412         current_tab->GetController().GetLastCommittedEntry();
413     if (!content::IsSavableURL(
414             last_committed_entry ? last_committed_entry->GetURL() : GURL()))
415       content_restrictions |= CONTENT_RESTRICTION_SAVE;
416   }
417   return content_restrictions;
418 }
419 
NewEmptyWindow(Profile * profile)420 void NewEmptyWindow(Profile* profile) {
421   bool incognito = profile->IsOffTheRecord();
422   PrefService* prefs = profile->GetPrefs();
423   if (incognito) {
424     if (IncognitoModePrefs::GetAvailability(prefs) ==
425         IncognitoModePrefs::DISABLED) {
426       incognito = false;
427     }
428   } else if (profile->IsGuestSession() ||
429              (browser_defaults::kAlwaysOpenIncognitoWindow &&
430               IncognitoModePrefs::ShouldLaunchIncognito(
431                   *base::CommandLine::ForCurrentProcess(), prefs))) {
432     incognito = true;
433   }
434 
435   if (incognito) {
436     base::RecordAction(UserMetricsAction("NewIncognitoWindow"));
437     OpenEmptyWindow(profile->GetPrimaryOTRProfile());
438   } else {
439     base::RecordAction(UserMetricsAction("NewWindow"));
440     SessionService* session_service =
441         SessionServiceFactory::GetForProfileForSessionRestore(
442             profile->GetOriginalProfile());
443     if (!session_service ||
444         !session_service->RestoreIfNecessary(std::vector<GURL>())) {
445       OpenEmptyWindow(profile->GetOriginalProfile());
446     }
447   }
448 }
449 
OpenEmptyWindow(Profile * profile)450 Browser* OpenEmptyWindow(Profile* profile) {
451   Browser* browser = Browser::Create(
452       Browser::CreateParams(Browser::TYPE_NORMAL, profile, true));
453   AddTabAt(browser, GURL(), -1, true);
454   browser->window()->Show();
455   return browser;
456 }
457 
OpenWindowWithRestoredTabs(Profile * profile)458 void OpenWindowWithRestoredTabs(Profile* profile) {
459   sessions::TabRestoreService* service =
460       TabRestoreServiceFactory::GetForProfile(profile);
461   if (service)
462     service->RestoreMostRecentEntry(nullptr);
463 }
464 
OpenURLOffTheRecord(Profile * profile,const GURL & url)465 void OpenURLOffTheRecord(Profile* profile, const GURL& url) {
466   ScopedTabbedBrowserDisplayer displayer(profile->GetPrimaryOTRProfile());
467   AddSelectedTabWithURL(displayer.browser(), url, ui::PAGE_TRANSITION_LINK);
468 }
469 
CanGoBack(const Browser * browser)470 bool CanGoBack(const Browser* browser) {
471   return browser->tab_strip_model()
472       ->GetActiveWebContents()
473       ->GetController()
474       .CanGoBack();
475 }
476 
GoBack(Browser * browser,WindowOpenDisposition disposition)477 void GoBack(Browser* browser, WindowOpenDisposition disposition) {
478   base::RecordAction(UserMetricsAction("Back"));
479 
480   if (CanGoBack(browser)) {
481     WebContents* new_tab = GetTabAndRevertIfNecessary(browser, disposition);
482     new_tab->GetController().GoBack();
483   }
484 }
485 
CanGoForward(const Browser * browser)486 bool CanGoForward(const Browser* browser) {
487   return browser->tab_strip_model()
488       ->GetActiveWebContents()
489       ->GetController()
490       .CanGoForward();
491 }
492 
GoForward(Browser * browser,WindowOpenDisposition disposition)493 void GoForward(Browser* browser, WindowOpenDisposition disposition) {
494   base::RecordAction(UserMetricsAction("Forward"));
495   if (CanGoForward(browser)) {
496     GetTabAndRevertIfNecessary(browser, disposition)
497         ->GetController()
498         .GoForward();
499   }
500 }
501 
NavigateToIndexWithDisposition(Browser * browser,int index,WindowOpenDisposition disposition)502 void NavigateToIndexWithDisposition(Browser* browser,
503                                     int index,
504                                     WindowOpenDisposition disposition) {
505   NavigationController* controller =
506       &GetTabAndRevertIfNecessary(browser, disposition)->GetController();
507   DCHECK_GE(index, 0);
508   DCHECK_LT(index, controller->GetEntryCount());
509   controller->GoToIndex(index);
510 }
511 
Reload(Browser * browser,WindowOpenDisposition disposition)512 void Reload(Browser* browser, WindowOpenDisposition disposition) {
513   base::RecordAction(UserMetricsAction("Reload"));
514   ReloadInternal(browser, disposition, false);
515 }
516 
ReloadBypassingCache(Browser * browser,WindowOpenDisposition disposition)517 void ReloadBypassingCache(Browser* browser, WindowOpenDisposition disposition) {
518   base::RecordAction(UserMetricsAction("ReloadBypassingCache"));
519   ReloadInternal(browser, disposition, true);
520 }
521 
CanReload(const Browser * browser)522 bool CanReload(const Browser* browser) {
523   return !browser->is_type_devtools();
524 }
525 
Home(Browser * browser,WindowOpenDisposition disposition)526 void Home(Browser* browser, WindowOpenDisposition disposition) {
527   base::RecordAction(UserMetricsAction("Home"));
528 
529   std::string extra_headers;
530 #if BUILDFLAG(ENABLE_RLZ)
531   // If the home page is a Google home page, add the RLZ header to the request.
532   PrefService* pref_service = browser->profile()->GetPrefs();
533   if (pref_service) {
534     if (google_util::IsGoogleHomePageUrl(
535             GURL(pref_service->GetString(prefs::kHomePage)))) {
536       extra_headers = rlz::RLZTracker::GetAccessPointHttpHeader(
537           rlz::RLZTracker::ChromeHomePage());
538     }
539   }
540 #endif  // BUILDFLAG(ENABLE_RLZ)
541 
542   GURL url = browser->profile()->GetHomePage();
543 
544 #if BUILDFLAG(ENABLE_EXTENSIONS)
545   // With bookmark apps enabled, hosted apps should return to their launch page
546   // when the home button is pressed.
547   if (browser->deprecated_is_app()) {
548     const extensions::Extension* extension = GetExtensionForBrowser(browser);
549     if (!extension)
550       return;
551     url = extensions::AppLaunchInfo::GetLaunchWebURL(extension);
552   }
553 
554   if (disposition == WindowOpenDisposition::CURRENT_TAB ||
555       disposition == WindowOpenDisposition::NEW_FOREGROUND_TAB)
556     extensions::MaybeShowExtensionControlledHomeNotification(browser);
557 #endif
558 
559   bool is_chrome_internal = url.SchemeIs(url::kAboutScheme) ||
560                             url.SchemeIs(content::kChromeUIScheme) ||
561                             url.SchemeIs(chrome::kChromeNativeScheme);
562   base::UmaHistogramBoolean("Navigation.Home.IsChromeInternal",
563                             is_chrome_internal);
564   OpenURLParams params(
565       url, Referrer(), disposition,
566       ui::PageTransitionFromInt(ui::PAGE_TRANSITION_AUTO_BOOKMARK |
567                                 ui::PAGE_TRANSITION_HOME_PAGE),
568       false);
569   params.extra_headers = extra_headers;
570   browser->OpenURL(params);
571 }
572 
OpenCurrentURL(Browser * browser)573 void OpenCurrentURL(Browser* browser) {
574   base::RecordAction(UserMetricsAction("LoadURL"));
575   LocationBar* location_bar = browser->window()->GetLocationBar();
576   if (!location_bar)
577     return;
578 
579   GURL url(location_bar->GetDestinationURL());
580 
581   NavigateParams params(browser, url, location_bar->GetPageTransition());
582   params.disposition = location_bar->GetWindowOpenDisposition();
583   // Use ADD_INHERIT_OPENER so that all pages opened by the omnibox at least
584   // inherit the opener. In some cases the tabstrip will determine the group
585   // should be inherited, in which case the group is inherited instead of the
586   // opener.
587   params.tabstrip_add_types =
588       TabStripModel::ADD_FORCE_INDEX | TabStripModel::ADD_INHERIT_OPENER;
589   params.input_start = location_bar->GetMatchSelectionTimestamp();
590   Navigate(&params);
591 
592 #if BUILDFLAG(ENABLE_EXTENSIONS)
593   DCHECK(extensions::ExtensionSystem::Get(browser->profile())
594              ->extension_service());
595   const extensions::Extension* extension =
596       extensions::ExtensionRegistry::Get(browser->profile())
597           ->enabled_extensions()
598           .GetAppByURL(url);
599   if (extension) {
600     extensions::RecordAppLaunchType(extension_misc::APP_LAUNCH_OMNIBOX_LOCATION,
601                                     extension->GetType());
602   }
603 #endif
604 }
605 
Stop(Browser * browser)606 void Stop(Browser* browser) {
607   base::RecordAction(UserMetricsAction("Stop"));
608   browser->tab_strip_model()->GetActiveWebContents()->Stop();
609 }
610 
NewWindow(Browser * browser)611 void NewWindow(Browser* browser) {
612   Profile* const profile = browser->profile();
613 #if BUILDFLAG(ENABLE_EXTENSIONS) && defined(OS_MAC)
614   // Web apps should open a window to their launch page.
615   if (browser->app_controller() && browser->app_controller()->HasAppId()) {
616     const web_app::AppId app_id = browser->app_controller()->GetAppId();
617 
618     auto launch_container =
619         apps::mojom::LaunchContainer::kLaunchContainerWindow;
620     if (web_app::WebAppProviderBase::GetProviderBase(profile)
621             ->registrar()
622             .GetAppEffectiveDisplayMode(app_id) ==
623         blink::mojom::DisplayMode::kBrowser) {
624       launch_container = apps::mojom::LaunchContainer::kLaunchContainerTab;
625     }
626     apps::AppLaunchParams params = apps::AppLaunchParams(
627         app_id, launch_container, WindowOpenDisposition::NEW_WINDOW,
628         apps::mojom::AppLaunchSource::kSourceKeyboard);
629     apps::AppServiceProxyFactory::GetForProfile(profile)
630         ->BrowserAppLauncher()
631         ->LaunchAppWithParams(std::move(params));
632     return;
633   }
634 
635   // Hosted apps should open a window to their launch page.
636   const extensions::Extension* extension = GetExtensionForBrowser(browser);
637   if (extension && extension->is_hosted_app()) {
638     DCHECK(!extension->from_bookmark());
639     const auto app_launch_params = CreateAppLaunchParamsUserContainer(
640         profile, extension, WindowOpenDisposition::NEW_WINDOW,
641         extensions::AppLaunchSource::kSourceKeyboard);
642     OpenApplicationWindow(
643         profile, app_launch_params,
644         extensions::AppLaunchInfo::GetLaunchWebURL(extension));
645     return;
646   }
647 #endif
648   NewEmptyWindow(profile->GetOriginalProfile());
649 }
650 
NewIncognitoWindow(Profile * profile)651 void NewIncognitoWindow(Profile* profile) {
652   NewEmptyWindow(profile->GetPrimaryOTRProfile());
653 }
654 
CloseWindow(Browser * browser)655 void CloseWindow(Browser* browser) {
656   base::RecordAction(UserMetricsAction("CloseWindow"));
657   browser->window()->Close();
658 }
659 
NewTab(Browser * browser)660 void NewTab(Browser* browser) {
661   base::RecordAction(UserMetricsAction("NewTab"));
662   // TODO(asvitkine): This is invoked programmatically from several places.
663   // Audit the code and change it so that the histogram only gets collected for
664   // user-initiated commands.
665   UMA_HISTOGRAM_ENUMERATION("Tab.NewTab", TabStripModel::NEW_TAB_COMMAND,
666                             TabStripModel::NEW_TAB_ENUM_COUNT);
667 
668   // Notify IPH that new tab was opened.
669   auto* reopen_tab_iph =
670       ReopenTabInProductHelpFactory::GetForProfile(browser->profile());
671   reopen_tab_iph->NewTabOpened();
672 
673   if (browser->SupportsWindowFeature(Browser::FEATURE_TABSTRIP)) {
674     AddTabAt(browser, GURL(), -1, true);
675   } else {
676     ScopedTabbedBrowserDisplayer displayer(browser->profile());
677     Browser* b = displayer.browser();
678     AddTabAt(b, GURL(), -1, true);
679     b->window()->Show();
680     // The call to AddBlankTabAt above did not set the focus to the tab as its
681     // window was not active, so we have to do it explicitly.
682     // See http://crbug.com/6380.
683     b->tab_strip_model()->GetActiveWebContents()->RestoreFocus();
684   }
685 }
686 
CloseTab(Browser * browser)687 void CloseTab(Browser* browser) {
688   base::RecordAction(UserMetricsAction("CloseTab_Accelerator"));
689   browser->tab_strip_model()->CloseSelectedTabs();
690 }
691 
CanZoomIn(content::WebContents * contents)692 bool CanZoomIn(content::WebContents* contents) {
693   return contents && !contents->IsCrashed() &&
694          zoom::ZoomController::FromWebContents(contents)->GetZoomPercent() !=
695              contents->GetMaximumZoomPercent();
696 }
697 
CanZoomOut(content::WebContents * contents)698 bool CanZoomOut(content::WebContents* contents) {
699   return contents && !contents->IsCrashed() &&
700          zoom::ZoomController::FromWebContents(contents)->GetZoomPercent() !=
701              contents->GetMinimumZoomPercent();
702 }
703 
CanResetZoom(content::WebContents * contents)704 bool CanResetZoom(content::WebContents* contents) {
705   zoom::ZoomController* zoom_controller =
706       zoom::ZoomController::FromWebContents(contents);
707   return !zoom_controller->IsAtDefaultZoom() ||
708          !zoom_controller->PageScaleFactorIsOne();
709 }
710 
SelectNextTab(Browser * browser,TabStripModel::UserGestureDetails gesture_detail)711 void SelectNextTab(Browser* browser,
712                    TabStripModel::UserGestureDetails gesture_detail) {
713   base::RecordAction(UserMetricsAction("SelectNextTab"));
714   browser->tab_strip_model()->SelectNextTab(gesture_detail);
715 }
716 
SelectPreviousTab(Browser * browser,TabStripModel::UserGestureDetails gesture_detail)717 void SelectPreviousTab(Browser* browser,
718                        TabStripModel::UserGestureDetails gesture_detail) {
719   base::RecordAction(UserMetricsAction("SelectPrevTab"));
720   browser->tab_strip_model()->SelectPreviousTab(gesture_detail);
721 }
722 
MoveTabNext(Browser * browser)723 void MoveTabNext(Browser* browser) {
724   base::RecordAction(UserMetricsAction("MoveTabNext"));
725   browser->tab_strip_model()->MoveTabNext();
726 }
727 
MoveTabPrevious(Browser * browser)728 void MoveTabPrevious(Browser* browser) {
729   base::RecordAction(UserMetricsAction("MoveTabPrevious"));
730   browser->tab_strip_model()->MoveTabPrevious();
731 }
732 
SelectNumberedTab(Browser * browser,int index,TabStripModel::UserGestureDetails gesture_detail)733 void SelectNumberedTab(Browser* browser,
734                        int index,
735                        TabStripModel::UserGestureDetails gesture_detail) {
736   if (index < browser->tab_strip_model()->count()) {
737     base::RecordAction(UserMetricsAction("SelectNumberedTab"));
738     browser->tab_strip_model()->ActivateTabAt(index, gesture_detail);
739   }
740 }
741 
SelectLastTab(Browser * browser,TabStripModel::UserGestureDetails gesture_detail)742 void SelectLastTab(Browser* browser,
743                    TabStripModel::UserGestureDetails gesture_detail) {
744   base::RecordAction(UserMetricsAction("SelectLastTab"));
745   browser->tab_strip_model()->SelectLastTab(gesture_detail);
746 }
747 
DuplicateTab(Browser * browser)748 void DuplicateTab(Browser* browser) {
749   base::RecordAction(UserMetricsAction("Duplicate"));
750   DuplicateTabAt(browser, browser->tab_strip_model()->active_index());
751 }
752 
CanDuplicateTab(const Browser * browser)753 bool CanDuplicateTab(const Browser* browser) {
754   return CanDuplicateTabAt(browser, browser->tab_strip_model()->active_index());
755 }
756 
CanDuplicateKeyboardFocusedTab(const Browser * browser)757 bool CanDuplicateKeyboardFocusedTab(const Browser* browser) {
758   if (!HasKeyboardFocusedTab(browser))
759     return false;
760   return CanDuplicateTabAt(browser, *GetKeyboardFocusedTabIndex(browser));
761 }
762 
CanMoveActiveTabToNewWindow(Browser * browser)763 bool CanMoveActiveTabToNewWindow(Browser* browser) {
764   return CanMoveTabsToNewWindow(browser,
765                                 {browser->tab_strip_model()->active_index()});
766 }
767 
MoveActiveTabToNewWindow(Browser * browser)768 void MoveActiveTabToNewWindow(Browser* browser) {
769   MoveTabsToNewWindow(browser, {browser->tab_strip_model()->active_index()});
770 }
CanMoveTabsToNewWindow(Browser * browser,const std::vector<int> & tab_indices)771 bool CanMoveTabsToNewWindow(Browser* browser,
772                             const std::vector<int>& tab_indices) {
773   return browser->tab_strip_model()->count() >
774          static_cast<int>(tab_indices.size());
775 }
776 
MoveTabsToNewWindow(Browser * browser,const std::vector<int> & tab_indices,base::Optional<tab_groups::TabGroupId> group)777 void MoveTabsToNewWindow(Browser* browser,
778                          const std::vector<int>& tab_indices,
779                          base::Optional<tab_groups::TabGroupId> group) {
780   if (tab_indices.empty())
781     return;
782 
783   Browser* new_browser =
784       Browser::Create(Browser::CreateParams(browser->profile(), true));
785 
786   if (group.has_value()) {
787     const tab_groups::TabGroupVisualData* old_visual_data =
788         browser->tab_strip_model()
789             ->group_model()
790             ->GetTabGroup(group.value())
791             ->visual_data();
792     tab_groups::TabGroupVisualData new_visual_data(old_visual_data->title(),
793                                                    old_visual_data->color(),
794                                                    false /* is_collapsed */);
795 
796     new_browser->tab_strip_model()->group_model()->AddTabGroup(group.value(),
797                                                                new_visual_data);
798   }
799 
800   int indices_size = tab_indices.size();
801   int active_index = browser->tab_strip_model()->active_index();
802   for (int i = 0; i < indices_size; i++) {
803     // Adjust tab index to account for tabs already moved.
804     int adjusted_index = tab_indices[i] - i;
805     bool pinned = browser->tab_strip_model()->IsTabPinned(adjusted_index);
806     std::unique_ptr<WebContents> contents_move =
807         browser->tab_strip_model()->DetachWebContentsAt(adjusted_index);
808 
809     int add_types = pinned ? TabStripModel::ADD_PINNED : 0;
810     // The last tab made active takes precedence, so activate the last active
811     // tab, with a fallback for the first tab (i == 0) if the active tab isn’t
812     // in the set of tabs being moved.
813     if (i == 0 || tab_indices[i] == active_index)
814       add_types = add_types | TabStripModel::ADD_ACTIVE;
815 
816     new_browser->tab_strip_model()->AddWebContents(std::move(contents_move), -1,
817                                                    ui::PAGE_TRANSITION_TYPED,
818                                                    add_types, group);
819   }
820   new_browser->window()->Show();
821 }
822 
CanCloseTabsToRight(const Browser * browser)823 bool CanCloseTabsToRight(const Browser* browser) {
824   return browser->tab_strip_model()->IsContextMenuCommandEnabled(
825       browser->tab_strip_model()->active_index(),
826       TabStripModel::CommandCloseTabsToRight);
827 }
828 
CanCloseOtherTabs(const Browser * browser)829 bool CanCloseOtherTabs(const Browser* browser) {
830   return browser->tab_strip_model()->IsContextMenuCommandEnabled(
831       browser->tab_strip_model()->active_index(),
832       TabStripModel::CommandCloseOtherTabs);
833 }
834 
DuplicateTabAt(Browser * browser,int index)835 WebContents* DuplicateTabAt(Browser* browser, int index) {
836   WebContents* contents = browser->tab_strip_model()->GetWebContentsAt(index);
837   CHECK(contents);
838   std::unique_ptr<WebContents> contents_dupe = contents->Clone();
839   WebContents* raw_contents_dupe = contents_dupe.get();
840 
841   bool pinned = false;
842   if (browser->CanSupportWindowFeature(Browser::FEATURE_TABSTRIP)) {
843     // If this is a tabbed browser, just create a duplicate tab inside the same
844     // window next to the tab being duplicated.
845     TabStripModel* tab_strip_model = browser->tab_strip_model();
846     const int index = tab_strip_model->GetIndexOfWebContents(contents);
847     pinned = tab_strip_model->IsTabPinned(index);
848     int add_types = TabStripModel::ADD_ACTIVE |
849                     TabStripModel::ADD_INHERIT_OPENER |
850                     (pinned ? TabStripModel::ADD_PINNED : 0);
851     const auto old_group = tab_strip_model->GetTabGroupForTab(index);
852     tab_strip_model->InsertWebContentsAt(index + 1, std::move(contents_dupe),
853                                          add_types, old_group);
854   } else {
855     CreateAndShowNewWindowWithContents(std::move(contents_dupe), browser);
856   }
857 
858   SessionService* session_service =
859       SessionServiceFactory::GetForProfileIfExisting(browser->profile());
860   if (session_service)
861     session_service->TabRestored(raw_contents_dupe, pinned);
862   return raw_contents_dupe;
863 }
864 
CanDuplicateTabAt(const Browser * browser,int index)865 bool CanDuplicateTabAt(const Browser* browser, int index) {
866   WebContents* contents = browser->tab_strip_model()->GetWebContentsAt(index);
867   return contents && contents->GetController().GetLastCommittedEntry();
868 }
869 
MoveTabsToExistingWindow(Browser * source,Browser * target,const std::vector<int> & tab_indices)870 void MoveTabsToExistingWindow(Browser* source,
871                               Browser* target,
872                               const std::vector<int>& tab_indices) {
873   if (tab_indices.empty())
874     return;
875 
876   int indices_size = tab_indices.size();
877   for (int i = 0; i < indices_size; i++) {
878     // Adjust tab index to account for tabs already moved.
879     int adjusted_index = tab_indices[i] - i;
880     bool pinned = source->tab_strip_model()->IsTabPinned(adjusted_index);
881     std::unique_ptr<WebContents> contents_move =
882         source->tab_strip_model()->DetachWebContentsAt(adjusted_index);
883     int add_types = TabStripModel::ADD_ACTIVE |
884                     (pinned ? TabStripModel::ADD_PINNED : 0);
885     target->tab_strip_model()->AddWebContents(
886         std::move(contents_move), -1, ui::PAGE_TRANSITION_TYPED, add_types);
887   }
888   target->window()->Show();
889 }
890 
PinTab(Browser * browser)891 void PinTab(Browser* browser) {
892   browser->tab_strip_model()->ExecuteContextMenuCommand(
893       browser->tab_strip_model()->active_index(),
894       TabStripModel::ContextMenuCommand::CommandTogglePinned);
895 }
896 
GroupTab(Browser * browser)897 void GroupTab(Browser* browser) {
898   browser->tab_strip_model()->ExecuteContextMenuCommand(
899       browser->tab_strip_model()->active_index(),
900       TabStripModel::ContextMenuCommand::CommandToggleGrouped);
901 }
902 
MuteSite(Browser * browser)903 void MuteSite(Browser* browser) {
904   browser->tab_strip_model()->ExecuteContextMenuCommand(
905       browser->tab_strip_model()->active_index(),
906       TabStripModel::ContextMenuCommand::CommandToggleSiteMuted);
907 }
908 
MuteSiteForKeyboardFocusedTab(Browser * browser)909 void MuteSiteForKeyboardFocusedTab(Browser* browser) {
910   if (!HasKeyboardFocusedTab(browser))
911     return;
912   browser->tab_strip_model()->ExecuteContextMenuCommand(
913       *GetKeyboardFocusedTabIndex(browser),
914       TabStripModel::ContextMenuCommand::CommandToggleSiteMuted);
915 }
916 
PinKeyboardFocusedTab(Browser * browser)917 void PinKeyboardFocusedTab(Browser* browser) {
918   if (!HasKeyboardFocusedTab(browser))
919     return;
920   browser->tab_strip_model()->ExecuteContextMenuCommand(
921       *GetKeyboardFocusedTabIndex(browser),
922       TabStripModel::ContextMenuCommand::CommandTogglePinned);
923 }
924 
GroupKeyboardFocusedTab(Browser * browser)925 void GroupKeyboardFocusedTab(Browser* browser) {
926   if (!HasKeyboardFocusedTab(browser))
927     return;
928   browser->tab_strip_model()->ExecuteContextMenuCommand(
929       *GetKeyboardFocusedTabIndex(browser),
930       TabStripModel::ContextMenuCommand::CommandToggleGrouped);
931 }
932 
DuplicateKeyboardFocusedTab(Browser * browser)933 void DuplicateKeyboardFocusedTab(Browser* browser) {
934   if (HasKeyboardFocusedTab(browser)) {
935     DuplicateTabAt(browser, *GetKeyboardFocusedTabIndex(browser));
936   }
937 }
938 
HasKeyboardFocusedTab(const Browser * browser)939 bool HasKeyboardFocusedTab(const Browser* browser) {
940   return GetKeyboardFocusedTabIndex(browser).has_value();
941 }
942 
ConvertPopupToTabbedBrowser(Browser * browser)943 void ConvertPopupToTabbedBrowser(Browser* browser) {
944   base::RecordAction(UserMetricsAction("ShowAsTab"));
945   TabStripModel* tab_strip = browser->tab_strip_model();
946   std::unique_ptr<content::WebContents> contents =
947       tab_strip->DetachWebContentsAt(tab_strip->active_index());
948   Browser* b = Browser::Create(Browser::CreateParams(browser->profile(), true));
949   b->tab_strip_model()->AppendWebContents(std::move(contents), true);
950   b->window()->Show();
951 }
952 
CloseTabsToRight(Browser * browser)953 void CloseTabsToRight(Browser* browser) {
954   browser->tab_strip_model()->ExecuteContextMenuCommand(
955       browser->tab_strip_model()->active_index(),
956       TabStripModel::CommandCloseTabsToRight);
957 }
958 
CloseOtherTabs(Browser * browser)959 void CloseOtherTabs(Browser* browser) {
960   browser->tab_strip_model()->ExecuteContextMenuCommand(
961       browser->tab_strip_model()->active_index(),
962       TabStripModel::CommandCloseOtherTabs);
963 }
964 
Exit()965 void Exit() {
966   base::RecordAction(UserMetricsAction("Exit"));
967   chrome::AttemptUserExit();
968 }
969 
BookmarkCurrentTab(Browser * browser)970 void BookmarkCurrentTab(Browser* browser) {
971   base::RecordAction(UserMetricsAction("Star"));
972 
973   BookmarkModel* model =
974       BookmarkModelFactory::GetForBrowserContext(browser->profile());
975   if (!model || !model->loaded())
976     return;  // Ignore requests until bookmarks are loaded.
977 
978   GURL url;
979   base::string16 title;
980   WebContents* web_contents =
981       browser->tab_strip_model()->GetActiveWebContents();
982   // |web_contents| can be nullptr if the last tab in the browser was closed
983   // but the browser wasn't closed yet. https://crbug.com/799668
984   if (!web_contents)
985     return;
986   GetURLAndTitleToBookmark(web_contents, &url, &title);
987   bool is_bookmarked_by_any = model->IsBookmarked(url);
988   if (!is_bookmarked_by_any &&
989       web_contents->GetBrowserContext()->IsOffTheRecord()) {
990     // If we're incognito the favicon may not have been saved. Save it now
991     // so that bookmarks have an icon for the page.
992     favicon::SaveFaviconEvenIfInIncognito(web_contents);
993   }
994   bool was_bookmarked_by_user = bookmarks::IsBookmarkedByUser(model, url);
995   bookmarks::AddIfNotBookmarked(model, url, title);
996   bool is_bookmarked_by_user = bookmarks::IsBookmarkedByUser(model, url);
997   // Make sure the model actually added a bookmark before showing the star. A
998   // bookmark isn't created if the url is invalid.
999   if (browser->window()->IsActive() && is_bookmarked_by_user) {
1000     // Only show the bubble if the window is active, otherwise we may get into
1001     // weird situations where the bubble is deleted as soon as it is shown.
1002     browser->window()->ShowBookmarkBubble(url, was_bookmarked_by_user);
1003   }
1004 
1005   if (!was_bookmarked_by_user && is_bookmarked_by_user)
1006     RecordBookmarksAdded(browser->profile());
1007 }
1008 
CanBookmarkCurrentTab(const Browser * browser)1009 bool CanBookmarkCurrentTab(const Browser* browser) {
1010   BookmarkModel* model =
1011       BookmarkModelFactory::GetForBrowserContext(browser->profile());
1012   return browser_defaults::bookmarks_enabled &&
1013          browser->profile()->GetPrefs()->GetBoolean(
1014              bookmarks::prefs::kEditBookmarksEnabled) &&
1015          model && model->loaded() && browser->is_type_normal();
1016 }
1017 
BookmarkAllTabs(Browser * browser)1018 void BookmarkAllTabs(Browser* browser) {
1019   base::RecordAction(UserMetricsAction("BookmarkAllTabs"));
1020   RecordBookmarkAllTabsWithTabsCount(browser->profile(),
1021                                      browser->tab_strip_model()->count());
1022   // We record the profile that invoked this option.
1023   RecordBookmarksAdded(browser->profile());
1024   chrome::ShowBookmarkAllTabsDialog(browser);
1025 }
1026 
CanBookmarkAllTabs(const Browser * browser)1027 bool CanBookmarkAllTabs(const Browser* browser) {
1028   return browser->tab_strip_model()->count() > 1 &&
1029          CanBookmarkCurrentTab(browser);
1030 }
1031 
CanMoveActiveTabToReadLater(Browser * browser)1032 bool CanMoveActiveTabToReadLater(Browser* browser) {
1033   GURL url =
1034       GetURLToBookmark(browser->tab_strip_model()->GetActiveWebContents());
1035   ReadingListModel* model = GetReadingListModel(browser);
1036   if (!model)
1037     return false;
1038   return model->IsUrlSupported(url);
1039 }
1040 
MoveCurrentTabToReadLater(Browser * browser)1041 bool MoveCurrentTabToReadLater(Browser* browser) {
1042   GURL url;
1043   base::string16 title;
1044   ReadingListModel* model = GetReadingListModel(browser);
1045   if (!model || !GetActiveTabURLAndTitleToSave(browser, &url, &title))
1046     return false;
1047   model->AddEntry(url, base::UTF16ToUTF8(title),
1048                   reading_list::EntrySource::ADDED_VIA_CURRENT_APP);
1049   return true;
1050 }
1051 
MarkCurrentTabAsReadInReadLater(Browser * browser)1052 bool MarkCurrentTabAsReadInReadLater(Browser* browser) {
1053   GURL url;
1054   base::string16 title;
1055   ReadingListModel* model = GetReadingListModel(browser);
1056   if (!model || !GetActiveTabURLAndTitleToSave(browser, &url, &title))
1057     return false;
1058   const ReadingListEntry* entry = model->GetEntryByURL(url);
1059   // Mark current tab as read.
1060   if (entry && !entry->IsRead())
1061     model->SetReadStatus(url, true);
1062   return entry != nullptr;
1063 }
1064 
IsCurrentTabUnreadInReadLater(Browser * browser)1065 bool IsCurrentTabUnreadInReadLater(Browser* browser) {
1066   GURL url;
1067   base::string16 title;
1068   ReadingListModel* model = GetReadingListModel(browser);
1069   if (!model || !GetActiveTabURLAndTitleToSave(browser, &url, &title))
1070     return false;
1071   const ReadingListEntry* entry = model->GetEntryByURL(url);
1072   return entry && !entry->IsRead();
1073 }
1074 
SaveCreditCard(Browser * browser)1075 void SaveCreditCard(Browser* browser) {
1076   WebContents* web_contents =
1077       browser->tab_strip_model()->GetActiveWebContents();
1078   autofill::SaveCardBubbleControllerImpl* controller =
1079       autofill::SaveCardBubbleControllerImpl::FromWebContents(web_contents);
1080   controller->ReshowBubble();
1081 }
1082 
MigrateLocalCards(Browser * browser)1083 void MigrateLocalCards(Browser* browser) {
1084   WebContents* web_contents =
1085       browser->tab_strip_model()->GetActiveWebContents();
1086   autofill::ManageMigrationUiController* controller =
1087       autofill::ManageMigrationUiController::FromWebContents(web_contents);
1088   // Show migration-related Ui when the user clicks the credit card icon.
1089   controller->OnUserClickedCreditCardIcon();
1090 }
1091 
MaybeShowSaveLocalCardSignInPromo(Browser * browser)1092 void MaybeShowSaveLocalCardSignInPromo(Browser* browser) {
1093   WebContents* web_contents =
1094       browser->tab_strip_model()->GetActiveWebContents();
1095   autofill::SaveCardBubbleControllerImpl* controller =
1096       autofill::SaveCardBubbleControllerImpl::FromWebContents(web_contents);
1097 
1098   // If controller does not exist for the tab, don't show the sign-in promo.
1099   if (controller) {
1100     // The sign in promo will only be shown when 1) The user is signed out or 2)
1101     // The user is signed in through DICe, but did not turn on syncing.
1102     controller->MaybeShowBubbleForSignInPromo();
1103   }
1104 }
1105 
CloseSaveLocalCardSignInPromo(Browser * browser)1106 void CloseSaveLocalCardSignInPromo(Browser* browser) {
1107   WebContents* web_contents =
1108       browser->tab_strip_model()->GetActiveWebContents();
1109   autofill::SaveCardBubbleControllerImpl* controller =
1110       autofill::SaveCardBubbleControllerImpl::FromWebContents(web_contents);
1111 
1112   if (controller)
1113     controller->HideBubbleForSignInPromo();
1114 }
1115 
Translate(Browser * browser)1116 void Translate(Browser* browser) {
1117   if (!browser->window()->IsActive())
1118     return;
1119 
1120   WebContents* web_contents =
1121       browser->tab_strip_model()->GetActiveWebContents();
1122   ChromeTranslateClient* chrome_translate_client =
1123       ChromeTranslateClient::FromWebContents(web_contents);
1124 
1125   std::string source_language;
1126   std::string target_language;
1127   chrome_translate_client->GetTranslateLanguages(web_contents, &source_language,
1128                                                  &target_language);
1129 
1130   translate::TranslateStep step = translate::TRANSLATE_STEP_BEFORE_TRANSLATE;
1131   if (chrome_translate_client) {
1132     if (chrome_translate_client->GetLanguageState().translation_pending())
1133       step = translate::TRANSLATE_STEP_TRANSLATING;
1134     else if (chrome_translate_client->GetLanguageState().translation_error())
1135       step = translate::TRANSLATE_STEP_TRANSLATE_ERROR;
1136     else if (chrome_translate_client->GetLanguageState().IsPageTranslated())
1137       step = translate::TRANSLATE_STEP_AFTER_TRANSLATE;
1138   }
1139   ShowTranslateBubbleResult result = browser->window()->ShowTranslateBubble(
1140       web_contents, step, source_language, target_language,
1141       translate::TranslateErrors::NONE, true);
1142   if (result != ShowTranslateBubbleResult::SUCCESS)
1143     translate::ReportUiAction(TranslateBubbleResultToUiEvent(result));
1144 }
1145 
ManagePasswordsForPage(Browser * browser)1146 void ManagePasswordsForPage(Browser* browser) {
1147   WebContents* web_contents =
1148       browser->tab_strip_model()->GetActiveWebContents();
1149   ManagePasswordsUIController* controller =
1150       ManagePasswordsUIController::FromWebContents(web_contents);
1151   TabDialogs::FromWebContents(web_contents)
1152       ->ShowManagePasswordsBubble(!controller->IsAutomaticallyOpeningBubble());
1153 }
1154 
SendTabToSelfFromPageAction(Browser * browser)1155 void SendTabToSelfFromPageAction(Browser* browser) {
1156   WebContents* web_contents =
1157       browser->tab_strip_model()->GetActiveWebContents();
1158   send_tab_to_self::SendTabToSelfBubbleController* controller =
1159       send_tab_to_self::SendTabToSelfBubbleController::
1160           CreateOrGetFromWebContents(web_contents);
1161   controller->ShowBubble();
1162 }
1163 
GenerateQRCodeFromPageAction(Browser * browser)1164 void GenerateQRCodeFromPageAction(Browser* browser) {
1165   WebContents* web_contents =
1166       browser->tab_strip_model()->GetActiveWebContents();
1167   qrcode_generator::QRCodeGeneratorBubbleController* controller =
1168       qrcode_generator::QRCodeGeneratorBubbleController::Get(web_contents);
1169   content::NavigationEntry* entry =
1170       web_contents->GetController().GetLastCommittedEntry();
1171   controller->ShowBubble(entry->GetURL());
1172 }
1173 
SavePage(Browser * browser)1174 void SavePage(Browser* browser) {
1175   base::RecordAction(UserMetricsAction("SavePage"));
1176   WebContents* current_tab = browser->tab_strip_model()->GetActiveWebContents();
1177   DCHECK(current_tab);
1178   if (current_tab->GetContentsMimeType() == "application/pdf")
1179     base::RecordAction(UserMetricsAction("PDF.SavePage"));
1180   current_tab->OnSavePage();
1181 }
1182 
CanSavePage(const Browser * browser)1183 bool CanSavePage(const Browser* browser) {
1184   // LocalState can be NULL in tests.
1185   if (g_browser_process->local_state() &&
1186       !g_browser_process->local_state()->GetBoolean(
1187           prefs::kAllowFileSelectionDialogs)) {
1188     return false;
1189   }
1190   return !browser->is_type_devtools() &&
1191          !(GetContentRestrictions(browser) & CONTENT_RESTRICTION_SAVE);
1192 }
1193 
Print(Browser * browser)1194 void Print(Browser* browser) {
1195 #if BUILDFLAG(ENABLE_PRINTING)
1196   auto* web_contents = browser->tab_strip_model()->GetActiveWebContents();
1197   printing::StartPrint(
1198       web_contents, mojo::NullAssociatedRemote() /* print_renderer */,
1199       browser->profile()->GetPrefs()->GetBoolean(prefs::kPrintPreviewDisabled),
1200       false /* has_selection? */);
1201 #endif
1202 }
1203 
CanPrint(Browser * browser)1204 bool CanPrint(Browser* browser) {
1205   // Do not print when printing is disabled via pref or policy.
1206   // Do not print when a page has crashed.
1207   // Do not print when a constrained window is showing. It's confusing.
1208   // TODO(gbillock): Need to re-assess the call to
1209   // IsShowingWebContentsModalDialog after a popup management policy is
1210   // refined -- we will probably want to just queue the print request, not
1211   // block it.
1212   WebContents* current_tab = browser->tab_strip_model()->GetActiveWebContents();
1213   return browser->profile()->GetPrefs()->GetBoolean(prefs::kPrintingEnabled) &&
1214          (current_tab && !current_tab->IsCrashed()) &&
1215          !(IsShowingWebContentsModalDialog(browser) ||
1216            GetContentRestrictions(browser) & CONTENT_RESTRICTION_PRINT);
1217 }
1218 
1219 #if BUILDFLAG(ENABLE_PRINTING)
BasicPrint(Browser * browser)1220 void BasicPrint(Browser* browser) {
1221   printing::StartBasicPrint(browser->tab_strip_model()->GetActiveWebContents());
1222 }
1223 
CanBasicPrint(Browser * browser)1224 bool CanBasicPrint(Browser* browser) {
1225 #if BUILDFLAG(ENABLE_BASIC_PRINT_DIALOG)
1226   // If printing is not disabled via pref or policy, it is always possible to
1227   // advanced print when the print preview is visible.
1228   return browser->profile()->GetPrefs()->GetBoolean(prefs::kPrintingEnabled) &&
1229          (PrintPreviewShowing(browser) || CanPrint(browser));
1230 #else
1231   return false;  // The print dialog is disabled.
1232 #endif  // BUILDFLAG(ENABLE_BASIC_PRINT_DIALOG)
1233 }
1234 #endif  // BUILDFLAG(ENABLE_PRINTING)
1235 
CanRouteMedia(Browser * browser)1236 bool CanRouteMedia(Browser* browser) {
1237   // Do not allow user to open Media Router dialog when there is already an
1238   // active modal dialog. This avoids overlapping dialogs.
1239   return media_router::MediaRouterEnabled(browser->profile()) &&
1240          !IsShowingWebContentsModalDialog(browser);
1241 }
1242 
RouteMediaInvokedFromAppMenu(Browser * browser)1243 void RouteMediaInvokedFromAppMenu(Browser* browser) {
1244   DCHECK(CanRouteMedia(browser));
1245 
1246   media_router::MediaRouterDialogController* dialog_controller =
1247       media_router::MediaRouterDialogController::GetOrCreateForWebContents(
1248           browser->tab_strip_model()->GetActiveWebContents());
1249   if (!dialog_controller)
1250     return;
1251 
1252   dialog_controller->ShowMediaRouterDialog(
1253       media_router::MediaRouterDialogOpenOrigin::APP_MENU);
1254 }
1255 
CutCopyPaste(Browser * browser,int command_id)1256 void CutCopyPaste(Browser* browser, int command_id) {
1257   if (command_id == IDC_CUT)
1258     base::RecordAction(UserMetricsAction("Cut"));
1259   else if (command_id == IDC_COPY)
1260     base::RecordAction(UserMetricsAction("Copy"));
1261   else
1262     base::RecordAction(UserMetricsAction("Paste"));
1263   browser->window()->CutCopyPaste(command_id);
1264 }
1265 
Find(Browser * browser)1266 void Find(Browser* browser) {
1267   base::RecordAction(UserMetricsAction("Find"));
1268   FindInPage(browser, false, true);
1269 }
1270 
FindNext(Browser * browser)1271 void FindNext(Browser* browser) {
1272   base::RecordAction(UserMetricsAction("FindNext"));
1273   FindInPage(browser, true, true);
1274 }
1275 
FindPrevious(Browser * browser)1276 void FindPrevious(Browser* browser) {
1277   base::RecordAction(UserMetricsAction("FindPrevious"));
1278   FindInPage(browser, true, false);
1279 }
1280 
FindInPage(Browser * browser,bool find_next,bool forward_direction)1281 void FindInPage(Browser* browser, bool find_next, bool forward_direction) {
1282   browser->GetFindBarController()->Show(find_next, forward_direction);
1283 }
1284 
ShowTabSearch(Browser * browser)1285 void ShowTabSearch(Browser* browser) {
1286   browser->window()->CreateTabSearchBubble();
1287 }
1288 
CloseTabSearch(Browser * browser)1289 void CloseTabSearch(Browser* browser) {
1290   browser->window()->CloseTabSearchBubble();
1291 }
1292 
CanCloseFind(Browser * browser)1293 bool CanCloseFind(Browser* browser) {
1294   WebContents* current_tab = browser->tab_strip_model()->GetActiveWebContents();
1295   if (!current_tab)
1296     return false;
1297 
1298   find_in_page::FindTabHelper* find_helper =
1299       find_in_page::FindTabHelper::FromWebContents(current_tab);
1300   return find_helper ? find_helper->find_ui_active() : false;
1301 }
1302 
CloseFind(Browser * browser)1303 void CloseFind(Browser* browser) {
1304   browser->GetFindBarController()->EndFindSession(
1305       find_in_page::SelectionAction::kKeep, find_in_page::ResultAction::kKeep);
1306 }
1307 
Zoom(Browser * browser,content::PageZoom zoom)1308 void Zoom(Browser* browser, content::PageZoom zoom) {
1309   zoom::PageZoom::Zoom(browser->tab_strip_model()->GetActiveWebContents(),
1310                        zoom);
1311 }
1312 
FocusToolbar(Browser * browser)1313 void FocusToolbar(Browser* browser) {
1314   base::RecordAction(UserMetricsAction("FocusToolbar"));
1315   browser->window()->FocusToolbar();
1316 }
1317 
FocusLocationBar(Browser * browser)1318 void FocusLocationBar(Browser* browser) {
1319   base::RecordAction(UserMetricsAction("FocusLocation"));
1320   browser->window()->SetFocusToLocationBar(true);
1321 }
1322 
FocusSearch(Browser * browser)1323 void FocusSearch(Browser* browser) {
1324   // TODO(beng): replace this with FocusLocationBar
1325   base::RecordAction(UserMetricsAction("FocusSearch"));
1326   browser->window()->GetLocationBar()->FocusSearch();
1327 }
1328 
FocusAppMenu(Browser * browser)1329 void FocusAppMenu(Browser* browser) {
1330   base::RecordAction(UserMetricsAction("FocusAppMenu"));
1331   browser->window()->FocusAppMenu();
1332 }
1333 
FocusBookmarksToolbar(Browser * browser)1334 void FocusBookmarksToolbar(Browser* browser) {
1335   base::RecordAction(UserMetricsAction("FocusBookmarksToolbar"));
1336   browser->window()->FocusBookmarksToolbar();
1337 }
1338 
FocusInactivePopupForAccessibility(Browser * browser)1339 void FocusInactivePopupForAccessibility(Browser* browser) {
1340   base::RecordAction(UserMetricsAction("FocusInactivePopupForAccessibility"));
1341   browser->window()->FocusInactivePopupForAccessibility();
1342 }
1343 
FocusNextPane(Browser * browser)1344 void FocusNextPane(Browser* browser) {
1345   base::RecordAction(UserMetricsAction("FocusNextPane"));
1346   browser->window()->RotatePaneFocus(true);
1347 }
1348 
FocusPreviousPane(Browser * browser)1349 void FocusPreviousPane(Browser* browser) {
1350   base::RecordAction(UserMetricsAction("FocusPreviousPane"));
1351   browser->window()->RotatePaneFocus(false);
1352 }
1353 
ToggleDevToolsWindow(Browser * browser,DevToolsToggleAction action,DevToolsOpenedByAction opened_by)1354 void ToggleDevToolsWindow(Browser* browser,
1355                           DevToolsToggleAction action,
1356                           DevToolsOpenedByAction opened_by) {
1357   if (action.type() == DevToolsToggleAction::kShowConsolePanel)
1358     base::RecordAction(UserMetricsAction("DevTools_ToggleConsole"));
1359   else
1360     base::RecordAction(UserMetricsAction("DevTools_ToggleWindow"));
1361   DevToolsWindow::ToggleDevToolsWindow(browser, action, opened_by);
1362 }
1363 
CanOpenTaskManager()1364 bool CanOpenTaskManager() {
1365 #if !defined(OS_ANDROID)
1366   return true;
1367 #else
1368   return false;
1369 #endif
1370 }
1371 
OpenTaskManager(Browser * browser)1372 void OpenTaskManager(Browser* browser) {
1373 #if !defined(OS_ANDROID)
1374   base::RecordAction(UserMetricsAction("TaskManager"));
1375   chrome::ShowTaskManager(browser);
1376 #else
1377   NOTREACHED();
1378 #endif
1379 }
1380 
OpenFeedbackDialog(Browser * browser,FeedbackSource source,const std::string & description_template)1381 void OpenFeedbackDialog(Browser* browser,
1382                         FeedbackSource source,
1383                         const std::string& description_template) {
1384   base::RecordAction(UserMetricsAction("Feedback"));
1385   chrome::ShowFeedbackPage(browser, source, description_template,
1386                            std::string() /* description_placeholder_text */,
1387                            std::string() /* category_tag */,
1388                            std::string() /* extra_diagnostics */);
1389 }
1390 
ToggleBookmarkBar(Browser * browser)1391 void ToggleBookmarkBar(Browser* browser) {
1392   base::RecordAction(UserMetricsAction("ShowBookmarksBar"));
1393   ToggleBookmarkBarWhenVisible(browser->profile());
1394 }
1395 
ToggleShowFullURLs(Browser * browser)1396 void ToggleShowFullURLs(Browser* browser) {
1397   bool pref_enabled = browser->profile()->GetPrefs()->GetBoolean(
1398       omnibox::kPreventUrlElisionsInOmnibox);
1399   browser->profile()->GetPrefs()->SetBoolean(
1400       omnibox::kPreventUrlElisionsInOmnibox, !pref_enabled);
1401 }
1402 
ShowAppMenu(Browser * browser)1403 void ShowAppMenu(Browser* browser) {
1404   // We record the user metric for this event in AppMenu::RunMenu.
1405   browser->window()->ShowAppMenu();
1406 }
1407 
ShowAvatarMenu(Browser * browser)1408 void ShowAvatarMenu(Browser* browser) {
1409   browser->window()->ShowAvatarBubbleFromAvatarButton(
1410       BrowserWindow::AVATAR_BUBBLE_MODE_DEFAULT,
1411       signin_metrics::AccessPoint::ACCESS_POINT_AVATAR_BUBBLE_SIGN_IN, true);
1412 }
1413 
OpenUpdateChromeDialog(Browser * browser)1414 void OpenUpdateChromeDialog(Browser* browser) {
1415   if (UpgradeDetector::GetInstance()->is_outdated_install()) {
1416     UpgradeDetector::GetInstance()->NotifyOutdatedInstall();
1417   } else if (UpgradeDetector::GetInstance()->is_outdated_install_no_au()) {
1418     UpgradeDetector::GetInstance()->NotifyOutdatedInstallNoAutoUpdate();
1419   } else {
1420     base::RecordAction(UserMetricsAction("UpdateChrome"));
1421     browser->window()->ShowUpdateChromeDialog();
1422   }
1423 }
1424 
ToggleDistilledView(Browser * browser)1425 void ToggleDistilledView(Browser* browser) {
1426   auto* current_web_contents =
1427       browser->tab_strip_model()->GetActiveWebContents();
1428   if (dom_distiller::url_utils::IsDistilledPage(
1429           current_web_contents->GetLastCommittedURL())) {
1430     ReturnToOriginalPage(current_web_contents);
1431   } else {
1432     DistillCurrentPageAndView(current_web_contents);
1433   }
1434 }
1435 
CanRequestTabletSite(WebContents * current_tab)1436 bool CanRequestTabletSite(WebContents* current_tab) {
1437   return current_tab &&
1438          current_tab->GetController().GetLastCommittedEntry() != nullptr;
1439 }
1440 
IsRequestingTabletSite(Browser * browser)1441 bool IsRequestingTabletSite(Browser* browser) {
1442   WebContents* current_tab = browser->tab_strip_model()->GetActiveWebContents();
1443   if (!current_tab)
1444     return false;
1445   content::NavigationEntry* entry =
1446       current_tab->GetController().GetLastCommittedEntry();
1447   if (!entry)
1448     return false;
1449   return entry->GetIsOverridingUserAgent();
1450 }
1451 
ToggleRequestTabletSite(Browser * browser)1452 void ToggleRequestTabletSite(Browser* browser) {
1453   WebContents* current_tab = browser->tab_strip_model()->GetActiveWebContents();
1454   if (!current_tab)
1455     return;
1456   NavigationController& controller = current_tab->GetController();
1457   NavigationEntry* entry = controller.GetLastCommittedEntry();
1458   if (!entry)
1459     return;
1460   if (entry->GetIsOverridingUserAgent())
1461     entry->SetIsOverridingUserAgent(false);
1462   else
1463     SetAndroidOsForTabletSite(current_tab);
1464   controller.Reload(content::ReloadType::ORIGINAL_REQUEST_URL, true);
1465 }
1466 
SetAndroidOsForTabletSite(content::WebContents * current_tab)1467 void SetAndroidOsForTabletSite(content::WebContents* current_tab) {
1468   DCHECK(current_tab);
1469   NavigationEntry* entry = current_tab->GetController().GetLastCommittedEntry();
1470   if (entry) {
1471     entry->SetIsOverridingUserAgent(true);
1472     std::string product =
1473         version_info::GetProductNameAndVersionForUserAgent() + " Mobile";
1474     blink::UserAgentOverride ua_override;
1475     ua_override.ua_string_override = content::BuildUserAgentFromOSAndProduct(
1476         kOsOverrideForTabletSite, product);
1477     ua_override.ua_metadata_override = GetUserAgentMetadata();
1478     ua_override.ua_metadata_override->mobile = true;
1479     ua_override.ua_metadata_override->platform =
1480         kChPlatformOverrideForTabletSite;
1481     ua_override.ua_metadata_override->platform_version = std::string();
1482     current_tab->SetUserAgentOverride(ua_override, false);
1483   }
1484 }
1485 
ToggleFullscreenMode(Browser * browser)1486 void ToggleFullscreenMode(Browser* browser) {
1487   DCHECK(browser);
1488   browser->exclusive_access_manager()
1489       ->fullscreen_controller()
1490       ->ToggleBrowserFullscreenMode();
1491 }
1492 
ClearCache(Browser * browser)1493 void ClearCache(Browser* browser) {
1494   content::BrowsingDataRemover* remover =
1495       content::BrowserContext::GetBrowsingDataRemover(browser->profile());
1496   remover->Remove(base::Time(), base::Time::Max(),
1497                   content::BrowsingDataRemover::DATA_TYPE_CACHE,
1498                   content::BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB);
1499   // BrowsingDataRemover takes care of deleting itself when done.
1500 }
1501 
IsDebuggerAttachedToCurrentTab(Browser * browser)1502 bool IsDebuggerAttachedToCurrentTab(Browser* browser) {
1503   WebContents* contents = browser->tab_strip_model()->GetActiveWebContents();
1504   return contents ? content::DevToolsAgentHost::IsDebuggerAttached(contents)
1505                   : false;
1506 }
1507 
CopyURL(Browser * browser)1508 void CopyURL(Browser* browser) {
1509   ui::ScopedClipboardWriter scw(ui::ClipboardBuffer::kCopyPaste);
1510   scw.WriteText(base::UTF8ToUTF16(browser->tab_strip_model()
1511                                       ->GetActiveWebContents()
1512                                       ->GetVisibleURL()
1513                                       .spec()));
1514 }
1515 
OpenInChrome(Browser * hosted_app_browser)1516 Browser* OpenInChrome(Browser* hosted_app_browser) {
1517   // Find a non-incognito browser.
1518   Browser* target_browser =
1519       chrome::FindTabbedBrowser(hosted_app_browser->profile(), false);
1520 
1521   if (!target_browser) {
1522     target_browser = Browser::Create(
1523         Browser::CreateParams(hosted_app_browser->profile(), true));
1524   }
1525 
1526   TabStripModel* source_tabstrip = hosted_app_browser->tab_strip_model();
1527   target_browser->tab_strip_model()->AppendWebContents(
1528       source_tabstrip->DetachWebContentsAt(source_tabstrip->active_index()),
1529       true);
1530   target_browser->window()->Show();
1531   return target_browser;
1532 }
1533 
CanViewSource(const Browser * browser)1534 bool CanViewSource(const Browser* browser) {
1535   return !browser->is_type_devtools() && browser->tab_strip_model()
1536                                              ->GetActiveWebContents()
1537                                              ->GetController()
1538                                              .CanViewSource();
1539 }
1540 
CanToggleCaretBrowsing(Browser * browser)1541 bool CanToggleCaretBrowsing(Browser* browser) {
1542 #if defined(OS_MAC)
1543   // On Mac, ignore the keyboard shortcut unless web contents is focused,
1544   // because the keyboard shortcut interferes with a Japenese IME when the
1545   // omnibox is focused.  See https://crbug.com/1138475
1546   WebContents* web_contents =
1547       browser->tab_strip_model()->GetActiveWebContents();
1548   if (!web_contents)
1549     return false;
1550 
1551   content::RenderWidgetHostView* rwhv = web_contents->GetRenderWidgetHostView();
1552   return rwhv && rwhv->HasFocus();
1553 #else
1554   return true;
1555 #endif  // defined(OS_MAC)
1556 }
1557 
ToggleCaretBrowsing(Browser * browser)1558 void ToggleCaretBrowsing(Browser* browser) {
1559   if (!CanToggleCaretBrowsing(browser))
1560     return;
1561 
1562   PrefService* prefService = browser->profile()->GetPrefs();
1563   bool enabled = prefService->GetBoolean(prefs::kCaretBrowsingEnabled);
1564 
1565   if (enabled) {
1566     base::RecordAction(base::UserMetricsAction(
1567         "Accessibility.CaretBrowsing.DisableWithKeyboard"));
1568     prefService->SetBoolean(prefs::kCaretBrowsingEnabled, false);
1569     return;
1570   }
1571 
1572   // Show a confirmation dialog, unless either (1) the command-line
1573   // flag was used, or (2) the user previously checked the box
1574   // indicating not to ask them next time.
1575   if (prefService->GetBoolean(prefs::kShowCaretBrowsingDialog) &&
1576       !base::CommandLine::ForCurrentProcess()->HasSwitch(
1577           switches::kEnableCaretBrowsing)) {
1578     browser->window()->ShowCaretBrowsingDialog();
1579   } else {
1580     base::RecordAction(base::UserMetricsAction(
1581         "Accessibility.CaretBrowsing.EnableWithKeyboard"));
1582     prefService->SetBoolean(prefs::kCaretBrowsingEnabled, true);
1583   }
1584 }
1585 
PromptToNameWindow(Browser * browser)1586 void PromptToNameWindow(Browser* browser) {
1587   chrome::ShowWindowNamePrompt(browser);
1588 }
1589 
ToggleCommander(Browser * browser)1590 void ToggleCommander(Browser* browser) {
1591   commander::Commander::Get()->ToggleForBrowser(browser);
1592 }
1593 
1594 #if !defined(TOOLKIT_VIEWS)
GetKeyboardFocusedTabIndex(const Browser * browser)1595 base::Optional<int> GetKeyboardFocusedTabIndex(const Browser* browser) {
1596   return base::nullopt;
1597 }
1598 #endif
1599 
1600 }  // namespace chrome
1601