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