15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/singleton_tabs.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h"
8a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "chrome/browser/search/search.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser_navigator.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/tabs/tab_strip_model.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/url_constants.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_url_handler.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_contents.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace chrome {
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns true if two URLs are equal after taking |replacements| into account.
205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liubool CompareURLsWithReplacements(const GURL& url,
215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                 const GURL& other,
225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                 const url::Replacements<char>& replacements) {
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (url == other)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL url_replaced = url.ReplaceComponents(replacements);
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL other_replaced = other.ReplaceComponents(replacements);
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return url_replaced == other_replaced;
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ShowSingletonTab(Browser* browser, const GURL& url) {
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NavigateParams params(GetSingletonTabNavigateParams(browser, url));
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Navigate(&params);
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ShowSingletonTabRespectRef(Browser* browser, const GURL& url) {
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NavigateParams params(GetSingletonTabNavigateParams(browser, url));
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  params.ref_behavior = NavigateParams::RESPECT_REF;
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Navigate(&params);
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ShowSingletonTabOverwritingNTP(Browser* browser,
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    const NavigateParams& params) {
46a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  DCHECK(browser);
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NavigateParams local_params(params);
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  content::WebContents* contents =
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      browser->tab_strip_model()->GetActiveWebContents();
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (contents) {
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& contents_url = contents->GetURL();
52a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    if ((contents_url == GURL(kChromeUINewTabURL) || IsInstantNTP(contents) ||
53f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)         contents_url == GURL(url::kAboutBlankURL)) &&
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GetIndexOfSingletonTab(&local_params) < 0) {
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      local_params.disposition = CURRENT_TAB;
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Navigate(&local_params);
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NavigateParams GetSingletonTabNavigateParams(Browser* browser,
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             const GURL& url) {
641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  NavigateParams params(browser, url, ui::PAGE_TRANSITION_AUTO_BOOKMARK);
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  params.disposition = SINGLETON_TAB;
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  params.window_action = NavigateParams::SHOW_WINDOW;
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  params.user_gesture = true;
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  params.tabstrip_add_types |= TabStripModel::ADD_INHERIT_OPENER;
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return params;
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns the index of an existing singleton tab in |params->browser| matching
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the URL specified in |params|.
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int GetIndexOfSingletonTab(NavigateParams* params) {
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (params->disposition != SINGLETON_TAB)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return -1;
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // In case the URL was rewritten by the BrowserURLHandler we need to ensure
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // that we do not open another URL that will get redirected to the rewritten
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // URL.
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL rewritten_url(params->url);
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool reverse_on_redirect = false;
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::BrowserURLHandler::GetInstance()->RewriteURLIfNecessary(
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &rewritten_url,
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      params->browser->profile(),
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &reverse_on_redirect);
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If there are several matches: prefer the active tab by starting there.
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int start_index =
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      std::max(0, params->browser->tab_strip_model()->active_index());
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int tab_count = params->browser->tab_strip_model()->count();
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < tab_count; ++i) {
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int tab_index = (start_index + i) % tab_count;
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    content::WebContents* tab =
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        params->browser->tab_strip_model()->GetWebContentsAt(tab_index);
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
97a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    GURL tab_url = tab->GetURL();
98a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
99a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    // Skip view-source tabs. This is needed because RewriteURLIfNecessary
100a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    // removes the "view-source:" scheme which leads to incorrect matching.
101868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (tab_url.SchemeIs(content::kViewSourceScheme))
102a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      continue;
103a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
104a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    GURL rewritten_tab_url = tab_url;
105a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    content::BrowserURLHandler::GetInstance()->RewriteURLIfNecessary(
106a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      &rewritten_tab_url,
107a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      params->browser->profile(),
108a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      &reverse_on_redirect);
109a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
1105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    url::Replacements<char> replacements;
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (params->ref_behavior == NavigateParams::IGNORE_REF)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      replacements.ClearRef();
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (params->path_behavior == NavigateParams::IGNORE_AND_NAVIGATE ||
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        params->path_behavior == NavigateParams::IGNORE_AND_STAY_PUT) {
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      replacements.ClearPath();
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      replacements.ClearQuery();
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (CompareURLsWithReplacements(tab_url, params->url, replacements) ||
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        CompareURLsWithReplacements(rewritten_tab_url,
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    rewritten_url,
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    replacements)) {
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      params->target_contents = tab;
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return tab_index;
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return -1;
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace chrome
132