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(&params);
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(&params);
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(&params);
78 
79   Navigate(&params);
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