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.
5 #include "chrome/browser/ui/singleton_tabs.h"
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"
19 // Returns true if two URLs are equal after taking |replacements| into account.
20 bool CompareURLsWithReplacements(
23 const url_canon::Replacements
<char>& replacements
) {
27 GURL url_replaced
= url
.ReplaceComponents(replacements
);
28 GURL other_replaced
= other
.ReplaceComponents(replacements
);
29 return url_replaced
== other_replaced
;
34 void ShowSingletonTab(Browser
* browser
, const GURL
& url
) {
35 NavigateParams
params(GetSingletonTabNavigateParams(browser
, url
));
39 void ShowSingletonTabRespectRef(Browser
* browser
, const GURL
& url
) {
40 NavigateParams
params(GetSingletonTabNavigateParams(browser
, url
));
41 params
.ref_behavior
= NavigateParams::RESPECT_REF
;
45 void ShowSingletonTabOverwritingNTP(Browser
* browser
,
46 const NavigateParams
& params
) {
48 NavigateParams
local_params(params
);
49 content::WebContents
* contents
=
50 browser
->tab_strip_model()->GetActiveWebContents();
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
;
60 Navigate(&local_params
);
63 NavigateParams
GetSingletonTabNavigateParams(Browser
* browser
,
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
;
73 // Returns the index of an existing singleton tab in |params->browser| matching
74 // the URL specified in |params|.
75 int GetIndexOfSingletonTab(NavigateParams
* params
) {
76 if (params
->disposition
!= SINGLETON_TAB
)
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
82 GURL
rewritten_url(params
->url
);
83 bool reverse_on_redirect
= false;
84 content::BrowserURLHandler::GetInstance()->RewriteURLIfNecessary(
86 params
->browser
->profile(),
87 &reverse_on_redirect
);
89 // If there are several matches: prefer the active tab by starting there.
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
);
98 GURL tab_url
= tab
->GetURL();
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
))
105 GURL rewritten_tab_url
= tab_url
;
106 content::BrowserURLHandler::GetInstance()->RewriteURLIfNecessary(
108 params
->browser
->profile(),
109 &reverse_on_redirect
);
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();
120 if (CompareURLsWithReplacements(tab_url
, params
->url
, replacements
) ||
121 CompareURLsWithReplacements(rewritten_tab_url
,
124 params
->target_contents
= tab
;
132 } // namespace chrome