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/prerender/prerender_util.h"
19 #include "chrome/browser/profiles/profile.h"
20 #include "chrome/browser/tab_contents/tab_util.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
);
68 // Returns true if the specified Browser can open tabs. Not all Browsers support
69 // multiple tabs, such as app frames and popups. This function returns false for
70 // those types of Browser.
71 bool WindowCanOpenTabs(Browser
* browser
) {
72 return browser
->CanSupportWindowFeature(Browser::FEATURE_TABSTRIP
) ||
73 browser
->tab_strip_model()->empty();
76 // Finds an existing Browser compatible with |profile|, making a new one if no
77 // such Browser is located.
78 Browser
* GetOrCreateBrowser(Profile
* profile
,
79 chrome::HostDesktopType host_desktop_type
) {
80 Browser
* browser
= chrome::FindTabbedBrowser(profile
, false,
82 return browser
? browser
: new Browser(
83 Browser::CreateParams(profile
, host_desktop_type
));
86 // Change some of the navigation parameters based on the particular URL.
87 // Currently this applies to some chrome:// pages which we always want to open
88 // in a non-incognito window. Note that even though a ChromeOS guest session is
89 // technically an incognito window, these URLs are allowed.
90 // Returns true on success. Otherwise, if changing params leads the browser into
91 // an erroneous state, returns false.
92 bool AdjustNavigateParamsForURL(chrome::NavigateParams
* params
) {
93 if (params
->target_contents
!= NULL
||
94 chrome::IsURLAllowedInIncognito(params
->url
,
95 params
->initiating_profile
) ||
96 params
->initiating_profile
->IsGuestSession()) {
100 Profile
* profile
= params
->initiating_profile
;
102 if (profile
->IsOffTheRecord() || params
->disposition
== OFF_THE_RECORD
) {
103 profile
= profile
->GetOriginalProfile();
105 // If incognito is forced, we punt.
106 PrefService
* prefs
= profile
->GetPrefs();
107 if (prefs
&& IncognitoModePrefs::GetAvailability(prefs
) ==
108 IncognitoModePrefs::FORCED
) {
112 params
->disposition
= SINGLETON_TAB
;
113 params
->browser
= GetOrCreateBrowser(profile
, params
->host_desktop_type
);
114 params
->window_action
= chrome::NavigateParams::SHOW_WINDOW
;
120 // Returns a Browser that can host the navigation or tab addition specified in
121 // |params|. This might just return the same Browser specified in |params|, or
122 // some other if that Browser is deemed incompatible.
123 Browser
* GetBrowserForDisposition(chrome::NavigateParams
* params
) {
124 // If no source WebContents was specified, we use the selected one from
125 // the target browser. This must happen first, before
126 // GetBrowserForDisposition() has a chance to replace |params->browser| with
128 if (!params
->source_contents
&& params
->browser
) {
129 params
->source_contents
=
130 params
->browser
->tab_strip_model()->GetActiveWebContents();
133 Profile
* profile
= params
->initiating_profile
;
135 switch (params
->disposition
) {
138 return params
->browser
;
139 // Find a compatible window and re-execute this command in it. Otherwise
140 // re-run with NEW_WINDOW.
141 return GetOrCreateBrowser(profile
, params
->host_desktop_type
);
143 case NEW_FOREGROUND_TAB
:
144 case NEW_BACKGROUND_TAB
:
145 // See if we can open the tab in the window this navigator is bound to.
146 if (params
->browser
&& WindowCanOpenTabs(params
->browser
))
147 return params
->browser
;
148 // Find a compatible window and re-execute this command in it. Otherwise
149 // re-run with NEW_WINDOW.
150 return GetOrCreateBrowser(profile
, params
->host_desktop_type
);
152 // Make a new popup window.
153 // Coerce app-style if |source| represents an app.
154 std::string app_name
;
155 #if defined(ENABLE_EXTENSIONS)
156 if (!params
->extension_app_id
.empty()) {
157 app_name
= web_app::GenerateApplicationNameFromExtensionId(
158 params
->extension_app_id
);
159 } else if (params
->browser
&& !params
->browser
->app_name().empty()) {
160 app_name
= params
->browser
->app_name();
161 } else if (params
->source_contents
) {
162 extensions::TabHelper
* extensions_tab_helper
=
163 extensions::TabHelper::FromWebContents(params
->source_contents
);
164 if (extensions_tab_helper
&& extensions_tab_helper
->is_app()) {
165 app_name
= web_app::GenerateApplicationNameFromExtensionId(
166 extensions_tab_helper
->extension_app()->id());
170 if (app_name
.empty()) {
171 Browser::CreateParams
browser_params(
172 Browser::TYPE_POPUP
, profile
, params
->host_desktop_type
);
173 browser_params
.trusted_source
= params
->trusted_source
;
174 browser_params
.initial_bounds
= params
->window_bounds
;
175 return new Browser(browser_params
);
178 return new Browser(Browser::CreateParams::CreateForApp(
180 params
->trusted_source
,
181 params
->window_bounds
,
183 params
->host_desktop_type
));
186 // Make a new normal browser window.
187 return new Browser(Browser::CreateParams(profile
,
188 params
->host_desktop_type
));
191 // Make or find an incognito window.
192 return GetOrCreateBrowser(profile
->GetOffTheRecordProfile(),
193 params
->host_desktop_type
);
194 // The following types all result in no navigation.
205 // Fix disposition and other parameter values depending on prevailing
207 void NormalizeDisposition(chrome::NavigateParams
* params
) {
208 // Calculate the WindowOpenDisposition if necessary.
209 if (params
->browser
->tab_strip_model()->empty() &&
210 (params
->disposition
== NEW_BACKGROUND_TAB
||
211 params
->disposition
== CURRENT_TAB
||
212 params
->disposition
== SINGLETON_TAB
)) {
213 params
->disposition
= NEW_FOREGROUND_TAB
;
215 if (params
->browser
->profile()->IsOffTheRecord() &&
216 params
->disposition
== OFF_THE_RECORD
) {
217 params
->disposition
= NEW_FOREGROUND_TAB
;
219 if (!params
->source_contents
&& params
->disposition
== CURRENT_TAB
)
220 params
->disposition
= NEW_FOREGROUND_TAB
;
222 switch (params
->disposition
) {
223 case NEW_BACKGROUND_TAB
:
224 // Disposition trumps add types. ADD_ACTIVE is a default, so we need to
225 // remove it if disposition implies the tab is going to open in the
227 params
->tabstrip_add_types
&= ~TabStripModel::ADD_ACTIVE
;
232 // Code that wants to open a new window typically expects it to be shown
234 if (params
->window_action
== chrome::NavigateParams::NO_ACTION
)
235 params
->window_action
= chrome::NavigateParams::SHOW_WINDOW
;
237 case NEW_FOREGROUND_TAB
:
239 params
->tabstrip_add_types
|= TabStripModel::ADD_ACTIVE
;
247 // Obtain the profile used by the code that originated the Navigate() request.
248 Profile
* GetSourceProfile(chrome::NavigateParams
* params
) {
249 if (params
->source_contents
) {
250 return Profile::FromBrowserContext(
251 params
->source_contents
->GetBrowserContext());
254 return params
->initiating_profile
;
257 void LoadURLInContents(WebContents
* target_contents
,
259 chrome::NavigateParams
* params
) {
260 NavigationController::LoadURLParams
load_url_params(url
);
261 load_url_params
.source_site_instance
= params
->source_site_instance
;
262 load_url_params
.referrer
= params
->referrer
;
263 load_url_params
.frame_tree_node_id
= params
->frame_tree_node_id
;
264 load_url_params
.redirect_chain
= params
->redirect_chain
;
265 load_url_params
.transition_type
= params
->transition
;
266 load_url_params
.extra_headers
= params
->extra_headers
;
267 load_url_params
.should_replace_current_entry
=
268 params
->should_replace_current_entry
;
270 if (params
->transferred_global_request_id
!= GlobalRequestID()) {
271 load_url_params
.is_renderer_initiated
= params
->is_renderer_initiated
;
272 load_url_params
.transferred_global_request_id
=
273 params
->transferred_global_request_id
;
274 } else if (params
->is_renderer_initiated
) {
275 load_url_params
.is_renderer_initiated
= true;
278 // Only allows the browser-initiated navigation to use POST.
279 if (params
->uses_post
&& !params
->is_renderer_initiated
) {
280 load_url_params
.load_type
=
281 NavigationController::LOAD_TYPE_BROWSER_INITIATED_HTTP_POST
;
282 load_url_params
.browser_initiated_post_data
=
283 params
->browser_initiated_post_data
;
285 target_contents
->GetController().LoadURLWithParams(load_url_params
);
288 // This class makes sure the Browser object held in |params| is made visible
289 // by the time it goes out of scope, provided |params| wants it to be shown.
290 class ScopedBrowserShower
{
292 explicit ScopedBrowserShower(chrome::NavigateParams
* params
)
295 ~ScopedBrowserShower() {
296 if (params_
->window_action
==
297 chrome::NavigateParams::SHOW_WINDOW_INACTIVE
) {
298 params_
->browser
->window()->ShowInactive();
299 } else if (params_
->window_action
== chrome::NavigateParams::SHOW_WINDOW
) {
300 params_
->browser
->window()->Show();
301 // If a user gesture opened a popup window, focus the contents.
302 if (params_
->user_gesture
&& params_
->disposition
== NEW_POPUP
&&
303 params_
->target_contents
) {
304 params_
->target_contents
->Focus();
310 chrome::NavigateParams
* params_
;
311 DISALLOW_COPY_AND_ASSIGN(ScopedBrowserShower
);
314 // This class manages the lifetime of a WebContents created by the
315 // Navigate() function. When Navigate() creates a WebContents for a URL,
316 // an instance of this class takes ownership of it via TakeOwnership() until the
317 // WebContents is added to a tab strip at which time ownership is
318 // relinquished via ReleaseOwnership(). If this object goes out of scope without
319 // being added to a tab strip, the created WebContents is deleted to
320 // avoid a leak and the params->target_contents field is set to NULL.
321 class ScopedTargetContentsOwner
{
323 explicit ScopedTargetContentsOwner(chrome::NavigateParams
* params
)
326 ~ScopedTargetContentsOwner() {
327 if (target_contents_owner_
.get())
328 params_
->target_contents
= NULL
;
331 // Assumes ownership of |params_|' target_contents until ReleaseOwnership
333 void TakeOwnership() {
334 target_contents_owner_
.reset(params_
->target_contents
);
337 // Relinquishes ownership of |params_|' target_contents.
338 WebContents
* ReleaseOwnership() {
339 return target_contents_owner_
.release();
343 chrome::NavigateParams
* params_
;
344 scoped_ptr
<WebContents
> target_contents_owner_
;
345 DISALLOW_COPY_AND_ASSIGN(ScopedTargetContentsOwner
);
348 content::WebContents
* CreateTargetContents(const chrome::NavigateParams
& params
,
350 WebContents::CreateParams
create_params(
351 params
.browser
->profile(),
352 tab_util::GetSiteInstanceForNewTab(params
.browser
->profile(), url
));
353 if (params
.source_contents
) {
354 create_params
.initial_size
=
355 params
.source_contents
->GetContainerBounds().size();
356 if (params
.should_set_opener
)
357 create_params
.opener
= params
.source_contents
;
359 if (params
.disposition
== NEW_BACKGROUND_TAB
)
360 create_params
.initially_hidden
= true;
362 #if defined(USE_AURA)
363 if (params
.browser
->window() &&
364 params
.browser
->window()->GetNativeWindow()) {
365 create_params
.context
=
366 params
.browser
->window()->GetNativeWindow();
370 WebContents
* target_contents
= WebContents::Create(create_params
);
372 // New tabs can have WebUI URLs that will make calls back to arbitrary
373 // tab helpers, so the entire set of tab helpers needs to be set up
375 BrowserNavigatorWebContentsAdoption::AttachTabHelpers(target_contents
);
376 #if defined(ENABLE_EXTENSIONS)
377 extensions::TabHelper::FromWebContents(target_contents
)->
378 SetExtensionAppById(params
.extension_app_id
);
380 return target_contents
;
383 // If a prerendered page exists for |url|, replace the page at
384 // |params->target_contents| with it and update to point to the swapped-in
386 bool SwapInPrerender(const GURL
& url
, chrome::NavigateParams
* params
) {
388 Profile::FromBrowserContext(params
->target_contents
->GetBrowserContext());
389 InstantSearchPrerenderer
* prerenderer
=
390 InstantSearchPrerenderer::GetForProfile(profile
);
391 if (prerenderer
&& prerenderer
->UsePrerenderedPage(url
, params
))
394 prerender::PrerenderManager
* prerender_manager
=
395 prerender::PrerenderManagerFactory::GetForProfile(profile
);
396 return prerender_manager
&&
397 prerender_manager
->MaybeUsePrerenderedPage(url
, params
);
400 chrome::HostDesktopType
GetHostDesktop(Browser
* browser
) {
402 return browser
->host_desktop_type();
403 return chrome::GetActiveDesktop();
410 NavigateParams::NavigateParams(Browser
* a_browser
,
412 ui::PageTransition a_transition
)
414 frame_tree_node_id(-1),
416 target_contents(NULL
),
417 source_contents(NULL
),
418 disposition(CURRENT_TAB
),
419 trusted_source(false),
420 transition(a_transition
),
421 is_renderer_initiated(false),
423 tabstrip_add_types(TabStripModel::ADD_ACTIVE
),
424 window_action(NO_ACTION
),
426 path_behavior(RESPECT
),
427 ref_behavior(IGNORE_REF
),
429 initiating_profile(NULL
),
430 host_desktop_type(GetHostDesktop(a_browser
)),
431 should_replace_current_entry(false),
432 should_set_opener(false) {
435 NavigateParams::NavigateParams(Browser
* a_browser
,
436 WebContents
* a_target_contents
)
437 : frame_tree_node_id(-1),
439 target_contents(a_target_contents
),
440 source_contents(NULL
),
441 disposition(CURRENT_TAB
),
442 trusted_source(false),
443 transition(ui::PAGE_TRANSITION_LINK
),
444 is_renderer_initiated(false),
446 tabstrip_add_types(TabStripModel::ADD_ACTIVE
),
447 window_action(NO_ACTION
),
449 path_behavior(RESPECT
),
450 ref_behavior(IGNORE_REF
),
452 initiating_profile(NULL
),
453 host_desktop_type(GetHostDesktop(a_browser
)),
454 should_replace_current_entry(false),
455 should_set_opener(false) {
458 NavigateParams::NavigateParams(Profile
* a_profile
,
460 ui::PageTransition a_transition
)
462 frame_tree_node_id(-1),
464 target_contents(NULL
),
465 source_contents(NULL
),
466 disposition(NEW_FOREGROUND_TAB
),
467 trusted_source(false),
468 transition(a_transition
),
469 is_renderer_initiated(false),
471 tabstrip_add_types(TabStripModel::ADD_ACTIVE
),
472 window_action(SHOW_WINDOW
),
474 path_behavior(RESPECT
),
475 ref_behavior(IGNORE_REF
),
477 initiating_profile(a_profile
),
478 host_desktop_type(chrome::GetActiveDesktop()),
479 should_replace_current_entry(false),
480 should_set_opener(false) {
483 NavigateParams::~NavigateParams() {}
485 void FillNavigateParamsFromOpenURLParams(chrome::NavigateParams
* nav_params
,
486 const content::OpenURLParams
& params
) {
487 nav_params
->referrer
= params
.referrer
;
488 nav_params
->source_site_instance
= params
.source_site_instance
;
489 nav_params
->frame_tree_node_id
= params
.frame_tree_node_id
;
490 nav_params
->redirect_chain
= params
.redirect_chain
;
491 nav_params
->extra_headers
= params
.extra_headers
;
492 nav_params
->disposition
= params
.disposition
;
493 nav_params
->trusted_source
= false;
494 nav_params
->is_renderer_initiated
= params
.is_renderer_initiated
;
495 nav_params
->transferred_global_request_id
=
496 params
.transferred_global_request_id
;
497 nav_params
->should_replace_current_entry
=
498 params
.should_replace_current_entry
;
499 nav_params
->uses_post
= params
.uses_post
;
500 nav_params
->browser_initiated_post_data
= params
.browser_initiated_post_data
;
503 void Navigate(NavigateParams
* params
) {
504 Browser
* source_browser
= params
->browser
;
506 params
->initiating_profile
= source_browser
->profile();
507 DCHECK(params
->initiating_profile
);
509 if (!AdjustNavigateParamsForURL(params
))
512 #if defined(ENABLE_EXTENSIONS)
513 const extensions::Extension
* extension
=
514 extensions::ExtensionRegistry::Get(params
->initiating_profile
)->
515 enabled_extensions().GetExtensionOrAppByURL(params
->url
);
516 // Platform apps cannot navigate. Block the request.
517 if (extension
&& extension
->is_platform_app())
518 params
->url
= GURL(chrome::kExtensionInvalidRequestURL
);
521 // The browser window may want to adjust the disposition.
522 if (params
->disposition
== NEW_POPUP
&&
524 source_browser
->window()) {
525 params
->disposition
=
526 source_browser
->window()->GetDispositionForPopupBounds(
527 params
->window_bounds
);
530 params
->browser
= GetBrowserForDisposition(params
);
531 if (!params
->browser
)
535 if (source_browser
&& source_browser
!= params
->browser
) {
536 // When the newly created browser was spawned by a browser which visits
537 // another user's desktop, it should be shown on the same desktop as the
538 // originating one. (This is part of the desktop separation per profile).
539 MultiUserWindowManager
* manager
= MultiUserWindowManager::GetInstance();
540 // Some unit tests have no manager instantiated.
542 aura::Window
* src_window
= source_browser
->window()->GetNativeWindow();
543 aura::Window
* new_window
= params
->browser
->window()->GetNativeWindow();
544 const std::string
& src_user
=
545 manager
->GetUserPresentingWindow(src_window
);
546 if (src_user
!= manager
->GetUserPresentingWindow(new_window
)) {
547 // Once the window gets presented, it should be shown on the same
548 // desktop as the desktop of the creating browser. Note that this
549 // command will not show the window if it wasn't shown yet by the
551 manager
->ShowWindowForUser(new_window
, src_user
);
557 // Navigate() must not return early after this point.
559 if (GetSourceProfile(params
) != params
->browser
->profile()) {
560 // A tab is being opened from a link from a different profile, we must reset
561 // source information that may cause state to be shared.
562 params
->source_contents
= NULL
;
563 params
->referrer
= content::Referrer();
566 // Make sure the Browser is shown if params call for it.
567 ScopedBrowserShower
shower(params
);
569 // Makes sure any WebContents created by this function is destroyed if
570 // not properly added to a tab strip.
571 ScopedTargetContentsOwner
target_contents_owner(params
);
573 // Some dispositions need coercion to base types.
574 NormalizeDisposition(params
);
576 // If a new window has been created, it needs to be shown.
577 if (params
->window_action
== NavigateParams::NO_ACTION
&&
578 source_browser
!= params
->browser
&&
579 params
->browser
->tab_strip_model()->empty()) {
580 params
->window_action
= NavigateParams::SHOW_WINDOW
;
583 // If we create a popup window from a non user-gesture, don't activate it.
584 if (params
->window_action
== NavigateParams::SHOW_WINDOW
&&
585 params
->disposition
== NEW_POPUP
&&
586 params
->user_gesture
== false) {
587 params
->window_action
= NavigateParams::SHOW_WINDOW_INACTIVE
;
590 // Determine if the navigation was user initiated. If it was, we need to
591 // inform the target WebContents, and we may need to update the UI.
592 ui::PageTransition base_transition
=
593 ui::PageTransitionStripQualifier(params
->transition
);
594 bool user_initiated
=
595 params
->transition
& ui::PAGE_TRANSITION_FROM_ADDRESS_BAR
||
596 base_transition
== ui::PAGE_TRANSITION_TYPED
||
597 base_transition
== ui::PAGE_TRANSITION_AUTO_BOOKMARK
||
598 base_transition
== ui::PAGE_TRANSITION_GENERATED
||
599 base_transition
== ui::PAGE_TRANSITION_AUTO_TOPLEVEL
||
600 base_transition
== ui::PAGE_TRANSITION_RELOAD
||
601 base_transition
== ui::PAGE_TRANSITION_KEYWORD
;
603 // Check if this is a singleton tab that already exists
604 int singleton_index
= chrome::GetIndexOfSingletonTab(params
);
606 // Did we use a prerender?
607 bool swapped_in_prerender
= false;
609 // If no target WebContents was specified, we need to construct one if
610 // we are supposed to target a new tab; unless it's a singleton that already
612 if (!params
->target_contents
&& singleton_index
< 0) {
613 DCHECK(!params
->url
.is_empty());
614 if (params
->disposition
!= CURRENT_TAB
) {
615 params
->target_contents
= CreateTargetContents(*params
, params
->url
);
617 // This function takes ownership of |params->target_contents| until it
618 // is added to a TabStripModel.
619 target_contents_owner
.TakeOwnership();
621 // ... otherwise if we're loading in the current tab, the target is the
622 // same as the source.
623 DCHECK(params
->source_contents
);
624 params
->target_contents
= params
->source_contents
;
626 // Prerender can only swap in CURRENT_TAB navigations; others have
627 // different sessionStorage namespaces.
628 swapped_in_prerender
= SwapInPrerender(params
->url
, params
);
632 params
->target_contents
->UserGestureDone();
634 if (!swapped_in_prerender
) {
635 // Try to handle non-navigational URLs that popup dialogs and such, these
636 // should not actually navigate.
637 if (!HandleNonNavigationAboutURL(params
->url
)) {
638 // Perform the actual navigation, tracking whether it came from the
641 LoadURLInContents(params
->target_contents
, params
->url
, params
);
642 // For prerender bookkeeping purposes, record that this pending navigate
643 // originated from chrome::Navigate.
644 content::NavigationEntry
* entry
=
645 params
->target_contents
->GetController().GetPendingEntry();
647 entry
->SetExtraData(prerender::kChromeNavigateExtraDataKey
,
652 // |target_contents| was specified non-NULL, and so we assume it has already
653 // been navigated appropriately. We need to do nothing more other than
654 // add it to the appropriate tabstrip.
657 // If the user navigated from the omnibox, and the selected tab is going to
658 // lose focus, then make sure the focus for the source tab goes away from the
660 if (params
->source_contents
&&
661 (params
->disposition
== NEW_FOREGROUND_TAB
||
662 params
->disposition
== NEW_WINDOW
) &&
663 (params
->tabstrip_add_types
& TabStripModel::ADD_INHERIT_OPENER
))
664 params
->source_contents
->Focus();
666 if (params
->source_contents
== params
->target_contents
||
667 (swapped_in_prerender
&& params
->disposition
== CURRENT_TAB
)) {
668 // The navigation occurred in the source tab.
669 params
->browser
->UpdateUIForNavigationInTab(params
->target_contents
,
672 } else if (singleton_index
== -1) {
673 // If some non-default value is set for the index, we should tell the
674 // TabStripModel to respect it.
675 if (params
->tabstrip_index
!= -1)
676 params
->tabstrip_add_types
|= TabStripModel::ADD_FORCE_INDEX
;
678 // The navigation should insert a new tab into the target Browser.
679 params
->browser
->tab_strip_model()->AddWebContents(
680 params
->target_contents
,
681 params
->tabstrip_index
,
683 params
->tabstrip_add_types
);
684 // Now that the |params->target_contents| is safely owned by the target
685 // Browser's TabStripModel, we can release ownership.
686 target_contents_owner
.ReleaseOwnership();
689 if (singleton_index
>= 0) {
690 WebContents
* target
=
691 params
->browser
->tab_strip_model()->GetWebContentsAt(singleton_index
);
693 if (target
->IsCrashed()) {
694 target
->GetController().Reload(true);
695 } else if (params
->path_behavior
== NavigateParams::IGNORE_AND_NAVIGATE
&&
696 target
->GetURL() != params
->url
) {
697 LoadURLInContents(target
, params
->url
, params
);
698 // For prerender bookkeeping purposes, record that this pending navigate
699 // originated from chrome::Navigate.
700 content::NavigationEntry
* entry
=
701 target
->GetController().GetPendingEntry();
703 entry
->SetExtraData(prerender::kChromeNavigateExtraDataKey
,
707 // If the singleton tab isn't already selected, select it.
708 if (params
->source_contents
!= params
->target_contents
) {
709 params
->browser
->tab_strip_model()->ActivateTabAt(singleton_index
,
714 if (params
->disposition
!= CURRENT_TAB
) {
715 content::NotificationService::current()->Notify(
716 chrome::NOTIFICATION_TAB_ADDED
,
717 content::Source
<content::WebContentsDelegate
>(params
->browser
),
718 content::Details
<WebContents
>(params
->target_contents
));
722 bool IsURLAllowedInIncognito(const GURL
& url
,
723 content::BrowserContext
* browser_context
) {
724 if (url
.scheme() == content::kViewSourceScheme
) {
725 // A view-source URL is allowed in incognito mode only if the URL itself
726 // is allowed in incognito mode. Remove the "view-source:" from the start
727 // of the URL and validate the rest.
728 std::string stripped_spec
= url
.spec();
729 DCHECK_GT(stripped_spec
.size(), strlen(content::kViewSourceScheme
));
730 stripped_spec
.erase(0, strlen(content::kViewSourceScheme
) + 1);
731 GURL
stripped_url(stripped_spec
);
732 return stripped_url
.is_valid() &&
733 IsURLAllowedInIncognito(stripped_url
, browser_context
);
735 // Most URLs are allowed in incognito; the following are exceptions.
736 // chrome://extensions is on the list because it redirects to
737 // chrome://settings.
738 if (url
.scheme() == content::kChromeUIScheme
&&
739 (url
.host() == chrome::kChromeUISettingsHost
||
740 url
.host() == chrome::kChromeUISettingsFrameHost
||
741 url
.host() == chrome::kChromeUIHelpHost
||
742 url
.host() == chrome::kChromeUIExtensionsHost
||
743 url
.host() == chrome::kChromeUIBookmarksHost
||
744 #if !defined(OS_CHROMEOS)
745 url
.host() == chrome::kChromeUIChromeSigninHost
||
747 url
.host() == chrome::kChromeUIUberHost
||
748 url
.host() == chrome::kChromeUIThumbnailHost
||
749 url
.host() == chrome::kChromeUIThumbnailHost2
||
750 url
.host() == chrome::kChromeUIThumbnailListHost
||
751 url
.host() == chrome::kChromeUISuggestionsHost
||
752 url
.host() == chrome::kChromeUIDevicesHost
||
753 url
.host() == chrome::kChromeUIVoiceSearchHost
)) {
757 if (url
.scheme() == chrome::kChromeSearchScheme
&&
758 (url
.host() == chrome::kChromeUIThumbnailHost
||
759 url
.host() == chrome::kChromeUIThumbnailHost2
||
760 url
.host() == chrome::kChromeUIThumbnailListHost
||
761 url
.host() == chrome::kChromeUISuggestionsHost
)) {
765 GURL rewritten_url
= url
;
766 bool reverse_on_redirect
= false;
767 content::BrowserURLHandler::GetInstance()->RewriteURLIfNecessary(
768 &rewritten_url
, browser_context
, &reverse_on_redirect
);
770 // Some URLs are mapped to uber subpages. Do not allow them in incognito.
771 return !(rewritten_url
.scheme() == content::kChromeUIScheme
&&
772 rewritten_url
.host() == chrome::kChromeUIUberHost
);
775 } // namespace chrome