// 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