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(¶ms);
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