1 // Copyright (c) 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_tabstrip.h"
6
7 #include "base/command_line.h"
8 #include "base/feature_list.h"
9 #include "chrome/browser/profiles/profile.h"
10 #include "chrome/browser/ui/browser.h"
11 #include "chrome/browser/ui/browser_navigator.h"
12 #include "chrome/browser/ui/browser_navigator_params.h"
13 #include "chrome/browser/ui/tab_contents/core_tab_helper.h"
14 #include "chrome/browser/ui/tabs/tab_strip_model.h"
15 #include "chrome/browser/ui/ui_features.h"
16 #include "chrome/common/chrome_switches.h"
17 #include "chrome/common/url_constants.h"
18 #include "content/public/browser/navigation_entry.h"
19 #include "content/public/browser/render_view_host.h"
20 #include "content/public/browser/web_contents.h"
21 #include "url/gurl.h"
22
23 namespace chrome {
24
AddTabAt(Browser * browser,const GURL & url,int idx,bool foreground,base::Optional<tab_groups::TabGroupId> group)25 void AddTabAt(Browser* browser,
26 const GURL& url,
27 int idx,
28 bool foreground,
29 base::Optional<tab_groups::TabGroupId> group) {
30 // Time new tab page creation time. We keep track of the timing data in
31 // WebContents, but we want to include the time it takes to create the
32 // WebContents object too.
33 base::TimeTicks new_tab_start_time = base::TimeTicks::Now();
34 NavigateParams params(browser, url.is_empty() ? browser->GetNewTabURL() : url,
35 ui::PAGE_TRANSITION_TYPED);
36 params.disposition = foreground ? WindowOpenDisposition::NEW_FOREGROUND_TAB
37 : WindowOpenDisposition::NEW_BACKGROUND_TAB;
38 params.tabstrip_index = idx;
39 params.group = group;
40 Navigate(¶ms);
41 CoreTabHelper* core_tab_helper =
42 CoreTabHelper::FromWebContents(params.navigated_or_inserted_contents);
43 core_tab_helper->set_new_tab_start_time(new_tab_start_time);
44 }
45
AddSelectedTabWithURL(Browser * browser,const GURL & url,ui::PageTransition transition)46 content::WebContents* AddSelectedTabWithURL(Browser* browser,
47 const GURL& url,
48 ui::PageTransition transition) {
49 NavigateParams params(browser, url, transition);
50 params.disposition = WindowOpenDisposition::NEW_FOREGROUND_TAB;
51 Navigate(¶ms);
52 return params.navigated_or_inserted_contents;
53 }
54
AddWebContents(Browser * browser,content::WebContents * source_contents,std::unique_ptr<content::WebContents> new_contents,const GURL & target_url,WindowOpenDisposition disposition,const gfx::Rect & initial_rect)55 void AddWebContents(Browser* browser,
56 content::WebContents* source_contents,
57 std::unique_ptr<content::WebContents> new_contents,
58 const GURL& target_url,
59 WindowOpenDisposition disposition,
60 const gfx::Rect& initial_rect) {
61 // No code for this yet.
62 DCHECK(disposition != WindowOpenDisposition::SAVE_TO_DISK);
63 // Can't create a new contents for the current tab - invalid case.
64 DCHECK(disposition != WindowOpenDisposition::CURRENT_TAB);
65
66 NavigateParams params(browser, std::move(new_contents));
67 params.source_contents = source_contents;
68 params.url = target_url;
69 params.disposition = disposition;
70 params.window_bounds = initial_rect;
71 params.window_action = NavigateParams::SHOW_WINDOW;
72 // At this point, we're already beyond the popup blocker. Even if the popup
73 // was created without a user gesture, we have to set |user_gesture| to true,
74 // so it gets correctly focused.
75 params.user_gesture = true;
76
77 ConfigureTabGroupForNavigation(¶ms);
78
79 Navigate(¶ms);
80 }
81
CloseWebContents(Browser * browser,content::WebContents * contents,bool add_to_history)82 void CloseWebContents(Browser* browser,
83 content::WebContents* contents,
84 bool add_to_history) {
85 int index = browser->tab_strip_model()->GetIndexOfWebContents(contents);
86 if (index == TabStripModel::kNoTab) {
87 NOTREACHED() << "CloseWebContents called for tab not in our strip";
88 return;
89 }
90
91 browser->tab_strip_model()->CloseWebContentsAt(
92 index, add_to_history ? TabStripModel::CLOSE_CREATE_HISTORICAL_TAB
93 : TabStripModel::CLOSE_NONE);
94 }
95
ConfigureTabGroupForNavigation(NavigateParams * nav_params)96 void ConfigureTabGroupForNavigation(NavigateParams* nav_params) {
97 if (!nav_params->source_contents)
98 return;
99
100 if (!nav_params->browser || !nav_params->browser->SupportsWindowFeature(
101 Browser::WindowFeature::FEATURE_TABSTRIP)) {
102 return;
103 }
104
105 TabStripModel* model = nav_params->browser->tab_strip_model();
106 DCHECK(model);
107
108 const int source_index =
109 model->GetIndexOfWebContents(nav_params->source_contents);
110
111 // If the source tab is not in the current tab strip (e.g. if the current
112 // navigation is in a new window), don't set the group. Groups cannot be
113 // shared across multiple windows.
114 if (source_index == TabStripModel::kNoTab)
115 return;
116
117 if (nav_params->disposition == WindowOpenDisposition::NEW_FOREGROUND_TAB ||
118 nav_params->disposition == WindowOpenDisposition::NEW_BACKGROUND_TAB) {
119 nav_params->group = model->GetTabGroupForTab(source_index);
120 if (base::FeatureList::IsEnabled(features::kTabGroupsAutoCreate) &&
121 !nav_params->group.has_value() && !model->IsTabPinned(source_index)) {
122 const GURL& source_url =
123 nav_params->source_contents->GetLastCommittedURL();
124 const GURL& target_url = nav_params->url;
125 if (target_url.DomainIs(source_url.host_piece()))
126 nav_params->group = model->AddToNewGroup({source_index});
127 }
128 }
129 }
130
131 } // namespace chrome
132