This source file includes following definitions.
- AttachTabHelpers
- WindowCanOpenTabs
- GetOrCreateBrowser
- AdjustNavigateParamsForURL
- GetBrowserForDisposition
- NormalizeDisposition
- GetSourceProfile
- LoadURLInContents
- TakeOwnership
- ReleaseOwnership
- CreateTargetContents
- SwapInPrerender
- GetHostDesktop
- should_set_opener
- should_set_opener
- should_set_opener
- FillNavigateParamsFromOpenURLParams
- Navigate
- IsURLAllowedInIncognito
#include "chrome/browser/ui/browser_navigator.h"
#include <algorithm>
#include "base/command_line.h"
#include "base/prefs/pref_service.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/browser_about_handler.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/extensions/tab_helper.h"
#include "chrome/browser/google/google_url_tracker.h"
#include "chrome/browser/prefs/incognito_mode_prefs.h"
#include "chrome/browser/prerender/prerender_manager.h"
#include "chrome/browser/prerender/prerender_manager_factory.h"
#include "chrome/browser/prerender/prerender_util.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/tab_contents/tab_util.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/browser_instant_controller.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/host_desktop.h"
#include "chrome/browser/ui/omnibox/location_bar.h"
#include "chrome/browser/ui/search/instant_search_prerenderer.h"
#include "chrome/browser/ui/singleton_tabs.h"
#include "chrome/browser/ui/status_bubble.h"
#include "chrome/browser/ui/tab_helpers.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/browser/web_applications/web_app.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/url_constants.h"
#include "content/public/browser/browser_url_handler.h"
#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_view.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/common/extension.h"
#include "extensions/common/extension_set.h"
#if defined(USE_ASH)
#include "chrome/browser/ui/ash/multi_user/multi_user_window_manager.h"
#endif
#if defined(USE_AURA)
#include "ui/aura/window.h"
#endif
using content::GlobalRequestID;
using content::NavigationController;
using content::WebContents;
class BrowserNavigatorWebContentsAdoption {
public:
static void AttachTabHelpers(content::WebContents* contents) {
TabHelpers::AttachTabHelpers(contents);
}
};
namespace {
bool WindowCanOpenTabs(Browser* browser) {
return browser->CanSupportWindowFeature(Browser::FEATURE_TABSTRIP) ||
browser->tab_strip_model()->empty();
}
Browser* GetOrCreateBrowser(Profile* profile,
chrome::HostDesktopType host_desktop_type) {
Browser* browser = chrome::FindTabbedBrowser(profile, false,
host_desktop_type);
return browser ? browser : new Browser(
Browser::CreateParams(profile, host_desktop_type));
}
bool AdjustNavigateParamsForURL(chrome::NavigateParams* params) {
if (params->target_contents != NULL ||
chrome::IsURLAllowedInIncognito(params->url,
params->initiating_profile) ||
params->initiating_profile->IsGuestSession()) {
return true;
}
Profile* profile = params->initiating_profile;
if (profile->IsOffTheRecord() || params->disposition == OFF_THE_RECORD) {
profile = profile->GetOriginalProfile();
PrefService* prefs = profile->GetPrefs();
if (prefs && IncognitoModePrefs::GetAvailability(prefs) ==
IncognitoModePrefs::FORCED) {
return false;
}
params->disposition = SINGLETON_TAB;
params->browser = GetOrCreateBrowser(profile, params->host_desktop_type);
params->window_action = chrome::NavigateParams::SHOW_WINDOW;
}
return true;
}
Browser* GetBrowserForDisposition(chrome::NavigateParams* params) {
if (!params->source_contents && params->browser) {
params->source_contents =
params->browser->tab_strip_model()->GetActiveWebContents();
}
Profile* profile = params->initiating_profile;
switch (params->disposition) {
case CURRENT_TAB:
if (params->browser)
return params->browser;
return GetOrCreateBrowser(profile, params->host_desktop_type);
case SINGLETON_TAB:
case NEW_FOREGROUND_TAB:
case NEW_BACKGROUND_TAB:
if (params->browser && WindowCanOpenTabs(params->browser))
return params->browser;
return GetOrCreateBrowser(profile, params->host_desktop_type);
case NEW_POPUP: {
std::string app_name;
if (!params->extension_app_id.empty()) {
app_name = web_app::GenerateApplicationNameFromExtensionId(
params->extension_app_id);
} else if (params->browser && !params->browser->app_name().empty()) {
app_name = params->browser->app_name();
} else if (params->source_contents) {
extensions::TabHelper* extensions_tab_helper =
extensions::TabHelper::FromWebContents(params->source_contents);
if (extensions_tab_helper && extensions_tab_helper->is_app()) {
app_name = web_app::GenerateApplicationNameFromExtensionId(
extensions_tab_helper->extension_app()->id());
}
}
if (app_name.empty()) {
Browser::CreateParams browser_params(
Browser::TYPE_POPUP, profile, params->host_desktop_type);
browser_params.initial_bounds = params->window_bounds;
return new Browser(browser_params);
}
return new Browser(Browser::CreateParams::CreateForApp(
Browser::TYPE_POPUP, app_name, params->window_bounds, profile,
params->host_desktop_type));
}
case NEW_WINDOW: {
return new Browser(Browser::CreateParams(profile,
params->host_desktop_type));
}
case OFF_THE_RECORD:
return GetOrCreateBrowser(profile->GetOffTheRecordProfile(),
params->host_desktop_type);
case SUPPRESS_OPEN:
case SAVE_TO_DISK:
case IGNORE_ACTION:
return NULL;
default:
NOTREACHED();
}
return NULL;
}
void NormalizeDisposition(chrome::NavigateParams* params) {
if (params->browser->tab_strip_model()->empty() &&
(params->disposition == NEW_BACKGROUND_TAB ||
params->disposition == CURRENT_TAB ||
params->disposition == SINGLETON_TAB)) {
params->disposition = NEW_FOREGROUND_TAB;
}
if (params->browser->profile()->IsOffTheRecord() &&
params->disposition == OFF_THE_RECORD) {
params->disposition = NEW_FOREGROUND_TAB;
}
if (!params->source_contents && params->disposition == CURRENT_TAB)
params->disposition = NEW_FOREGROUND_TAB;
switch (params->disposition) {
case NEW_BACKGROUND_TAB:
params->tabstrip_add_types &= ~TabStripModel::ADD_ACTIVE;
break;
case NEW_WINDOW:
case NEW_POPUP:
if (params->window_action == chrome::NavigateParams::NO_ACTION)
params->window_action = chrome::NavigateParams::SHOW_WINDOW;
case NEW_FOREGROUND_TAB:
case SINGLETON_TAB:
params->tabstrip_add_types |= TabStripModel::ADD_ACTIVE;
break;
default:
break;
}
}
Profile* GetSourceProfile(chrome::NavigateParams* params) {
if (params->source_contents) {
return Profile::FromBrowserContext(
params->source_contents->GetBrowserContext());
}
return params->initiating_profile;
}
void LoadURLInContents(WebContents* target_contents,
const GURL& url,
chrome::NavigateParams* params) {
NavigationController::LoadURLParams load_url_params(url);
load_url_params.referrer = params->referrer;
load_url_params.frame_tree_node_id = params->frame_tree_node_id;
load_url_params.redirect_chain = params->redirect_chain;
load_url_params.transition_type = params->transition;
load_url_params.extra_headers = params->extra_headers;
load_url_params.should_replace_current_entry =
params->should_replace_current_entry;
if (params->transferred_global_request_id != GlobalRequestID()) {
load_url_params.is_renderer_initiated = params->is_renderer_initiated;
load_url_params.transferred_global_request_id =
params->transferred_global_request_id;
} else if (params->is_renderer_initiated) {
load_url_params.is_renderer_initiated = true;
}
if (params->uses_post && !params->is_renderer_initiated) {
load_url_params.load_type =
NavigationController::LOAD_TYPE_BROWSER_INITIATED_HTTP_POST;
load_url_params.browser_initiated_post_data =
params->browser_initiated_post_data;
}
target_contents->GetController().LoadURLWithParams(load_url_params);
}
class ScopedBrowserShower {
public:
explicit ScopedBrowserShower(chrome::NavigateParams* params)
: params_(params) {
}
~ScopedBrowserShower() {
if (params_->window_action == chrome::NavigateParams::SHOW_WINDOW_INACTIVE)
params_->browser->window()->ShowInactive();
else if (params_->window_action == chrome::NavigateParams::SHOW_WINDOW)
params_->browser->window()->Show();
}
private:
chrome::NavigateParams* params_;
DISALLOW_COPY_AND_ASSIGN(ScopedBrowserShower);
};
class ScopedTargetContentsOwner {
public:
explicit ScopedTargetContentsOwner(chrome::NavigateParams* params)
: params_(params) {
}
~ScopedTargetContentsOwner() {
if (target_contents_owner_.get())
params_->target_contents = NULL;
}
void TakeOwnership() {
target_contents_owner_.reset(params_->target_contents);
}
WebContents* ReleaseOwnership() {
return target_contents_owner_.release();
}
private:
chrome::NavigateParams* params_;
scoped_ptr<WebContents> target_contents_owner_;
DISALLOW_COPY_AND_ASSIGN(ScopedTargetContentsOwner);
};
content::WebContents* CreateTargetContents(const chrome::NavigateParams& params,
const GURL& url) {
WebContents::CreateParams create_params(
params.browser->profile(),
tab_util::GetSiteInstanceForNewTab(params.browser->profile(), url));
if (params.source_contents) {
create_params.initial_size =
params.source_contents->GetView()->GetContainerSize();
if (params.should_set_opener)
create_params.opener = params.source_contents;
}
if (params.disposition == NEW_BACKGROUND_TAB)
create_params.initially_hidden = true;
#if defined(USE_AURA)
if (params.browser->window() &&
params.browser->window()->GetNativeWindow()) {
create_params.context =
params.browser->window()->GetNativeWindow();
}
#endif
WebContents* target_contents = WebContents::Create(create_params);
BrowserNavigatorWebContentsAdoption::AttachTabHelpers(target_contents);
extensions::TabHelper::FromWebContents(target_contents)->
SetExtensionAppById(params.extension_app_id);
return target_contents;
}
bool SwapInPrerender(const GURL& url, chrome::NavigateParams* params) {
Profile* profile =
Profile::FromBrowserContext(params->target_contents->GetBrowserContext());
InstantSearchPrerenderer* prerenderer =
InstantSearchPrerenderer::GetForProfile(profile);
if (prerenderer && prerenderer->UsePrerenderedPage(url, params))
return true;
prerender::PrerenderManager* prerender_manager =
prerender::PrerenderManagerFactory::GetForProfile(profile);
return prerender_manager &&
prerender_manager->MaybeUsePrerenderedPage(url, params);
}
chrome::HostDesktopType GetHostDesktop(Browser* browser) {
if (browser)
return browser->host_desktop_type();
return chrome::GetActiveDesktop();
}
}
namespace chrome {
NavigateParams::NavigateParams(Browser* a_browser,
const GURL& a_url,
content::PageTransition a_transition)
: url(a_url),
frame_tree_node_id(-1),
uses_post(false),
target_contents(NULL),
source_contents(NULL),
disposition(CURRENT_TAB),
transition(a_transition),
is_renderer_initiated(false),
tabstrip_index(-1),
tabstrip_add_types(TabStripModel::ADD_ACTIVE),
window_action(NO_ACTION),
user_gesture(true),
path_behavior(RESPECT),
ref_behavior(IGNORE_REF),
browser(a_browser),
initiating_profile(NULL),
host_desktop_type(GetHostDesktop(a_browser)),
should_replace_current_entry(false),
should_set_opener(false) {
}
NavigateParams::NavigateParams(Browser* a_browser,
WebContents* a_target_contents)
: frame_tree_node_id(-1),
uses_post(false),
target_contents(a_target_contents),
source_contents(NULL),
disposition(CURRENT_TAB),
transition(content::PAGE_TRANSITION_LINK),
is_renderer_initiated(false),
tabstrip_index(-1),
tabstrip_add_types(TabStripModel::ADD_ACTIVE),
window_action(NO_ACTION),
user_gesture(true),
path_behavior(RESPECT),
ref_behavior(IGNORE_REF),
browser(a_browser),
initiating_profile(NULL),
host_desktop_type(GetHostDesktop(a_browser)),
should_replace_current_entry(false),
should_set_opener(false) {
}
NavigateParams::NavigateParams(Profile* a_profile,
const GURL& a_url,
content::PageTransition a_transition)
: url(a_url),
frame_tree_node_id(-1),
uses_post(false),
target_contents(NULL),
source_contents(NULL),
disposition(NEW_FOREGROUND_TAB),
transition(a_transition),
is_renderer_initiated(false),
tabstrip_index(-1),
tabstrip_add_types(TabStripModel::ADD_ACTIVE),
window_action(SHOW_WINDOW),
user_gesture(true),
path_behavior(RESPECT),
ref_behavior(IGNORE_REF),
browser(NULL),
initiating_profile(a_profile),
host_desktop_type(chrome::GetActiveDesktop()),
should_replace_current_entry(false),
should_set_opener(false) {
}
NavigateParams::~NavigateParams() {}
void FillNavigateParamsFromOpenURLParams(chrome::NavigateParams* nav_params,
const content::OpenURLParams& params) {
nav_params->referrer = params.referrer;
nav_params->frame_tree_node_id = params.frame_tree_node_id;
nav_params->redirect_chain = params.redirect_chain;
nav_params->extra_headers = params.extra_headers;
nav_params->disposition = params.disposition;
nav_params->is_renderer_initiated = params.is_renderer_initiated;
nav_params->transferred_global_request_id =
params.transferred_global_request_id;
nav_params->should_replace_current_entry =
params.should_replace_current_entry;
nav_params->uses_post = params.uses_post;
nav_params->browser_initiated_post_data = params.browser_initiated_post_data;
}
void Navigate(NavigateParams* params) {
Browser* source_browser = params->browser;
if (source_browser)
params->initiating_profile = source_browser->profile();
DCHECK(params->initiating_profile);
if (!AdjustNavigateParamsForURL(params))
return;
const extensions::Extension* extension =
extensions::ExtensionRegistry::Get(params->initiating_profile)->
enabled_extensions().GetExtensionOrAppByURL(params->url);
if (extension && extension->is_platform_app())
params->url = GURL(chrome::kExtensionInvalidRequestURL);
if (params->disposition == NEW_POPUP &&
source_browser &&
source_browser->window()) {
params->disposition =
source_browser->window()->GetDispositionForPopupBounds(
params->window_bounds);
}
params->browser = GetBrowserForDisposition(params);
if (!params->browser)
return;
#if defined(USE_ASH)
if (source_browser && source_browser != params->browser) {
MultiUserWindowManager* manager = MultiUserWindowManager::GetInstance();
if (manager) {
aura::Window* src_window = source_browser->window()->GetNativeWindow();
aura::Window* new_window = params->browser->window()->GetNativeWindow();
const std::string& src_user =
manager->GetUserPresentingWindow(src_window);
if (src_user != manager->GetUserPresentingWindow(new_window)) {
manager->ShowWindowForUser(new_window, src_user);
}
}
}
#endif
if (GetSourceProfile(params) != params->browser->profile()) {
params->source_contents = NULL;
params->referrer = content::Referrer();
}
ScopedBrowserShower shower(params);
ScopedTargetContentsOwner target_contents_owner(params);
NormalizeDisposition(params);
if (params->window_action == NavigateParams::NO_ACTION &&
source_browser != params->browser &&
params->browser->tab_strip_model()->empty()) {
params->window_action = NavigateParams::SHOW_WINDOW;
}
if (params->window_action == NavigateParams::SHOW_WINDOW &&
params->disposition == NEW_POPUP &&
params->user_gesture == false) {
params->window_action = NavigateParams::SHOW_WINDOW_INACTIVE;
}
content::PageTransition base_transition =
content::PageTransitionStripQualifier(params->transition);
bool user_initiated =
params->transition & content::PAGE_TRANSITION_FROM_ADDRESS_BAR ||
base_transition == content::PAGE_TRANSITION_TYPED ||
base_transition == content::PAGE_TRANSITION_AUTO_BOOKMARK ||
base_transition == content::PAGE_TRANSITION_GENERATED ||
base_transition == content::PAGE_TRANSITION_AUTO_TOPLEVEL ||
base_transition == content::PAGE_TRANSITION_RELOAD ||
base_transition == content::PAGE_TRANSITION_KEYWORD;
int singleton_index = chrome::GetIndexOfSingletonTab(params);
bool swapped_in_prerender = false;
if (!params->target_contents && singleton_index < 0) {
GURL url;
if (params->url.is_empty()) {
url = params->browser->profile()->GetHomePage();
params->transition = content::PageTransitionFromInt(
params->transition | content::PAGE_TRANSITION_HOME_PAGE);
} else {
url = params->url;
}
if (params->disposition != CURRENT_TAB) {
params->target_contents = CreateTargetContents(*params, url);
target_contents_owner.TakeOwnership();
} else {
DCHECK(params->source_contents);
params->target_contents = params->source_contents;
DCHECK(params->target_contents);
swapped_in_prerender = SwapInPrerender(url, params);
}
if (user_initiated)
params->target_contents->UserGestureDone();
if (!swapped_in_prerender) {
if (!HandleNonNavigationAboutURL(url)) {
LoadURLInContents(params->target_contents, url, params);
content::NavigationEntry* entry =
params->target_contents->GetController().GetPendingEntry();
if (entry)
entry->SetExtraData(prerender::kChromeNavigateExtraDataKey,
base::string16());
}
}
} else {
}
if (params->source_contents &&
(params->disposition == NEW_FOREGROUND_TAB ||
params->disposition == NEW_WINDOW) &&
(params->tabstrip_add_types & TabStripModel::ADD_INHERIT_OPENER))
params->source_contents->GetView()->Focus();
if (params->source_contents == params->target_contents ||
(swapped_in_prerender && params->disposition == CURRENT_TAB)) {
params->browser->UpdateUIForNavigationInTab(params->target_contents,
params->transition,
user_initiated);
} else if (singleton_index == -1) {
if (params->tabstrip_index != -1)
params->tabstrip_add_types |= TabStripModel::ADD_FORCE_INDEX;
params->browser->tab_strip_model()->AddWebContents(
params->target_contents,
params->tabstrip_index,
params->transition,
params->tabstrip_add_types);
target_contents_owner.ReleaseOwnership();
}
if (singleton_index >= 0) {
WebContents* target =
params->browser->tab_strip_model()->GetWebContentsAt(singleton_index);
if (target->IsCrashed()) {
target->GetController().Reload(true);
} else if (params->path_behavior == NavigateParams::IGNORE_AND_NAVIGATE &&
target->GetURL() != params->url) {
LoadURLInContents(target, params->url, params);
content::NavigationEntry* entry =
target->GetController().GetPendingEntry();
if (entry)
entry->SetExtraData(prerender::kChromeNavigateExtraDataKey,
base::string16());
}
if (params->source_contents != params->target_contents) {
params->browser->tab_strip_model()->ActivateTabAt(singleton_index,
user_initiated);
}
}
if (params->disposition != CURRENT_TAB) {
content::NotificationService::current()->Notify(
chrome::NOTIFICATION_TAB_ADDED,
content::Source<content::WebContentsDelegate>(params->browser),
content::Details<WebContents>(params->target_contents));
}
}
bool IsURLAllowedInIncognito(const GURL& url,
content::BrowserContext* browser_context) {
if (url.scheme() == content::kViewSourceScheme) {
std::string stripped_spec = url.spec();
DCHECK_GT(stripped_spec.size(), strlen(content::kViewSourceScheme));
stripped_spec.erase(0, strlen(content::kViewSourceScheme) + 1);
GURL stripped_url(stripped_spec);
return stripped_url.is_valid() &&
IsURLAllowedInIncognito(stripped_url, browser_context);
}
if (url.scheme() == content::kChromeUIScheme &&
(url.host() == chrome::kChromeUISettingsHost ||
url.host() == chrome::kChromeUISettingsFrameHost ||
url.host() == chrome::kChromeUIExtensionsHost ||
url.host() == chrome::kChromeUIBookmarksHost ||
#if !defined(OS_CHROMEOS)
url.host() == chrome::kChromeUIChromeSigninHost ||
#endif
url.host() == chrome::kChromeUIUberHost ||
url.host() == chrome::kChromeUIThumbnailHost ||
url.host() == chrome::kChromeUIThumbnailHost2 ||
url.host() == chrome::kChromeUIThumbnailListHost ||
url.host() == chrome::kChromeUISuggestionsHost)) {
return false;
}
if (url.scheme() == chrome::kChromeSearchScheme &&
(url.host() == chrome::kChromeUIThumbnailHost ||
url.host() == chrome::kChromeUIThumbnailHost2 ||
url.host() == chrome::kChromeUIThumbnailListHost ||
url.host() == chrome::kChromeUISuggestionsHost)) {
return false;
}
GURL rewritten_url = url;
bool reverse_on_redirect = false;
content::BrowserURLHandler::GetInstance()->RewriteURLIfNecessary(
&rewritten_url, browser_context, &reverse_on_redirect);
return !(rewritten_url.scheme() == content::kChromeUIScheme &&
rewritten_url.host() == chrome::kChromeUIUberHost);
}
}