• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/singleton_tabs.h"
6 
7 #include "chrome/browser/profiles/profile.h"
8 #include "chrome/browser/search/search.h"
9 #include "chrome/browser/ui/browser.h"
10 #include "chrome/browser/ui/browser_navigator.h"
11 #include "chrome/browser/ui/tabs/tab_strip_model.h"
12 #include "chrome/common/url_constants.h"
13 #include "content/public/browser/browser_url_handler.h"
14 #include "content/public/browser/web_contents.h"
15 
16 namespace chrome {
17 namespace {
18 
19 // Returns true if two URLs are equal after taking |replacements| into account.
CompareURLsWithReplacements(const GURL & url,const GURL & other,const url_canon::Replacements<char> & replacements)20 bool CompareURLsWithReplacements(
21     const GURL& url,
22     const GURL& other,
23     const url_canon::Replacements<char>& replacements) {
24   if (url == other)
25     return true;
26 
27   GURL url_replaced = url.ReplaceComponents(replacements);
28   GURL other_replaced = other.ReplaceComponents(replacements);
29   return url_replaced == other_replaced;
30 }
31 
32 }  // namespace
33 
ShowSingletonTab(Browser * browser,const GURL & url)34 void ShowSingletonTab(Browser* browser, const GURL& url) {
35   NavigateParams params(GetSingletonTabNavigateParams(browser, url));
36   Navigate(&params);
37 }
38 
ShowSingletonTabRespectRef(Browser * browser,const GURL & url)39 void ShowSingletonTabRespectRef(Browser* browser, const GURL& url) {
40   NavigateParams params(GetSingletonTabNavigateParams(browser, url));
41   params.ref_behavior = NavigateParams::RESPECT_REF;
42   Navigate(&params);
43 }
44 
ShowSingletonTabOverwritingNTP(Browser * browser,const NavigateParams & params)45 void ShowSingletonTabOverwritingNTP(Browser* browser,
46                                     const NavigateParams& params) {
47   DCHECK(browser);
48   NavigateParams local_params(params);
49   content::WebContents* contents =
50       browser->tab_strip_model()->GetActiveWebContents();
51   if (contents) {
52     const GURL& contents_url = contents->GetURL();
53     if ((contents_url == GURL(kChromeUINewTabURL) || IsInstantNTP(contents) ||
54          contents_url == GURL(content::kAboutBlankURL)) &&
55         GetIndexOfSingletonTab(&local_params) < 0) {
56       local_params.disposition = CURRENT_TAB;
57     }
58   }
59 
60   Navigate(&local_params);
61 }
62 
GetSingletonTabNavigateParams(Browser * browser,const GURL & url)63 NavigateParams GetSingletonTabNavigateParams(Browser* browser,
64                                              const GURL& url) {
65   NavigateParams params(browser, url, content::PAGE_TRANSITION_AUTO_BOOKMARK);
66   params.disposition = SINGLETON_TAB;
67   params.window_action = NavigateParams::SHOW_WINDOW;
68   params.user_gesture = true;
69   params.tabstrip_add_types |= TabStripModel::ADD_INHERIT_OPENER;
70   return params;
71 }
72 
73 // Returns the index of an existing singleton tab in |params->browser| matching
74 // the URL specified in |params|.
GetIndexOfSingletonTab(NavigateParams * params)75 int GetIndexOfSingletonTab(NavigateParams* params) {
76   if (params->disposition != SINGLETON_TAB)
77     return -1;
78 
79   // In case the URL was rewritten by the BrowserURLHandler we need to ensure
80   // that we do not open another URL that will get redirected to the rewritten
81   // URL.
82   GURL rewritten_url(params->url);
83   bool reverse_on_redirect = false;
84   content::BrowserURLHandler::GetInstance()->RewriteURLIfNecessary(
85       &rewritten_url,
86       params->browser->profile(),
87       &reverse_on_redirect);
88 
89   // If there are several matches: prefer the active tab by starting there.
90   int start_index =
91       std::max(0, params->browser->tab_strip_model()->active_index());
92   int tab_count = params->browser->tab_strip_model()->count();
93   for (int i = 0; i < tab_count; ++i) {
94     int tab_index = (start_index + i) % tab_count;
95     content::WebContents* tab =
96         params->browser->tab_strip_model()->GetWebContentsAt(tab_index);
97 
98     GURL tab_url = tab->GetURL();
99 
100     // Skip view-source tabs. This is needed because RewriteURLIfNecessary
101     // removes the "view-source:" scheme which leads to incorrect matching.
102     if (tab_url.SchemeIs(content::kViewSourceScheme))
103       continue;
104 
105     GURL rewritten_tab_url = tab_url;
106     content::BrowserURLHandler::GetInstance()->RewriteURLIfNecessary(
107       &rewritten_tab_url,
108       params->browser->profile(),
109       &reverse_on_redirect);
110 
111     url_canon::Replacements<char> replacements;
112     if (params->ref_behavior == NavigateParams::IGNORE_REF)
113       replacements.ClearRef();
114     if (params->path_behavior == NavigateParams::IGNORE_AND_NAVIGATE ||
115         params->path_behavior == NavigateParams::IGNORE_AND_STAY_PUT) {
116       replacements.ClearPath();
117       replacements.ClearQuery();
118     }
119 
120     if (CompareURLsWithReplacements(tab_url, params->url, replacements) ||
121         CompareURLsWithReplacements(rewritten_tab_url,
122                                     rewritten_url,
123                                     replacements)) {
124       params->target_contents = tab;
125       return tab_index;
126     }
127   }
128 
129   return -1;
130 }
131 
132 }  // namespace chrome
133