browser_navigator.cc revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
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/browser_navigator.h" 6 7#include <algorithm> 8 9#include "base/command_line.h" 10#include "base/prefs/pref_service.h" 11#include "base/stringprintf.h" 12#include "base/utf_string_conversions.h" 13#include "chrome/browser/browser_about_handler.h" 14#include "chrome/browser/extensions/extension_service.h" 15#include "chrome/browser/extensions/tab_helper.h" 16#include "chrome/browser/google/google_url_tracker.h" 17#include "chrome/browser/prefs/incognito_mode_prefs.h" 18#include "chrome/browser/prerender/prerender_manager.h" 19#include "chrome/browser/prerender/prerender_manager_factory.h" 20#include "chrome/browser/profiles/profile.h" 21#include "chrome/browser/tab_contents/tab_util.h" 22#include "chrome/browser/ui/browser.h" 23#include "chrome/browser/ui/browser_finder.h" 24#include "chrome/browser/ui/browser_instant_controller.h" 25#include "chrome/browser/ui/browser_tab_contents.h" 26#include "chrome/browser/ui/browser_window.h" 27#include "chrome/browser/ui/host_desktop.h" 28#include "chrome/browser/ui/omnibox/location_bar.h" 29#include "chrome/browser/ui/singleton_tabs.h" 30#include "chrome/browser/ui/status_bubble.h" 31#include "chrome/browser/ui/tabs/tab_strip_model.h" 32#include "chrome/browser/web_applications/web_app.h" 33#include "chrome/common/chrome_notification_types.h" 34#include "chrome/common/extensions/extension.h" 35#include "chrome/common/pref_names.h" 36#include "chrome/common/url_constants.h" 37#include "content/public/browser/browser_url_handler.h" 38#include "content/public/browser/notification_service.h" 39#include "content/public/browser/render_view_host.h" 40#include "content/public/browser/web_contents.h" 41#include "content/public/browser/web_contents_view.h" 42 43#if defined(USE_AURA) 44#include "ui/aura/window.h" 45#endif 46 47using content::GlobalRequestID; 48using content::WebContents; 49 50class BrowserNavigatorWebContentsAdoption { 51 public: 52 static void AttachTabHelpers(content::WebContents* contents) { 53 BrowserTabContents::AttachTabHelpers(contents); 54 } 55}; 56 57namespace { 58 59// Returns true if the specified Browser can open tabs. Not all Browsers support 60// multiple tabs, such as app frames and popups. This function returns false for 61// those types of Browser. 62bool WindowCanOpenTabs(Browser* browser) { 63 return browser->CanSupportWindowFeature(Browser::FEATURE_TABSTRIP) || 64 browser->tab_strip_model()->empty(); 65} 66 67// Finds an existing Browser compatible with |profile|, making a new one if no 68// such Browser is located. 69Browser* GetOrCreateBrowser(Profile* profile, 70 chrome::HostDesktopType host_desktop_type) { 71 Browser* browser = chrome::FindTabbedBrowser(profile, false, 72 host_desktop_type); 73 return browser ? browser : new Browser( 74 Browser::CreateParams(profile, host_desktop_type)); 75} 76 77// Change some of the navigation parameters based on the particular URL. 78// Currently this applies to some chrome:// pages which we always want to open 79// in a non-incognito window. Note that even though a ChromeOS guest session is 80// technically an incognito window, these URLs are allowed. 81// Returns true on success. Otherwise, if changing params leads the browser into 82// an erroneous state, returns false. 83bool AdjustNavigateParamsForURL(chrome::NavigateParams* params) { 84 if (params->target_contents != NULL || 85 chrome::IsURLAllowedInIncognito(params->url, 86 params->initiating_profile) || 87 params->initiating_profile->IsGuestSession()) { 88 return true; 89 } 90 91 Profile* profile = params->initiating_profile; 92 93 if (profile->IsOffTheRecord() || params->disposition == OFF_THE_RECORD) { 94 profile = profile->GetOriginalProfile(); 95 96 // If incognito is forced, we punt. 97 PrefService* prefs = profile->GetPrefs(); 98 if (prefs && IncognitoModePrefs::GetAvailability(prefs) == 99 IncognitoModePrefs::FORCED) { 100 return false; 101 } 102 103 params->disposition = SINGLETON_TAB; 104 params->browser = 105 chrome::FindOrCreateTabbedBrowser(profile, params->host_desktop_type); 106 params->window_action = chrome::NavigateParams::SHOW_WINDOW; 107 } 108 109 return true; 110} 111 112// Returns a Browser that can host the navigation or tab addition specified in 113// |params|. This might just return the same Browser specified in |params|, or 114// some other if that Browser is deemed incompatible. 115Browser* GetBrowserForDisposition(chrome::NavigateParams* params) { 116 // If no source WebContents was specified, we use the selected one from 117 // the target browser. This must happen first, before 118 // GetBrowserForDisposition() has a chance to replace |params->browser| with 119 // another one. 120 if (!params->source_contents && params->browser) { 121 params->source_contents = 122 params->browser->tab_strip_model()->GetActiveWebContents(); 123 } 124 125 Profile* profile = params->initiating_profile; 126 127 switch (params->disposition) { 128 case CURRENT_TAB: 129 if (params->browser) 130 return params->browser; 131 // Find a compatible window and re-execute this command in it. Otherwise 132 // re-run with NEW_WINDOW. 133 return GetOrCreateBrowser(profile, params->host_desktop_type); 134 case SINGLETON_TAB: 135 case NEW_FOREGROUND_TAB: 136 case NEW_BACKGROUND_TAB: 137 // See if we can open the tab in the window this navigator is bound to. 138 if (params->browser && WindowCanOpenTabs(params->browser)) 139 return params->browser; 140 // Find a compatible window and re-execute this command in it. Otherwise 141 // re-run with NEW_WINDOW. 142 return GetOrCreateBrowser(profile, params->host_desktop_type); 143 case NEW_POPUP: { 144 // Make a new popup window. 145 // Coerce app-style if |source| represents an app. 146 std::string app_name; 147 if (!params->extension_app_id.empty()) { 148 app_name = web_app::GenerateApplicationNameFromExtensionId( 149 params->extension_app_id); 150 } else if (!params->browser->app_name().empty()) { 151 app_name = params->browser->app_name(); 152 } else if (params->source_contents) { 153 extensions::TabHelper* extensions_tab_helper = 154 extensions::TabHelper::FromWebContents(params->source_contents); 155 if (extensions_tab_helper && extensions_tab_helper->is_app()) { 156 app_name = web_app::GenerateApplicationNameFromExtensionId( 157 extensions_tab_helper->extension_app()->id()); 158 } 159 } 160 if (app_name.empty()) { 161 Browser::CreateParams browser_params( 162 Browser::TYPE_POPUP, profile, params->host_desktop_type); 163 browser_params.initial_bounds = params->window_bounds; 164 return new Browser(browser_params); 165 } 166 167 return new Browser(Browser::CreateParams::CreateForApp( 168 Browser::TYPE_POPUP, app_name, params->window_bounds, profile, 169 params->host_desktop_type)); 170 } 171 case NEW_WINDOW: { 172 // Make a new normal browser window. 173 return new Browser(Browser::CreateParams(profile, 174 params->host_desktop_type)); 175 } 176 case OFF_THE_RECORD: 177 // Make or find an incognito window. 178 return GetOrCreateBrowser(profile->GetOffTheRecordProfile(), 179 params->host_desktop_type); 180 // The following types all result in no navigation. 181 case SUPPRESS_OPEN: 182 case SAVE_TO_DISK: 183 case IGNORE_ACTION: 184 return NULL; 185 default: 186 NOTREACHED(); 187 } 188 return NULL; 189} 190 191// Fix disposition and other parameter values depending on prevailing 192// conditions. 193void NormalizeDisposition(chrome::NavigateParams* params) { 194 // Calculate the WindowOpenDisposition if necessary. 195 if (params->browser->tab_strip_model()->empty() && 196 (params->disposition == NEW_BACKGROUND_TAB || 197 params->disposition == CURRENT_TAB || 198 params->disposition == SINGLETON_TAB)) { 199 params->disposition = NEW_FOREGROUND_TAB; 200 } 201 if (params->browser->profile()->IsOffTheRecord() && 202 params->disposition == OFF_THE_RECORD) { 203 params->disposition = NEW_FOREGROUND_TAB; 204 } 205 if (!params->source_contents && params->disposition == CURRENT_TAB) 206 params->disposition = NEW_FOREGROUND_TAB; 207 208 switch (params->disposition) { 209 case NEW_BACKGROUND_TAB: 210 // Disposition trumps add types. ADD_ACTIVE is a default, so we need to 211 // remove it if disposition implies the tab is going to open in the 212 // background. 213 params->tabstrip_add_types &= ~TabStripModel::ADD_ACTIVE; 214 break; 215 216 case NEW_WINDOW: 217 case NEW_POPUP: 218 // Code that wants to open a new window typically expects it to be shown 219 // automatically. 220 if (params->window_action == chrome::NavigateParams::NO_ACTION) 221 params->window_action = chrome::NavigateParams::SHOW_WINDOW; 222 // Fall-through. 223 case NEW_FOREGROUND_TAB: 224 case SINGLETON_TAB: 225 params->tabstrip_add_types |= TabStripModel::ADD_ACTIVE; 226 break; 227 228 default: 229 break; 230 } 231} 232 233// Obtain the profile used by the code that originated the Navigate() request. 234Profile* GetSourceProfile(chrome::NavigateParams* params) { 235 if (params->source_contents) { 236 return Profile::FromBrowserContext( 237 params->source_contents->GetBrowserContext()); 238 } 239 240 return params->initiating_profile; 241} 242 243void LoadURLInContents(WebContents* target_contents, 244 const GURL& url, 245 chrome::NavigateParams* params) { 246 content::NavigationController::LoadURLParams load_url_params(url); 247 load_url_params.referrer = params->referrer; 248 load_url_params.transition_type = params->transition; 249 load_url_params.extra_headers = params->extra_headers; 250 load_url_params.is_cross_site_redirect = params->is_cross_site_redirect; 251 252 if (params->transferred_global_request_id != GlobalRequestID()) { 253 load_url_params.is_renderer_initiated = params->is_renderer_initiated; 254 load_url_params.transferred_global_request_id = 255 params->transferred_global_request_id; 256 } else if (params->is_renderer_initiated) { 257 load_url_params.is_renderer_initiated = true; 258 } 259 target_contents->GetController().LoadURLWithParams(load_url_params); 260} 261 262// This class makes sure the Browser object held in |params| is made visible 263// by the time it goes out of scope, provided |params| wants it to be shown. 264class ScopedBrowserDisplayer { 265 public: 266 explicit ScopedBrowserDisplayer(chrome::NavigateParams* params) 267 : params_(params) { 268 } 269 ~ScopedBrowserDisplayer() { 270 if (params_->window_action == chrome::NavigateParams::SHOW_WINDOW_INACTIVE) 271 params_->browser->window()->ShowInactive(); 272 else if (params_->window_action == chrome::NavigateParams::SHOW_WINDOW) 273 params_->browser->window()->Show(); 274 } 275 private: 276 chrome::NavigateParams* params_; 277 DISALLOW_COPY_AND_ASSIGN(ScopedBrowserDisplayer); 278}; 279 280// This class manages the lifetime of a WebContents created by the 281// Navigate() function. When Navigate() creates a WebContents for a URL, 282// an instance of this class takes ownership of it via TakeOwnership() until the 283// WebContents is added to a tab strip at which time ownership is 284// relinquished via ReleaseOwnership(). If this object goes out of scope without 285// being added to a tab strip, the created WebContents is deleted to 286// avoid a leak and the params->target_contents field is set to NULL. 287class ScopedTargetContentsOwner { 288 public: 289 explicit ScopedTargetContentsOwner(chrome::NavigateParams* params) 290 : params_(params) { 291 } 292 ~ScopedTargetContentsOwner() { 293 if (target_contents_owner_.get()) 294 params_->target_contents = NULL; 295 } 296 297 // Assumes ownership of |params_|' target_contents until ReleaseOwnership 298 // is called. 299 void TakeOwnership() { 300 target_contents_owner_.reset(params_->target_contents); 301 } 302 303 // Relinquishes ownership of |params_|' target_contents. 304 WebContents* ReleaseOwnership() { 305 return target_contents_owner_.release(); 306 } 307 308 private: 309 chrome::NavigateParams* params_; 310 scoped_ptr<WebContents> target_contents_owner_; 311 DISALLOW_COPY_AND_ASSIGN(ScopedTargetContentsOwner); 312}; 313 314content::WebContents* CreateTargetContents(const chrome::NavigateParams& params, 315 const GURL& url) { 316 WebContents::CreateParams create_params( 317 params.browser->profile(), 318 tab_util::GetSiteInstanceForNewTab(params.browser->profile(), url)); 319 if (params.source_contents) { 320 create_params.initial_size = 321 params.source_contents->GetView()->GetContainerSize(); 322 } 323#if defined(USE_AURA) 324 if (params.browser->window() && 325 params.browser->window()->GetNativeWindow()) { 326 create_params.context = 327 params.browser->window()->GetNativeWindow(); 328 } 329#endif 330 331 content::WebContents* target_contents = WebContents::Create(create_params); 332 // New tabs can have WebUI URLs that will make calls back to arbitrary 333 // tab helpers, so the entire set of tab helpers needs to be set up 334 // immediately. 335 BrowserNavigatorWebContentsAdoption::AttachTabHelpers(target_contents); 336 extensions::TabHelper::FromWebContents(target_contents)-> 337 SetExtensionAppById(params.extension_app_id); 338 // TODO(sky): Figure out why this is needed. Without it we seem to get 339 // failures in startup tests. 340 // By default, content believes it is not hidden. When adding contents 341 // in the background, tell it that it's hidden. 342 if ((params.tabstrip_add_types & TabStripModel::ADD_ACTIVE) == 0) { 343 // TabStripModel::AddWebContents invokes WasHidden if not foreground. 344 target_contents->WasHidden(); 345 } 346 return target_contents; 347} 348 349// If a prerendered page exists for |url|, replace the page at |target_contents| 350// with it. 351bool SwapInPrerender(WebContents* target_contents, const GURL& url) { 352 prerender::PrerenderManager* prerender_manager = 353 prerender::PrerenderManagerFactory::GetForProfile( 354 Profile::FromBrowserContext(target_contents->GetBrowserContext())); 355 return prerender_manager && 356 prerender_manager->MaybeUsePrerenderedPage(target_contents, url); 357} 358 359bool SwapInInstantNTP(chrome::NavigateParams* params, 360 const GURL& url, 361 content::WebContents* source_contents) { 362 chrome::BrowserInstantController* instant = 363 params->browser->instant_controller(); 364 return instant && instant->MaybeSwapInInstantNTPContents( 365 url, source_contents, ¶ms->target_contents); 366} 367 368} // namespace 369 370namespace chrome { 371 372NavigateParams::NavigateParams(Browser* a_browser, 373 const GURL& a_url, 374 content::PageTransition a_transition) 375 : url(a_url), 376 target_contents(NULL), 377 source_contents(NULL), 378 disposition(CURRENT_TAB), 379 transition(a_transition), 380 is_renderer_initiated(false), 381 tabstrip_index(-1), 382 tabstrip_add_types(TabStripModel::ADD_ACTIVE), 383 window_action(NO_ACTION), 384 user_gesture(true), 385 path_behavior(RESPECT), 386 ref_behavior(IGNORE_REF), 387 browser(a_browser), 388 initiating_profile(NULL), 389 is_cross_site_redirect(false) { 390 if (a_browser) 391 host_desktop_type = a_browser->host_desktop_type(); 392 else 393 host_desktop_type = chrome::HOST_DESKTOP_TYPE_NATIVE; 394 } 395 396NavigateParams::NavigateParams(Browser* a_browser, 397 WebContents* a_target_contents) 398 : target_contents(a_target_contents), 399 source_contents(NULL), 400 disposition(CURRENT_TAB), 401 transition(content::PAGE_TRANSITION_LINK), 402 is_renderer_initiated(false), 403 tabstrip_index(-1), 404 tabstrip_add_types(TabStripModel::ADD_ACTIVE), 405 window_action(NO_ACTION), 406 user_gesture(true), 407 path_behavior(RESPECT), 408 ref_behavior(IGNORE_REF), 409 browser(a_browser), 410 initiating_profile(NULL), 411 is_cross_site_redirect(false) { 412 if (a_browser) 413 host_desktop_type = a_browser->host_desktop_type(); 414 else 415 host_desktop_type = chrome::HOST_DESKTOP_TYPE_NATIVE; 416 } 417 418NavigateParams::NavigateParams(Profile* a_profile, 419 const GURL& a_url, 420 content::PageTransition a_transition) 421 : url(a_url), 422 target_contents(NULL), 423 source_contents(NULL), 424 disposition(NEW_FOREGROUND_TAB), 425 transition(a_transition), 426 is_renderer_initiated(false), 427 tabstrip_index(-1), 428 tabstrip_add_types(TabStripModel::ADD_ACTIVE), 429 window_action(SHOW_WINDOW), 430 user_gesture(true), 431 path_behavior(RESPECT), 432 ref_behavior(IGNORE_REF), 433 browser(NULL), 434 initiating_profile(a_profile), 435 host_desktop_type(chrome::HOST_DESKTOP_TYPE_NATIVE), 436 is_cross_site_redirect(false) {} 437 438NavigateParams::~NavigateParams() {} 439 440void FillNavigateParamsFromOpenURLParams(chrome::NavigateParams* nav_params, 441 const content::OpenURLParams& params) { 442 nav_params->referrer = params.referrer; 443 nav_params->extra_headers = params.extra_headers; 444 nav_params->disposition = params.disposition; 445 nav_params->override_encoding = params.override_encoding; 446 nav_params->is_renderer_initiated = params.is_renderer_initiated; 447 nav_params->transferred_global_request_id = 448 params.transferred_global_request_id; 449 nav_params->is_cross_site_redirect = params.is_cross_site_redirect; 450} 451 452void Navigate(NavigateParams* params) { 453 Browser* source_browser = params->browser; 454 if (source_browser) 455 params->initiating_profile = source_browser->profile(); 456 DCHECK(params->initiating_profile); 457 458 if (!AdjustNavigateParamsForURL(params)) 459 return; 460 461 ExtensionService* service = params->initiating_profile->GetExtensionService(); 462 if (service) 463 service->ShouldBlockUrlInBrowserTab(¶ms->url); 464 465 // The browser window may want to adjust the disposition. 466 if (params->disposition == NEW_POPUP && 467 source_browser && 468 source_browser->window()) { 469 params->disposition = 470 source_browser->window()->GetDispositionForPopupBounds( 471 params->window_bounds); 472 } 473 474 params->browser = GetBrowserForDisposition(params); 475 if (!params->browser) 476 return; 477 478 // Navigate() must not return early after this point. 479 480 if (GetSourceProfile(params) != params->browser->profile()) { 481 // A tab is being opened from a link from a different profile, we must reset 482 // source information that may cause state to be shared. 483 params->source_contents = NULL; 484 params->referrer = content::Referrer(); 485 } 486 487 // Make sure the Browser is shown if params call for it. 488 ScopedBrowserDisplayer displayer(params); 489 490 // Makes sure any WebContents created by this function is destroyed if 491 // not properly added to a tab strip. 492 ScopedTargetContentsOwner target_contents_owner(params); 493 494 // Some dispositions need coercion to base types. 495 NormalizeDisposition(params); 496 497 // If a new window has been created, it needs to be displayed. 498 if (params->window_action == NavigateParams::NO_ACTION && 499 source_browser != params->browser && 500 params->browser->tab_strip_model()->empty()) { 501 params->window_action = NavigateParams::SHOW_WINDOW; 502 } 503 504 // If we create a popup window from a non user-gesture, don't activate it. 505 if (params->window_action == NavigateParams::SHOW_WINDOW && 506 params->disposition == NEW_POPUP && 507 params->user_gesture == false) { 508 params->window_action = NavigateParams::SHOW_WINDOW_INACTIVE; 509 } 510 511 // Determine if the navigation was user initiated. If it was, we need to 512 // inform the target WebContents, and we may need to update the UI. 513 content::PageTransition base_transition = 514 content::PageTransitionStripQualifier(params->transition); 515 bool user_initiated = 516 params->transition & content::PAGE_TRANSITION_FROM_ADDRESS_BAR || 517 base_transition == content::PAGE_TRANSITION_TYPED || 518 base_transition == content::PAGE_TRANSITION_AUTO_BOOKMARK || 519 base_transition == content::PAGE_TRANSITION_GENERATED || 520 base_transition == content::PAGE_TRANSITION_AUTO_TOPLEVEL || 521 base_transition == content::PAGE_TRANSITION_RELOAD || 522 base_transition == content::PAGE_TRANSITION_KEYWORD; 523 524 // Check if this is a singleton tab that already exists 525 int singleton_index = chrome::GetIndexOfSingletonTab(params); 526 527 // Did we use Instant's NTP contents? 528 bool swapped_in_instant = false; 529 530 // If no target WebContents was specified, we need to construct one if 531 // we are supposed to target a new tab; unless it's a singleton that already 532 // exists. 533 if (!params->target_contents && singleton_index < 0) { 534 GURL url; 535 if (params->url.is_empty()) { 536 url = params->browser->profile()->GetHomePage(); 537 params->transition = content::PageTransitionFromInt( 538 params->transition | content::PAGE_TRANSITION_HOME_PAGE); 539 } else { 540 url = params->url; 541 } 542 543 if (params->disposition != CURRENT_TAB) { 544 swapped_in_instant = SwapInInstantNTP(params, url, NULL); 545 if (!swapped_in_instant) 546 params->target_contents = CreateTargetContents(*params, url); 547 548 // This function takes ownership of |params->target_contents| until it 549 // is added to a TabStripModel. 550 target_contents_owner.TakeOwnership(); 551 } else { 552 // ... otherwise if we're loading in the current tab, the target is the 553 // same as the source. 554 DCHECK(params->source_contents); 555 swapped_in_instant = SwapInInstantNTP(params, url, 556 params->source_contents); 557 if (!swapped_in_instant) 558 params->target_contents = params->source_contents; 559 DCHECK(params->target_contents); 560 } 561 562 if (user_initiated) 563 params->target_contents->UserGestureDone(); 564 565 if (!swapped_in_instant) { 566 if (SwapInPrerender(params->target_contents, url)) 567 return; 568 569 // Try to handle non-navigational URLs that popup dialogs and such, these 570 // should not actually navigate. 571 if (!HandleNonNavigationAboutURL(url)) { 572 // Perform the actual navigation, tracking whether it came from the 573 // renderer. 574 575 LoadURLInContents(params->target_contents, url, params); 576 } 577 } 578 } else { 579 // |target_contents| was specified non-NULL, and so we assume it has already 580 // been navigated appropriately. We need to do nothing more other than 581 // add it to the appropriate tabstrip. 582 } 583 584 // If the user navigated from the omnibox, and the selected tab is going to 585 // lose focus, then make sure the focus for the source tab goes away from the 586 // omnibox. 587 if (params->source_contents && 588 (params->disposition == NEW_FOREGROUND_TAB || 589 params->disposition == NEW_WINDOW) && 590 (params->tabstrip_add_types & TabStripModel::ADD_INHERIT_OPENER)) 591 params->source_contents->GetView()->Focus(); 592 593 if (params->source_contents == params->target_contents || 594 (swapped_in_instant && params->disposition == CURRENT_TAB)) { 595 // The navigation occurred in the source tab. 596 params->browser->UpdateUIForNavigationInTab(params->target_contents, 597 params->transition, 598 user_initiated); 599 } else if (singleton_index == -1) { 600 // If some non-default value is set for the index, we should tell the 601 // TabStripModel to respect it. 602 if (params->tabstrip_index != -1) 603 params->tabstrip_add_types |= TabStripModel::ADD_FORCE_INDEX; 604 605 // The navigation should insert a new tab into the target Browser. 606 params->browser->tab_strip_model()->AddWebContents( 607 params->target_contents, 608 params->tabstrip_index, 609 params->transition, 610 params->tabstrip_add_types); 611 // Now that the |params->target_contents| is safely owned by the target 612 // Browser's TabStripModel, we can release ownership. 613 target_contents_owner.ReleaseOwnership(); 614 } 615 616 if (singleton_index >= 0) { 617 WebContents* target = 618 params->browser->tab_strip_model()->GetWebContentsAt(singleton_index); 619 620 if (target->IsCrashed()) { 621 target->GetController().Reload(true); 622 } else if (params->path_behavior == NavigateParams::IGNORE_AND_NAVIGATE && 623 target->GetURL() != params->url) { 624 LoadURLInContents(target, params->url, params); 625 } 626 627 // If the singleton tab isn't already selected, select it. 628 if (params->source_contents != params->target_contents) { 629 params->browser->tab_strip_model()->ActivateTabAt(singleton_index, 630 user_initiated); 631 } 632 } 633 634 if (params->disposition != CURRENT_TAB) { 635 content::NotificationService::current()->Notify( 636 chrome::NOTIFICATION_TAB_ADDED, 637 content::Source<content::WebContentsDelegate>(params->browser), 638 content::Details<WebContents>(params->target_contents)); 639 } 640} 641 642bool IsURLAllowedInIncognito(const GURL& url, 643 content::BrowserContext* browser_context) { 644 // Most URLs are allowed in incognito; the following are exceptions. 645 // chrome://extensions is on the list because it redirects to 646 // chrome://settings. 647 if (url.scheme() == chrome::kChromeUIScheme && 648 (url.host() == chrome::kChromeUISettingsHost || 649 url.host() == chrome::kChromeUISettingsFrameHost || 650 url.host() == chrome::kChromeUIExtensionsHost || 651 url.host() == chrome::kChromeUIBookmarksHost || 652 url.host() == chrome::kChromeUISyncPromoHost || 653 url.host() == chrome::kChromeUIUberHost)) { 654 return false; 655 } 656 657 GURL rewritten_url = url; 658 bool reverse_on_redirect = false; 659 content::BrowserURLHandler::GetInstance()->RewriteURLIfNecessary( 660 &rewritten_url, browser_context, &reverse_on_redirect); 661 662 // Some URLs are mapped to uber subpages. Do not allow them in incognito. 663 return !(rewritten_url.scheme() == chrome::kChromeUIScheme && 664 rewritten_url.host() == chrome::kChromeUIUberHost); 665} 666 667} // namespace chrome 668