| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chrome/browser/ui/singleton_tabs.h" |
| |
| #include "chrome/browser/profiles/profile.h" |
| #include "chrome/browser/search/search.h" |
| #include "chrome/browser/ui/browser.h" |
| #include "chrome/browser/ui/browser_navigator.h" |
| #include "chrome/browser/ui/tabs/tab_strip_model.h" |
| #include "chrome/common/url_constants.h" |
| #include "content/public/browser/browser_url_handler.h" |
| #include "content/public/browser/web_contents.h" |
| |
| namespace chrome { |
| namespace { |
| |
| // Returns true if two URLs are equal after taking |replacements| into account. |
| bool CompareURLsWithReplacements( |
| const GURL& url, |
| const GURL& other, |
| const url_canon::Replacements<char>& replacements) { |
| if (url == other) |
| return true; |
| |
| GURL url_replaced = url.ReplaceComponents(replacements); |
| GURL other_replaced = other.ReplaceComponents(replacements); |
| return url_replaced == other_replaced; |
| } |
| |
| } // namespace |
| |
| void ShowSingletonTab(Browser* browser, const GURL& url) { |
| NavigateParams params(GetSingletonTabNavigateParams(browser, url)); |
| Navigate(¶ms); |
| } |
| |
| void ShowSingletonTabRespectRef(Browser* browser, const GURL& url) { |
| NavigateParams params(GetSingletonTabNavigateParams(browser, url)); |
| params.ref_behavior = NavigateParams::RESPECT_REF; |
| Navigate(¶ms); |
| } |
| |
| void ShowSingletonTabOverwritingNTP(Browser* browser, |
| const NavigateParams& params) { |
| DCHECK(browser); |
| NavigateParams local_params(params); |
| content::WebContents* contents = |
| browser->tab_strip_model()->GetActiveWebContents(); |
| if (contents) { |
| const GURL& contents_url = contents->GetURL(); |
| if ((contents_url == GURL(kChromeUINewTabURL) || IsInstantNTP(contents) || |
| contents_url == GURL(content::kAboutBlankURL)) && |
| GetIndexOfSingletonTab(&local_params) < 0) { |
| local_params.disposition = CURRENT_TAB; |
| } |
| } |
| |
| Navigate(&local_params); |
| } |
| |
| NavigateParams GetSingletonTabNavigateParams(Browser* browser, |
| const GURL& url) { |
| NavigateParams params(browser, url, content::PAGE_TRANSITION_AUTO_BOOKMARK); |
| params.disposition = SINGLETON_TAB; |
| params.window_action = NavigateParams::SHOW_WINDOW; |
| params.user_gesture = true; |
| params.tabstrip_add_types |= TabStripModel::ADD_INHERIT_OPENER; |
| return params; |
| } |
| |
| // Returns the index of an existing singleton tab in |params->browser| matching |
| // the URL specified in |params|. |
| int GetIndexOfSingletonTab(NavigateParams* params) { |
| if (params->disposition != SINGLETON_TAB) |
| return -1; |
| |
| // In case the URL was rewritten by the BrowserURLHandler we need to ensure |
| // that we do not open another URL that will get redirected to the rewritten |
| // URL. |
| GURL rewritten_url(params->url); |
| bool reverse_on_redirect = false; |
| content::BrowserURLHandler::GetInstance()->RewriteURLIfNecessary( |
| &rewritten_url, |
| params->browser->profile(), |
| &reverse_on_redirect); |
| |
| // If there are several matches: prefer the active tab by starting there. |
| int start_index = |
| std::max(0, params->browser->tab_strip_model()->active_index()); |
| int tab_count = params->browser->tab_strip_model()->count(); |
| for (int i = 0; i < tab_count; ++i) { |
| int tab_index = (start_index + i) % tab_count; |
| content::WebContents* tab = |
| params->browser->tab_strip_model()->GetWebContentsAt(tab_index); |
| |
| GURL tab_url = tab->GetURL(); |
| |
| // Skip view-source tabs. This is needed because RewriteURLIfNecessary |
| // removes the "view-source:" scheme which leads to incorrect matching. |
| if (tab_url.SchemeIs(content::kViewSourceScheme)) |
| continue; |
| |
| GURL rewritten_tab_url = tab_url; |
| content::BrowserURLHandler::GetInstance()->RewriteURLIfNecessary( |
| &rewritten_tab_url, |
| params->browser->profile(), |
| &reverse_on_redirect); |
| |
| url_canon::Replacements<char> replacements; |
| if (params->ref_behavior == NavigateParams::IGNORE_REF) |
| replacements.ClearRef(); |
| if (params->path_behavior == NavigateParams::IGNORE_AND_NAVIGATE || |
| params->path_behavior == NavigateParams::IGNORE_AND_STAY_PUT) { |
| replacements.ClearPath(); |
| replacements.ClearQuery(); |
| } |
| |
| if (CompareURLsWithReplacements(tab_url, params->url, replacements) || |
| CompareURLsWithReplacements(rewritten_tab_url, |
| rewritten_url, |
| replacements)) { |
| params->target_contents = tab; |
| return tab_index; |
| } |
| } |
| |
| return -1; |
| } |
| |
| } // namespace chrome |