Home | History | Annotate | Download | only in ui
      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.
     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 
     34 void ShowSingletonTab(Browser* browser, const GURL& url) {
     35   NavigateParams params(GetSingletonTabNavigateParams(browser, url));
     36   Navigate(&params);
     37 }
     38 
     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 
     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 
     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|.
     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