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(const GURL
& url
,
22 const url::Replacements
<char>& replacements
) {
26 GURL url_replaced
= url
.ReplaceComponents(replacements
);
27 GURL other_replaced
= other
.ReplaceComponents(replacements
);
28 return url_replaced
== other_replaced
;
33 void ShowSingletonTab(Browser
* browser
, const GURL
& url
) {
34 NavigateParams
params(GetSingletonTabNavigateParams(browser
, url
));
38 void ShowSingletonTabRespectRef(Browser
* browser
, const GURL
& url
) {
39 NavigateParams
params(GetSingletonTabNavigateParams(browser
, url
));
40 params
.ref_behavior
= NavigateParams::RESPECT_REF
;
44 void ShowSingletonTabOverwritingNTP(Browser
* browser
,
45 const NavigateParams
& params
) {
47 NavigateParams
local_params(params
);
48 content::WebContents
* contents
=
49 browser
->tab_strip_model()->GetActiveWebContents();
51 const GURL
& contents_url
= contents
->GetURL();
52 if ((contents_url
== GURL(kChromeUINewTabURL
) || IsInstantNTP(contents
) ||
53 contents_url
== GURL(url::kAboutBlankURL
)) &&
54 GetIndexOfSingletonTab(&local_params
) < 0) {
55 local_params
.disposition
= CURRENT_TAB
;
59 Navigate(&local_params
);
62 NavigateParams
GetSingletonTabNavigateParams(Browser
* browser
,
64 NavigateParams
params(browser
, url
, ui::PAGE_TRANSITION_AUTO_BOOKMARK
);
65 params
.disposition
= SINGLETON_TAB
;
66 params
.window_action
= NavigateParams::SHOW_WINDOW
;
67 params
.user_gesture
= true;
68 params
.tabstrip_add_types
|= TabStripModel::ADD_INHERIT_OPENER
;
72 // Returns the index of an existing singleton tab in |params->browser| matching
73 // the URL specified in |params|.
74 int GetIndexOfSingletonTab(NavigateParams
* params
) {
75 if (params
->disposition
!= SINGLETON_TAB
)
78 // In case the URL was rewritten by the BrowserURLHandler we need to ensure
79 // that we do not open another URL that will get redirected to the rewritten
81 GURL
rewritten_url(params
->url
);
82 bool reverse_on_redirect
= false;
83 content::BrowserURLHandler::GetInstance()->RewriteURLIfNecessary(
85 params
->browser
->profile(),
86 &reverse_on_redirect
);
88 // If there are several matches: prefer the active tab by starting there.
90 std::max(0, params
->browser
->tab_strip_model()->active_index());
91 int tab_count
= params
->browser
->tab_strip_model()->count();
92 for (int i
= 0; i
< tab_count
; ++i
) {
93 int tab_index
= (start_index
+ i
) % tab_count
;
94 content::WebContents
* tab
=
95 params
->browser
->tab_strip_model()->GetWebContentsAt(tab_index
);
97 GURL tab_url
= tab
->GetURL();
99 // Skip view-source tabs. This is needed because RewriteURLIfNecessary
100 // removes the "view-source:" scheme which leads to incorrect matching.
101 if (tab_url
.SchemeIs(content::kViewSourceScheme
))
104 GURL rewritten_tab_url
= tab_url
;
105 content::BrowserURLHandler::GetInstance()->RewriteURLIfNecessary(
107 params
->browser
->profile(),
108 &reverse_on_redirect
);
110 url::Replacements
<char> replacements
;
111 if (params
->ref_behavior
== NavigateParams::IGNORE_REF
)
112 replacements
.ClearRef();
113 if (params
->path_behavior
== NavigateParams::IGNORE_AND_NAVIGATE
||
114 params
->path_behavior
== NavigateParams::IGNORE_AND_STAY_PUT
) {
115 replacements
.ClearPath();
116 replacements
.ClearQuery();
119 if (CompareURLsWithReplacements(tab_url
, params
->url
, replacements
) ||
120 CompareURLsWithReplacements(rewritten_tab_url
,
123 params
->target_contents
= tab
;
131 } // namespace chrome