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.
5 #include "chrome/browser/ui/browser_navigator.h"
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/prefs/incognito_mode_prefs.h"
16 #include "chrome/browser/prerender/prerender_manager.h"
17 #include "chrome/browser/prerender/prerender_manager_factory.h"
18 #include "chrome/browser/profiles/profile.h"
19 #include "chrome/browser/tab_contents/tab_util.h"
20 #include "chrome/browser/task_management/web_contents_tags.h"
21 #include "chrome/browser/ui/browser.h"
22 #include "chrome/browser/ui/browser_finder.h"
23 #include "chrome/browser/ui/browser_instant_controller.h"
24 #include "chrome/browser/ui/browser_window.h"
25 #include "chrome/browser/ui/host_desktop.h"
26 #include "chrome/browser/ui/location_bar/location_bar.h"
27 #include "chrome/browser/ui/search/instant_search_prerenderer.h"
28 #include "chrome/browser/ui/singleton_tabs.h"
29 #include "chrome/browser/ui/status_bubble.h"
30 #include "chrome/browser/ui/tab_helpers.h"
31 #include "chrome/browser/ui/tabs/tab_strip_model.h"
32 #include "chrome/common/url_constants.h"
33 #include "content/public/browser/browser_url_handler.h"
34 #include "content/public/browser/navigation_entry.h"
35 #include "content/public/browser/notification_service.h"
36 #include "content/public/browser/render_view_host.h"
37 #include "content/public/browser/web_contents.h"
40 #include "chrome/browser/ui/ash/multi_user/multi_user_window_manager.h"
44 #include "ui/aura/window.h"
47 #if defined(ENABLE_EXTENSIONS)
48 #include "chrome/browser/extensions/tab_helper.h"
49 #include "chrome/browser/web_applications/web_app.h"
50 #include "extensions/browser/extension_registry.h"
51 #include "extensions/common/extension.h"
52 #include "extensions/common/extension_set.h"
55 using content::GlobalRequestID
;
56 using content::NavigationController
;
57 using content::WebContents
;
59 class BrowserNavigatorWebContentsAdoption
{
61 static void AttachTabHelpers(content::WebContents
* contents
) {
62 TabHelpers::AttachTabHelpers(contents
);
64 // Make the tab show up in the task manager.
65 task_management::WebContentsTags::CreateForTabContents(contents
);
71 // Returns true if the specified Browser can open tabs. Not all Browsers support
72 // multiple tabs, such as app frames and popups. This function returns false for
73 // those types of Browser.
74 bool WindowCanOpenTabs(Browser
* browser
) {
75 return browser
->CanSupportWindowFeature(Browser::FEATURE_TABSTRIP
) ||
76 browser
->tab_strip_model()->empty();
79 // Finds an existing Browser compatible with |profile|, making a new one if no
80 // such Browser is located.
81 Browser
* GetOrCreateBrowser(Profile
* profile
,
82 chrome::HostDesktopType host_desktop_type
) {
83 Browser
* browser
= chrome::FindTabbedBrowser(profile
, false,
85 return browser
? browser
: new Browser(
86 Browser::CreateParams(profile
, host_desktop_type
));
89 // Change some of the navigation parameters based on the particular URL.
90 // Currently this applies to some chrome:// pages which we always want to open
91 // in a non-incognito window. Note that even though a ChromeOS guest session is
92 // technically an incognito window, these URLs are allowed.
93 // Returns true on success. Otherwise, if changing params leads the browser into
94 // an erroneous state, returns false.
95 bool AdjustNavigateParamsForURL(chrome::NavigateParams
* params
) {
96 if (params
->target_contents
!= NULL
||
97 chrome::IsURLAllowedInIncognito(params
->url
,
98 params
->initiating_profile
) ||
99 params
->initiating_profile
->IsGuestSession()) {
103 Profile
* profile
= params
->initiating_profile
;
105 if (profile
->IsOffTheRecord() || params
->disposition
== OFF_THE_RECORD
) {
106 profile
= profile
->GetOriginalProfile();
108 // If incognito is forced, we punt.
109 PrefService
* prefs
= profile
->GetPrefs();
110 if (prefs
&& IncognitoModePrefs::GetAvailability(prefs
) ==
111 IncognitoModePrefs::FORCED
) {
115 params
->disposition
= SINGLETON_TAB
;
116 params
->browser
= GetOrCreateBrowser(profile
, params
->host_desktop_type
);
117 params
->window_action
= chrome::NavigateParams::SHOW_WINDOW
;
123 // Returns a Browser that can host the navigation or tab addition specified in
124 // |params|. This might just return the same Browser specified in |params|, or
125 // some other if that Browser is deemed incompatible.
126 Browser
* GetBrowserForDisposition(chrome::NavigateParams
* params
) {
127 // If no source WebContents was specified, we use the selected one from
128 // the target browser. This must happen first, before
129 // GetBrowserForDisposition() has a chance to replace |params->browser| with
131 if (!params
->source_contents
&& params
->browser
) {
132 params
->source_contents
=
133 params
->browser
->tab_strip_model()->GetActiveWebContents();
136 Profile
* profile
= params
->initiating_profile
;
138 switch (params
->disposition
) {
141 return params
->browser
;
142 // Find a compatible window and re-execute this command in it. Otherwise
143 // re-run with NEW_WINDOW.
144 return GetOrCreateBrowser(profile
, params
->host_desktop_type
);
146 case NEW_FOREGROUND_TAB
:
147 case NEW_BACKGROUND_TAB
:
148 // See if we can open the tab in the window this navigator is bound to.
149 if (params
->browser
&& WindowCanOpenTabs(params
->browser
))
150 return params
->browser
;
151 // Find a compatible window and re-execute this command in it. Otherwise
152 // re-run with NEW_WINDOW.
153 return GetOrCreateBrowser(profile
, params
->host_desktop_type
);
155 // Make a new popup window.
156 // Coerce app-style if |source| represents an app.
157 std::string app_name
;
158 #if defined(ENABLE_EXTENSIONS)
159 if (!params
->extension_app_id
.empty()) {
160 app_name
= web_app::GenerateApplicationNameFromExtensionId(
161 params
->extension_app_id
);
162 } else if (params
->browser
&& !params
->browser
->app_name().empty()) {
163 app_name
= params
->browser
->app_name();
164 } else if (params
->source_contents
) {
165 extensions::TabHelper
* extensions_tab_helper
=
166 extensions::TabHelper::FromWebContents(params
->source_contents
);
167 if (extensions_tab_helper
&& extensions_tab_helper
->is_app()) {
168 app_name
= web_app::GenerateApplicationNameFromExtensionId(
169 extensions_tab_helper
->extension_app()->id());
173 if (app_name
.empty()) {
174 Browser::CreateParams
browser_params(
175 Browser::TYPE_POPUP
, profile
, params
->host_desktop_type
);
176 browser_params
.trusted_source
= params
->trusted_source
;
177 browser_params
.initial_bounds
= params
->window_bounds
;
178 return new Browser(browser_params
);
181 return new Browser(Browser::CreateParams::CreateForApp(
183 params
->trusted_source
,
184 params
->window_bounds
,
186 params
->host_desktop_type
));
189 // Make a new normal browser window.
190 return new Browser(Browser::CreateParams(profile
,
191 params
->host_desktop_type
));
194 // Make or find an incognito window.
195 return GetOrCreateBrowser(profile
->GetOffTheRecordProfile(),
196 params
->host_desktop_type
);
197 // The following types all result in no navigation.
208 // Fix disposition and other parameter values depending on prevailing
210 void NormalizeDisposition(chrome::NavigateParams
* params
) {
211 // Calculate the WindowOpenDisposition if necessary.
212 if (params
->browser
->tab_strip_model()->empty() &&
213 (params
->disposition
== NEW_BACKGROUND_TAB
||
214 params
->disposition
== CURRENT_TAB
||
215 params
->disposition
== SINGLETON_TAB
)) {
216 params
->disposition
= NEW_FOREGROUND_TAB
;
218 if (params
->browser
->profile()->IsOffTheRecord() &&
219 params
->disposition
== OFF_THE_RECORD
) {
220 params
->disposition
= NEW_FOREGROUND_TAB
;
222 if (!params
->source_contents
&& params
->disposition
== CURRENT_TAB
)
223 params
->disposition
= NEW_FOREGROUND_TAB
;
225 switch (params
->disposition
) {
226 case NEW_BACKGROUND_TAB
:
227 // Disposition trumps add types. ADD_ACTIVE is a default, so we need to
228 // remove it if disposition implies the tab is going to open in the
230 params
->tabstrip_add_types
&= ~TabStripModel::ADD_ACTIVE
;
235 // Code that wants to open a new window typically expects it to be shown
237 if (params
->window_action
== chrome::NavigateParams::NO_ACTION
)
238 params
->window_action
= chrome::NavigateParams::SHOW_WINDOW
;
240 case NEW_FOREGROUND_TAB
:
242 params
->tabstrip_add_types
|= TabStripModel::ADD_ACTIVE
;
250 // Obtain the profile used by the code that originated the Navigate() request.
251 Profile
* GetSourceProfile(chrome::NavigateParams
* params
) {
252 if (params
->source_contents
) {
253 return Profile::FromBrowserContext(
254 params
->source_contents
->GetBrowserContext());
257 return params
->initiating_profile
;
260 void LoadURLInContents(WebContents
* target_contents
,
262 chrome::NavigateParams
* params
) {
263 NavigationController::LoadURLParams
load_url_params(url
);
264 load_url_params
.source_site_instance
= params
->source_site_instance
;
265 load_url_params
.referrer
= params
->referrer
;
266 load_url_params
.frame_tree_node_id
= params
->frame_tree_node_id
;
267 load_url_params
.redirect_chain
= params
->redirect_chain
;
268 load_url_params
.transition_type
= params
->transition
;
269 load_url_params
.extra_headers
= params
->extra_headers
;
270 load_url_params
.should_replace_current_entry
=
271 params
->should_replace_current_entry
;
273 if (params
->transferred_global_request_id
!= GlobalRequestID()) {
274 load_url_params
.is_renderer_initiated
= params
->is_renderer_initiated
;
275 load_url_params
.transferred_global_request_id
=
276 params
->transferred_global_request_id
;
277 } else if (params
->is_renderer_initiated
) {
278 load_url_params
.is_renderer_initiated
= true;
281 // Only allows the browser-initiated navigation to use POST.
282 if (params
->uses_post
&& !params
->is_renderer_initiated
) {
283 load_url_params
.load_type
=
284 NavigationController::LOAD_TYPE_BROWSER_INITIATED_HTTP_POST
;
285 load_url_params
.browser_initiated_post_data
=
286 params
->browser_initiated_post_data
;
288 target_contents
->GetController().LoadURLWithParams(load_url_params
);
291 // This class makes sure the Browser object held in |params| is made visible
292 // by the time it goes out of scope, provided |params| wants it to be shown.
293 class ScopedBrowserShower
{
295 explicit ScopedBrowserShower(chrome::NavigateParams
* params
)
298 ~ScopedBrowserShower() {
299 if (params_
->window_action
==
300 chrome::NavigateParams::SHOW_WINDOW_INACTIVE
) {
301 params_
->browser
->window()->ShowInactive();
302 } else if (params_
->window_action
== chrome::NavigateParams::SHOW_WINDOW
) {
303 params_
->browser
->window()->Show();
304 // If a user gesture opened a popup window, focus the contents.
305 if (params_
->user_gesture
&& params_
->disposition
== NEW_POPUP
&&
306 params_
->target_contents
) {
307 params_
->target_contents
->Focus();
313 chrome::NavigateParams
* params_
;
314 DISALLOW_COPY_AND_ASSIGN(ScopedBrowserShower
);
317 // This class manages the lifetime of a WebContents created by the
318 // Navigate() function. When Navigate() creates a WebContents for a URL,
319 // an instance of this class takes ownership of it via TakeOwnership() until the
320 // WebContents is added to a tab strip at which time ownership is
321 // relinquished via ReleaseOwnership(). If this object goes out of scope without
322 // being added to a tab strip, the created WebContents is deleted to
323 // avoid a leak and the params->target_contents field is set to NULL.
324 class ScopedTargetContentsOwner
{
326 explicit ScopedTargetContentsOwner(chrome::NavigateParams
* params
)
329 ~ScopedTargetContentsOwner() {
330 if (target_contents_owner_
.get())
331 params_
->target_contents
= NULL
;
334 // Assumes ownership of |params_|' target_contents until ReleaseOwnership
336 void TakeOwnership() {
337 target_contents_owner_
.reset(params_
->target_contents
);
340 // Relinquishes ownership of |params_|' target_contents.
341 WebContents
* ReleaseOwnership() {
342 return target_contents_owner_
.release();
346 chrome::NavigateParams
* params_
;
347 scoped_ptr
<WebContents
> target_contents_owner_
;
348 DISALLOW_COPY_AND_ASSIGN(ScopedTargetContentsOwner
);
351 content::WebContents
* CreateTargetContents(const chrome::NavigateParams
& params
,
353 WebContents::CreateParams
create_params(
354 params
.browser
->profile(),
355 tab_util::GetSiteInstanceForNewTab(params
.browser
->profile(), url
));
356 if (params
.source_contents
) {
357 create_params
.initial_size
=
358 params
.source_contents
->GetContainerBounds().size();
359 create_params
.created_with_opener
= params
.created_with_opener
;
361 if (params
.disposition
== NEW_BACKGROUND_TAB
)
362 create_params
.initially_hidden
= true;
364 #if defined(USE_AURA)
365 if (params
.browser
->window() &&
366 params
.browser
->window()->GetNativeWindow()) {
367 create_params
.context
=
368 params
.browser
->window()->GetNativeWindow();
372 WebContents
* target_contents
= WebContents::Create(create_params
);
374 // New tabs can have WebUI URLs that will make calls back to arbitrary
375 // tab helpers, so the entire set of tab helpers needs to be set up
377 BrowserNavigatorWebContentsAdoption::AttachTabHelpers(target_contents
);
378 #if defined(ENABLE_EXTENSIONS)
379 extensions::TabHelper::FromWebContents(target_contents
)->
380 SetExtensionAppById(params
.extension_app_id
);
382 return target_contents
;
385 // If a prerendered page exists for |url|, replace the page at
386 // |params->target_contents| with it and update to point to the swapped-in
388 bool SwapInPrerender(const GURL
& url
, chrome::NavigateParams
* params
) {
390 Profile::FromBrowserContext(params
->target_contents
->GetBrowserContext());
391 InstantSearchPrerenderer
* prerenderer
=
392 InstantSearchPrerenderer::GetForProfile(profile
);
393 if (prerenderer
&& prerenderer
->UsePrerenderedPage(url
, params
))
396 prerender::PrerenderManager
* prerender_manager
=
397 prerender::PrerenderManagerFactory::GetForProfile(profile
);
398 return prerender_manager
&&
399 prerender_manager
->MaybeUsePrerenderedPage(url
, params
);
402 chrome::HostDesktopType
GetHostDesktop(Browser
* browser
) {
404 return browser
->host_desktop_type();
405 return chrome::GetActiveDesktop();
412 NavigateParams::NavigateParams(Browser
* a_browser
,
414 ui::PageTransition a_transition
)
416 frame_tree_node_id(-1),
418 target_contents(NULL
),
419 source_contents(NULL
),
420 disposition(CURRENT_TAB
),
421 trusted_source(false),
422 transition(a_transition
),
423 is_renderer_initiated(false),
425 tabstrip_add_types(TabStripModel::ADD_ACTIVE
),
426 window_action(NO_ACTION
),
428 path_behavior(RESPECT
),
429 ref_behavior(IGNORE_REF
),
431 initiating_profile(NULL
),
432 host_desktop_type(GetHostDesktop(a_browser
)),
433 should_replace_current_entry(false),
434 created_with_opener(false) {
437 NavigateParams::NavigateParams(Browser
* a_browser
,
438 WebContents
* a_target_contents
)
439 : frame_tree_node_id(-1),
441 target_contents(a_target_contents
),
442 source_contents(NULL
),
443 disposition(CURRENT_TAB
),
444 trusted_source(false),
445 transition(ui::PAGE_TRANSITION_LINK
),
446 is_renderer_initiated(false),
448 tabstrip_add_types(TabStripModel::ADD_ACTIVE
),
449 window_action(NO_ACTION
),
451 path_behavior(RESPECT
),
452 ref_behavior(IGNORE_REF
),
454 initiating_profile(NULL
),
455 host_desktop_type(GetHostDesktop(a_browser
)),
456 should_replace_current_entry(false),
457 created_with_opener(false) {
460 NavigateParams::NavigateParams(Profile
* a_profile
,
462 ui::PageTransition a_transition
)
464 frame_tree_node_id(-1),
466 target_contents(NULL
),
467 source_contents(NULL
),
468 disposition(NEW_FOREGROUND_TAB
),
469 trusted_source(false),
470 transition(a_transition
),
471 is_renderer_initiated(false),
473 tabstrip_add_types(TabStripModel::ADD_ACTIVE
),
474 window_action(SHOW_WINDOW
),
476 path_behavior(RESPECT
),
477 ref_behavior(IGNORE_REF
),
479 initiating_profile(a_profile
),
480 host_desktop_type(chrome::GetActiveDesktop()),
481 should_replace_current_entry(false),
482 created_with_opener(false) {
485 NavigateParams::~NavigateParams() {}
487 void FillNavigateParamsFromOpenURLParams(chrome::NavigateParams
* nav_params
,
488 const content::OpenURLParams
& params
) {
489 nav_params
->referrer
= params
.referrer
;
490 nav_params
->source_site_instance
= params
.source_site_instance
;
491 nav_params
->frame_tree_node_id
= params
.frame_tree_node_id
;
492 nav_params
->redirect_chain
= params
.redirect_chain
;
493 nav_params
->extra_headers
= params
.extra_headers
;
494 nav_params
->disposition
= params
.disposition
;
495 nav_params
->trusted_source
= false;
496 nav_params
->is_renderer_initiated
= params
.is_renderer_initiated
;
497 nav_params
->transferred_global_request_id
=
498 params
.transferred_global_request_id
;
499 nav_params
->should_replace_current_entry
=
500 params
.should_replace_current_entry
;
501 nav_params
->uses_post
= params
.uses_post
;
502 nav_params
->browser_initiated_post_data
= params
.browser_initiated_post_data
;
505 void Navigate(NavigateParams
* params
) {
506 Browser
* source_browser
= params
->browser
;
508 params
->initiating_profile
= source_browser
->profile();
509 DCHECK(params
->initiating_profile
);
511 if (!AdjustNavigateParamsForURL(params
))
514 #if defined(ENABLE_EXTENSIONS)
515 const extensions::Extension
* extension
=
516 extensions::ExtensionRegistry::Get(params
->initiating_profile
)->
517 enabled_extensions().GetExtensionOrAppByURL(params
->url
);
518 // Platform apps cannot navigate. Block the request.
519 if (extension
&& extension
->is_platform_app())
520 params
->url
= GURL(chrome::kExtensionInvalidRequestURL
);
523 // The browser window may want to adjust the disposition.
524 if (params
->disposition
== NEW_POPUP
&&
526 source_browser
->window()) {
527 params
->disposition
=
528 source_browser
->window()->GetDispositionForPopupBounds(
529 params
->window_bounds
);
532 params
->browser
= GetBrowserForDisposition(params
);
533 if (!params
->browser
)
537 if (source_browser
&& source_browser
!= params
->browser
) {
538 // When the newly created browser was spawned by a browser which visits
539 // another user's desktop, it should be shown on the same desktop as the
540 // originating one. (This is part of the desktop separation per profile).
541 MultiUserWindowManager
* manager
= MultiUserWindowManager::GetInstance();
542 // Some unit tests have no manager instantiated.
544 aura::Window
* src_window
= source_browser
->window()->GetNativeWindow();
545 aura::Window
* new_window
= params
->browser
->window()->GetNativeWindow();
546 const std::string
& src_user
=
547 manager
->GetUserPresentingWindow(src_window
);
548 if (src_user
!= manager
->GetUserPresentingWindow(new_window
)) {
549 // Once the window gets presented, it should be shown on the same
550 // desktop as the desktop of the creating browser. Note that this
551 // command will not show the window if it wasn't shown yet by the
553 manager
->ShowWindowForUser(new_window
, src_user
);
559 // Navigate() must not return early after this point.
561 if (GetSourceProfile(params
) != params
->browser
->profile()) {
562 // A tab is being opened from a link from a different profile, we must reset
563 // source information that may cause state to be shared.
564 params
->source_contents
= NULL
;
565 params
->referrer
= content::Referrer();
568 // Make sure the Browser is shown if params call for it.
569 ScopedBrowserShower
shower(params
);
571 // Makes sure any WebContents created by this function is destroyed if
572 // not properly added to a tab strip.
573 ScopedTargetContentsOwner
target_contents_owner(params
);
575 // Some dispositions need coercion to base types.
576 NormalizeDisposition(params
);
578 // If a new window has been created, it needs to be shown.
579 if (params
->window_action
== NavigateParams::NO_ACTION
&&
580 source_browser
!= params
->browser
&&
581 params
->browser
->tab_strip_model()->empty()) {
582 params
->window_action
= NavigateParams::SHOW_WINDOW
;
585 // If we create a popup window from a non user-gesture, don't activate it.
586 if (params
->window_action
== NavigateParams::SHOW_WINDOW
&&
587 params
->disposition
== NEW_POPUP
&&
588 params
->user_gesture
== false) {
589 params
->window_action
= NavigateParams::SHOW_WINDOW_INACTIVE
;
592 // Determine if the navigation was user initiated. If it was, we need to
593 // inform the target WebContents, and we may need to update the UI.
594 ui::PageTransition base_transition
=
595 ui::PageTransitionStripQualifier(params
->transition
);
596 bool user_initiated
=
597 params
->transition
& ui::PAGE_TRANSITION_FROM_ADDRESS_BAR
||
598 base_transition
== ui::PAGE_TRANSITION_TYPED
||
599 base_transition
== ui::PAGE_TRANSITION_AUTO_BOOKMARK
||
600 base_transition
== ui::PAGE_TRANSITION_GENERATED
||
601 base_transition
== ui::PAGE_TRANSITION_AUTO_TOPLEVEL
||
602 base_transition
== ui::PAGE_TRANSITION_RELOAD
||
603 base_transition
== ui::PAGE_TRANSITION_KEYWORD
;
605 // Check if this is a singleton tab that already exists
606 int singleton_index
= chrome::GetIndexOfSingletonTab(params
);
608 // Did we use a prerender?
609 bool swapped_in_prerender
= false;
611 // If no target WebContents was specified, we need to construct one if
612 // we are supposed to target a new tab; unless it's a singleton that already
614 if (!params
->target_contents
&& singleton_index
< 0) {
615 DCHECK(!params
->url
.is_empty());
616 if (params
->disposition
!= CURRENT_TAB
) {
617 params
->target_contents
= CreateTargetContents(*params
, params
->url
);
619 // This function takes ownership of |params->target_contents| until it
620 // is added to a TabStripModel.
621 target_contents_owner
.TakeOwnership();
623 // ... otherwise if we're loading in the current tab, the target is the
624 // same as the source.
625 DCHECK(params
->source_contents
);
626 params
->target_contents
= params
->source_contents
;
628 // Prerender can only swap in CURRENT_TAB navigations; others have
629 // different sessionStorage namespaces.
630 swapped_in_prerender
= SwapInPrerender(params
->url
, params
);
634 params
->target_contents
->UserGestureDone();
636 if (!swapped_in_prerender
) {
637 // Try to handle non-navigational URLs that popup dialogs and such, these
638 // should not actually navigate.
639 if (!HandleNonNavigationAboutURL(params
->url
)) {
640 // Perform the actual navigation, tracking whether it came from the
643 LoadURLInContents(params
->target_contents
, params
->url
, params
);
647 // |target_contents| was specified non-NULL, and so we assume it has already
648 // been navigated appropriately. We need to do nothing more other than
649 // add it to the appropriate tabstrip.
652 // If the user navigated from the omnibox, and the selected tab is going to
653 // lose focus, then make sure the focus for the source tab goes away from the
655 if (params
->source_contents
&&
656 (params
->disposition
== NEW_FOREGROUND_TAB
||
657 params
->disposition
== NEW_WINDOW
) &&
658 (params
->tabstrip_add_types
& TabStripModel::ADD_INHERIT_OPENER
))
659 params
->source_contents
->Focus();
661 if (params
->source_contents
== params
->target_contents
||
662 (swapped_in_prerender
&& params
->disposition
== CURRENT_TAB
)) {
663 // The navigation occurred in the source tab.
664 params
->browser
->UpdateUIForNavigationInTab(params
->target_contents
,
667 } else if (singleton_index
== -1) {
668 // If some non-default value is set for the index, we should tell the
669 // TabStripModel to respect it.
670 if (params
->tabstrip_index
!= -1)
671 params
->tabstrip_add_types
|= TabStripModel::ADD_FORCE_INDEX
;
673 // The navigation should insert a new tab into the target Browser.
674 params
->browser
->tab_strip_model()->AddWebContents(
675 params
->target_contents
,
676 params
->tabstrip_index
,
678 params
->tabstrip_add_types
);
679 // Now that the |params->target_contents| is safely owned by the target
680 // Browser's TabStripModel, we can release ownership.
681 target_contents_owner
.ReleaseOwnership();
684 if (singleton_index
>= 0) {
685 WebContents
* target
=
686 params
->browser
->tab_strip_model()->GetWebContentsAt(singleton_index
);
688 if (target
->IsCrashed()) {
689 target
->GetController().Reload(true);
690 } else if (params
->path_behavior
== NavigateParams::IGNORE_AND_NAVIGATE
&&
691 target
->GetURL() != params
->url
) {
692 LoadURLInContents(target
, params
->url
, params
);
695 // If the singleton tab isn't already selected, select it.
696 if (params
->source_contents
!= params
->target_contents
) {
697 params
->browser
->tab_strip_model()->ActivateTabAt(singleton_index
,
702 if (params
->disposition
!= CURRENT_TAB
) {
703 content::NotificationService::current()->Notify(
704 chrome::NOTIFICATION_TAB_ADDED
,
705 content::Source
<content::WebContentsDelegate
>(params
->browser
),
706 content::Details
<WebContents
>(params
->target_contents
));
710 bool IsURLAllowedInIncognito(const GURL
& url
,
711 content::BrowserContext
* browser_context
) {
712 if (url
.scheme() == content::kViewSourceScheme
) {
713 // A view-source URL is allowed in incognito mode only if the URL itself
714 // is allowed in incognito mode. Remove the "view-source:" from the start
715 // of the URL and validate the rest.
716 std::string stripped_spec
= url
.spec();
717 DCHECK_GT(stripped_spec
.size(), strlen(content::kViewSourceScheme
));
718 stripped_spec
.erase(0, strlen(content::kViewSourceScheme
) + 1);
719 GURL
stripped_url(stripped_spec
);
720 return stripped_url
.is_valid() &&
721 IsURLAllowedInIncognito(stripped_url
, browser_context
);
723 // Most URLs are allowed in incognito; the following are exceptions.
724 // chrome://extensions is on the list because it redirects to
725 // chrome://settings.
726 if (url
.scheme() == content::kChromeUIScheme
&&
727 (url
.host() == chrome::kChromeUISettingsHost
||
728 url
.host() == chrome::kChromeUISettingsFrameHost
||
729 url
.host() == chrome::kChromeUIHelpHost
||
730 url
.host() == chrome::kChromeUIExtensionsHost
||
731 url
.host() == chrome::kChromeUIBookmarksHost
||
732 #if !defined(OS_CHROMEOS)
733 url
.host() == chrome::kChromeUIChromeSigninHost
||
735 url
.host() == chrome::kChromeUIUberHost
||
736 url
.host() == chrome::kChromeUIThumbnailHost
||
737 url
.host() == chrome::kChromeUIThumbnailHost2
||
738 url
.host() == chrome::kChromeUIThumbnailListHost
||
739 url
.host() == chrome::kChromeUISuggestionsHost
||
740 #if defined(OS_CHROMEOS)
741 url
.host() == chrome::kChromeUIVoiceSearchHost
||
743 url
.host() == chrome::kChromeUIDevicesHost
)) {
747 if (url
.scheme() == chrome::kChromeSearchScheme
&&
748 (url
.host() == chrome::kChromeUIThumbnailHost
||
749 url
.host() == chrome::kChromeUIThumbnailHost2
||
750 url
.host() == chrome::kChromeUIThumbnailListHost
||
751 url
.host() == chrome::kChromeUISuggestionsHost
)) {
755 GURL rewritten_url
= url
;
756 bool reverse_on_redirect
= false;
757 content::BrowserURLHandler::GetInstance()->RewriteURLIfNecessary(
758 &rewritten_url
, browser_context
, &reverse_on_redirect
);
760 // Some URLs are mapped to uber subpages. Do not allow them in incognito.
761 return !(rewritten_url
.scheme() == content::kChromeUIScheme
&&
762 rewritten_url
.host() == chrome::kChromeUIUberHost
);
765 } // namespace chrome