Don't show supervised user as "already on this device" while they're being imported.
[chromium-blink-merge.git] / chrome / browser / ui / browser_navigator.cc
blob7be37f78cca1f3e1d9a72658416b78fbfc8748f0
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"
7 #include <algorithm>
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/ui/browser.h"
21 #include "chrome/browser/ui/browser_finder.h"
22 #include "chrome/browser/ui/browser_instant_controller.h"
23 #include "chrome/browser/ui/browser_window.h"
24 #include "chrome/browser/ui/host_desktop.h"
25 #include "chrome/browser/ui/location_bar/location_bar.h"
26 #include "chrome/browser/ui/search/instant_search_prerenderer.h"
27 #include "chrome/browser/ui/singleton_tabs.h"
28 #include "chrome/browser/ui/status_bubble.h"
29 #include "chrome/browser/ui/tab_helpers.h"
30 #include "chrome/browser/ui/tabs/tab_strip_model.h"
31 #include "chrome/common/url_constants.h"
32 #include "content/public/browser/browser_url_handler.h"
33 #include "content/public/browser/navigation_entry.h"
34 #include "content/public/browser/notification_service.h"
35 #include "content/public/browser/render_view_host.h"
36 #include "content/public/browser/web_contents.h"
38 #if defined(USE_ASH)
39 #include "chrome/browser/ui/ash/multi_user/multi_user_window_manager.h"
40 #endif
42 #if defined(USE_AURA)
43 #include "ui/aura/window.h"
44 #endif
46 #if defined(ENABLE_EXTENSIONS)
47 #include "chrome/browser/extensions/tab_helper.h"
48 #include "chrome/browser/web_applications/web_app.h"
49 #include "extensions/browser/extension_registry.h"
50 #include "extensions/common/extension.h"
51 #include "extensions/common/extension_set.h"
52 #endif
54 using content::GlobalRequestID;
55 using content::NavigationController;
56 using content::WebContents;
58 class BrowserNavigatorWebContentsAdoption {
59 public:
60 static void AttachTabHelpers(content::WebContents* contents) {
61 TabHelpers::AttachTabHelpers(contents);
65 namespace {
67 // Returns true if the specified Browser can open tabs. Not all Browsers support
68 // multiple tabs, such as app frames and popups. This function returns false for
69 // those types of Browser.
70 bool WindowCanOpenTabs(Browser* browser) {
71 return browser->CanSupportWindowFeature(Browser::FEATURE_TABSTRIP) ||
72 browser->tab_strip_model()->empty();
75 // Finds an existing Browser compatible with |profile|, making a new one if no
76 // such Browser is located.
77 Browser* GetOrCreateBrowser(Profile* profile,
78 chrome::HostDesktopType host_desktop_type) {
79 Browser* browser = chrome::FindTabbedBrowser(profile, false,
80 host_desktop_type);
81 return browser ? browser : new Browser(
82 Browser::CreateParams(profile, host_desktop_type));
85 // Change some of the navigation parameters based on the particular URL.
86 // Currently this applies to some chrome:// pages which we always want to open
87 // in a non-incognito window. Note that even though a ChromeOS guest session is
88 // technically an incognito window, these URLs are allowed.
89 // Returns true on success. Otherwise, if changing params leads the browser into
90 // an erroneous state, returns false.
91 bool AdjustNavigateParamsForURL(chrome::NavigateParams* params) {
92 if (params->target_contents != NULL ||
93 chrome::IsURLAllowedInIncognito(params->url,
94 params->initiating_profile) ||
95 params->initiating_profile->IsGuestSession()) {
96 return true;
99 Profile* profile = params->initiating_profile;
101 if (profile->IsOffTheRecord() || params->disposition == OFF_THE_RECORD) {
102 profile = profile->GetOriginalProfile();
104 // If incognito is forced, we punt.
105 PrefService* prefs = profile->GetPrefs();
106 if (prefs && IncognitoModePrefs::GetAvailability(prefs) ==
107 IncognitoModePrefs::FORCED) {
108 return false;
111 params->disposition = SINGLETON_TAB;
112 params->browser = GetOrCreateBrowser(profile, params->host_desktop_type);
113 params->window_action = chrome::NavigateParams::SHOW_WINDOW;
116 return true;
119 // Returns a Browser that can host the navigation or tab addition specified in
120 // |params|. This might just return the same Browser specified in |params|, or
121 // some other if that Browser is deemed incompatible.
122 Browser* GetBrowserForDisposition(chrome::NavigateParams* params) {
123 // If no source WebContents was specified, we use the selected one from
124 // the target browser. This must happen first, before
125 // GetBrowserForDisposition() has a chance to replace |params->browser| with
126 // another one.
127 if (!params->source_contents && params->browser) {
128 params->source_contents =
129 params->browser->tab_strip_model()->GetActiveWebContents();
132 Profile* profile = params->initiating_profile;
134 switch (params->disposition) {
135 case CURRENT_TAB:
136 if (params->browser)
137 return params->browser;
138 // Find a compatible window and re-execute this command in it. Otherwise
139 // re-run with NEW_WINDOW.
140 return GetOrCreateBrowser(profile, params->host_desktop_type);
141 case SINGLETON_TAB:
142 case NEW_FOREGROUND_TAB:
143 case NEW_BACKGROUND_TAB:
144 // See if we can open the tab in the window this navigator is bound to.
145 if (params->browser && WindowCanOpenTabs(params->browser))
146 return params->browser;
147 // Find a compatible window and re-execute this command in it. Otherwise
148 // re-run with NEW_WINDOW.
149 return GetOrCreateBrowser(profile, params->host_desktop_type);
150 case NEW_POPUP: {
151 // Make a new popup window.
152 // Coerce app-style if |source| represents an app.
153 std::string app_name;
154 #if defined(ENABLE_EXTENSIONS)
155 if (!params->extension_app_id.empty()) {
156 app_name = web_app::GenerateApplicationNameFromExtensionId(
157 params->extension_app_id);
158 } else if (params->browser && !params->browser->app_name().empty()) {
159 app_name = params->browser->app_name();
160 } else if (params->source_contents) {
161 extensions::TabHelper* extensions_tab_helper =
162 extensions::TabHelper::FromWebContents(params->source_contents);
163 if (extensions_tab_helper && extensions_tab_helper->is_app()) {
164 app_name = web_app::GenerateApplicationNameFromExtensionId(
165 extensions_tab_helper->extension_app()->id());
168 #endif
169 if (app_name.empty()) {
170 Browser::CreateParams browser_params(
171 Browser::TYPE_POPUP, profile, params->host_desktop_type);
172 browser_params.trusted_source = params->trusted_source;
173 browser_params.initial_bounds = params->window_bounds;
174 return new Browser(browser_params);
177 return new Browser(Browser::CreateParams::CreateForApp(
178 app_name,
179 params->trusted_source,
180 params->window_bounds,
181 profile,
182 params->host_desktop_type));
184 case NEW_WINDOW: {
185 // Make a new normal browser window.
186 return new Browser(Browser::CreateParams(profile,
187 params->host_desktop_type));
189 case OFF_THE_RECORD:
190 // Make or find an incognito window.
191 return GetOrCreateBrowser(profile->GetOffTheRecordProfile(),
192 params->host_desktop_type);
193 // The following types all result in no navigation.
194 case SUPPRESS_OPEN:
195 case SAVE_TO_DISK:
196 case IGNORE_ACTION:
197 return NULL;
198 default:
199 NOTREACHED();
201 return NULL;
204 // Fix disposition and other parameter values depending on prevailing
205 // conditions.
206 void NormalizeDisposition(chrome::NavigateParams* params) {
207 // Calculate the WindowOpenDisposition if necessary.
208 if (params->browser->tab_strip_model()->empty() &&
209 (params->disposition == NEW_BACKGROUND_TAB ||
210 params->disposition == CURRENT_TAB ||
211 params->disposition == SINGLETON_TAB)) {
212 params->disposition = NEW_FOREGROUND_TAB;
214 if (params->browser->profile()->IsOffTheRecord() &&
215 params->disposition == OFF_THE_RECORD) {
216 params->disposition = NEW_FOREGROUND_TAB;
218 if (!params->source_contents && params->disposition == CURRENT_TAB)
219 params->disposition = NEW_FOREGROUND_TAB;
221 switch (params->disposition) {
222 case NEW_BACKGROUND_TAB:
223 // Disposition trumps add types. ADD_ACTIVE is a default, so we need to
224 // remove it if disposition implies the tab is going to open in the
225 // background.
226 params->tabstrip_add_types &= ~TabStripModel::ADD_ACTIVE;
227 break;
229 case NEW_WINDOW:
230 case NEW_POPUP:
231 // Code that wants to open a new window typically expects it to be shown
232 // automatically.
233 if (params->window_action == chrome::NavigateParams::NO_ACTION)
234 params->window_action = chrome::NavigateParams::SHOW_WINDOW;
235 // Fall-through.
236 case NEW_FOREGROUND_TAB:
237 case SINGLETON_TAB:
238 params->tabstrip_add_types |= TabStripModel::ADD_ACTIVE;
239 break;
241 default:
242 break;
246 // Obtain the profile used by the code that originated the Navigate() request.
247 Profile* GetSourceProfile(chrome::NavigateParams* params) {
248 if (params->source_contents) {
249 return Profile::FromBrowserContext(
250 params->source_contents->GetBrowserContext());
253 return params->initiating_profile;
256 void LoadURLInContents(WebContents* target_contents,
257 const GURL& url,
258 chrome::NavigateParams* params) {
259 NavigationController::LoadURLParams load_url_params(url);
260 load_url_params.source_site_instance = params->source_site_instance;
261 load_url_params.referrer = params->referrer;
262 load_url_params.frame_tree_node_id = params->frame_tree_node_id;
263 load_url_params.redirect_chain = params->redirect_chain;
264 load_url_params.transition_type = params->transition;
265 load_url_params.extra_headers = params->extra_headers;
266 load_url_params.should_replace_current_entry =
267 params->should_replace_current_entry;
269 if (params->transferred_global_request_id != GlobalRequestID()) {
270 load_url_params.is_renderer_initiated = params->is_renderer_initiated;
271 load_url_params.transferred_global_request_id =
272 params->transferred_global_request_id;
273 } else if (params->is_renderer_initiated) {
274 load_url_params.is_renderer_initiated = true;
277 // Only allows the browser-initiated navigation to use POST.
278 if (params->uses_post && !params->is_renderer_initiated) {
279 load_url_params.load_type =
280 NavigationController::LOAD_TYPE_BROWSER_INITIATED_HTTP_POST;
281 load_url_params.browser_initiated_post_data =
282 params->browser_initiated_post_data;
284 target_contents->GetController().LoadURLWithParams(load_url_params);
287 // This class makes sure the Browser object held in |params| is made visible
288 // by the time it goes out of scope, provided |params| wants it to be shown.
289 class ScopedBrowserShower {
290 public:
291 explicit ScopedBrowserShower(chrome::NavigateParams* params)
292 : params_(params) {
294 ~ScopedBrowserShower() {
295 if (params_->window_action ==
296 chrome::NavigateParams::SHOW_WINDOW_INACTIVE) {
297 params_->browser->window()->ShowInactive();
298 } else if (params_->window_action == chrome::NavigateParams::SHOW_WINDOW) {
299 params_->browser->window()->Show();
300 // If a user gesture opened a popup window, focus the contents.
301 if (params_->user_gesture && params_->disposition == NEW_POPUP &&
302 params_->target_contents) {
303 params_->target_contents->Focus();
308 private:
309 chrome::NavigateParams* params_;
310 DISALLOW_COPY_AND_ASSIGN(ScopedBrowserShower);
313 // This class manages the lifetime of a WebContents created by the
314 // Navigate() function. When Navigate() creates a WebContents for a URL,
315 // an instance of this class takes ownership of it via TakeOwnership() until the
316 // WebContents is added to a tab strip at which time ownership is
317 // relinquished via ReleaseOwnership(). If this object goes out of scope without
318 // being added to a tab strip, the created WebContents is deleted to
319 // avoid a leak and the params->target_contents field is set to NULL.
320 class ScopedTargetContentsOwner {
321 public:
322 explicit ScopedTargetContentsOwner(chrome::NavigateParams* params)
323 : params_(params) {
325 ~ScopedTargetContentsOwner() {
326 if (target_contents_owner_.get())
327 params_->target_contents = NULL;
330 // Assumes ownership of |params_|' target_contents until ReleaseOwnership
331 // is called.
332 void TakeOwnership() {
333 target_contents_owner_.reset(params_->target_contents);
336 // Relinquishes ownership of |params_|' target_contents.
337 WebContents* ReleaseOwnership() {
338 return target_contents_owner_.release();
341 private:
342 chrome::NavigateParams* params_;
343 scoped_ptr<WebContents> target_contents_owner_;
344 DISALLOW_COPY_AND_ASSIGN(ScopedTargetContentsOwner);
347 content::WebContents* CreateTargetContents(const chrome::NavigateParams& params,
348 const GURL& url) {
349 WebContents::CreateParams create_params(
350 params.browser->profile(),
351 tab_util::GetSiteInstanceForNewTab(params.browser->profile(), url));
352 if (params.source_contents) {
353 create_params.initial_size =
354 params.source_contents->GetContainerBounds().size();
355 create_params.created_with_opener = params.created_with_opener;
357 if (params.disposition == NEW_BACKGROUND_TAB)
358 create_params.initially_hidden = true;
360 #if defined(USE_AURA)
361 if (params.browser->window() &&
362 params.browser->window()->GetNativeWindow()) {
363 create_params.context =
364 params.browser->window()->GetNativeWindow();
366 #endif
368 WebContents* target_contents = WebContents::Create(create_params);
370 // New tabs can have WebUI URLs that will make calls back to arbitrary
371 // tab helpers, so the entire set of tab helpers needs to be set up
372 // immediately.
373 BrowserNavigatorWebContentsAdoption::AttachTabHelpers(target_contents);
374 #if defined(ENABLE_EXTENSIONS)
375 extensions::TabHelper::FromWebContents(target_contents)->
376 SetExtensionAppById(params.extension_app_id);
377 #endif
378 return target_contents;
381 // If a prerendered page exists for |url|, replace the page at
382 // |params->target_contents| with it and update to point to the swapped-in
383 // WebContents.
384 bool SwapInPrerender(const GURL& url, chrome::NavigateParams* params) {
385 Profile* profile =
386 Profile::FromBrowserContext(params->target_contents->GetBrowserContext());
387 InstantSearchPrerenderer* prerenderer =
388 InstantSearchPrerenderer::GetForProfile(profile);
389 if (prerenderer && prerenderer->UsePrerenderedPage(url, params))
390 return true;
392 prerender::PrerenderManager* prerender_manager =
393 prerender::PrerenderManagerFactory::GetForProfile(profile);
394 return prerender_manager &&
395 prerender_manager->MaybeUsePrerenderedPage(url, params);
398 chrome::HostDesktopType GetHostDesktop(Browser* browser) {
399 if (browser)
400 return browser->host_desktop_type();
401 return chrome::GetActiveDesktop();
404 } // namespace
406 namespace chrome {
408 NavigateParams::NavigateParams(Browser* a_browser,
409 const GURL& a_url,
410 ui::PageTransition a_transition)
411 : url(a_url),
412 frame_tree_node_id(-1),
413 uses_post(false),
414 target_contents(NULL),
415 source_contents(NULL),
416 disposition(CURRENT_TAB),
417 trusted_source(false),
418 transition(a_transition),
419 is_renderer_initiated(false),
420 tabstrip_index(-1),
421 tabstrip_add_types(TabStripModel::ADD_ACTIVE),
422 window_action(NO_ACTION),
423 user_gesture(true),
424 path_behavior(RESPECT),
425 ref_behavior(IGNORE_REF),
426 browser(a_browser),
427 initiating_profile(NULL),
428 host_desktop_type(GetHostDesktop(a_browser)),
429 should_replace_current_entry(false),
430 created_with_opener(false) {
433 NavigateParams::NavigateParams(Browser* a_browser,
434 WebContents* a_target_contents)
435 : frame_tree_node_id(-1),
436 uses_post(false),
437 target_contents(a_target_contents),
438 source_contents(NULL),
439 disposition(CURRENT_TAB),
440 trusted_source(false),
441 transition(ui::PAGE_TRANSITION_LINK),
442 is_renderer_initiated(false),
443 tabstrip_index(-1),
444 tabstrip_add_types(TabStripModel::ADD_ACTIVE),
445 window_action(NO_ACTION),
446 user_gesture(true),
447 path_behavior(RESPECT),
448 ref_behavior(IGNORE_REF),
449 browser(a_browser),
450 initiating_profile(NULL),
451 host_desktop_type(GetHostDesktop(a_browser)),
452 should_replace_current_entry(false),
453 created_with_opener(false) {
456 NavigateParams::NavigateParams(Profile* a_profile,
457 const GURL& a_url,
458 ui::PageTransition a_transition)
459 : url(a_url),
460 frame_tree_node_id(-1),
461 uses_post(false),
462 target_contents(NULL),
463 source_contents(NULL),
464 disposition(NEW_FOREGROUND_TAB),
465 trusted_source(false),
466 transition(a_transition),
467 is_renderer_initiated(false),
468 tabstrip_index(-1),
469 tabstrip_add_types(TabStripModel::ADD_ACTIVE),
470 window_action(SHOW_WINDOW),
471 user_gesture(true),
472 path_behavior(RESPECT),
473 ref_behavior(IGNORE_REF),
474 browser(NULL),
475 initiating_profile(a_profile),
476 host_desktop_type(chrome::GetActiveDesktop()),
477 should_replace_current_entry(false),
478 created_with_opener(false) {
481 NavigateParams::~NavigateParams() {}
483 void FillNavigateParamsFromOpenURLParams(chrome::NavigateParams* nav_params,
484 const content::OpenURLParams& params) {
485 nav_params->referrer = params.referrer;
486 nav_params->source_site_instance = params.source_site_instance;
487 nav_params->frame_tree_node_id = params.frame_tree_node_id;
488 nav_params->redirect_chain = params.redirect_chain;
489 nav_params->extra_headers = params.extra_headers;
490 nav_params->disposition = params.disposition;
491 nav_params->trusted_source = false;
492 nav_params->is_renderer_initiated = params.is_renderer_initiated;
493 nav_params->transferred_global_request_id =
494 params.transferred_global_request_id;
495 nav_params->should_replace_current_entry =
496 params.should_replace_current_entry;
497 nav_params->uses_post = params.uses_post;
498 nav_params->browser_initiated_post_data = params.browser_initiated_post_data;
501 void Navigate(NavigateParams* params) {
502 Browser* source_browser = params->browser;
503 if (source_browser)
504 params->initiating_profile = source_browser->profile();
505 DCHECK(params->initiating_profile);
507 if (!AdjustNavigateParamsForURL(params))
508 return;
510 #if defined(ENABLE_EXTENSIONS)
511 const extensions::Extension* extension =
512 extensions::ExtensionRegistry::Get(params->initiating_profile)->
513 enabled_extensions().GetExtensionOrAppByURL(params->url);
514 // Platform apps cannot navigate. Block the request.
515 if (extension && extension->is_platform_app())
516 params->url = GURL(chrome::kExtensionInvalidRequestURL);
517 #endif
519 // The browser window may want to adjust the disposition.
520 if (params->disposition == NEW_POPUP &&
521 source_browser &&
522 source_browser->window()) {
523 params->disposition =
524 source_browser->window()->GetDispositionForPopupBounds(
525 params->window_bounds);
528 params->browser = GetBrowserForDisposition(params);
529 if (!params->browser)
530 return;
532 #if defined(USE_ASH)
533 if (source_browser && source_browser != params->browser) {
534 // When the newly created browser was spawned by a browser which visits
535 // another user's desktop, it should be shown on the same desktop as the
536 // originating one. (This is part of the desktop separation per profile).
537 MultiUserWindowManager* manager = MultiUserWindowManager::GetInstance();
538 // Some unit tests have no manager instantiated.
539 if (manager) {
540 aura::Window* src_window = source_browser->window()->GetNativeWindow();
541 aura::Window* new_window = params->browser->window()->GetNativeWindow();
542 const std::string& src_user =
543 manager->GetUserPresentingWindow(src_window);
544 if (src_user != manager->GetUserPresentingWindow(new_window)) {
545 // Once the window gets presented, it should be shown on the same
546 // desktop as the desktop of the creating browser. Note that this
547 // command will not show the window if it wasn't shown yet by the
548 // browser creation.
549 manager->ShowWindowForUser(new_window, src_user);
553 #endif
555 // Navigate() must not return early after this point.
557 if (GetSourceProfile(params) != params->browser->profile()) {
558 // A tab is being opened from a link from a different profile, we must reset
559 // source information that may cause state to be shared.
560 params->source_contents = NULL;
561 params->referrer = content::Referrer();
564 // Make sure the Browser is shown if params call for it.
565 ScopedBrowserShower shower(params);
567 // Makes sure any WebContents created by this function is destroyed if
568 // not properly added to a tab strip.
569 ScopedTargetContentsOwner target_contents_owner(params);
571 // Some dispositions need coercion to base types.
572 NormalizeDisposition(params);
574 // If a new window has been created, it needs to be shown.
575 if (params->window_action == NavigateParams::NO_ACTION &&
576 source_browser != params->browser &&
577 params->browser->tab_strip_model()->empty()) {
578 params->window_action = NavigateParams::SHOW_WINDOW;
581 // If we create a popup window from a non user-gesture, don't activate it.
582 if (params->window_action == NavigateParams::SHOW_WINDOW &&
583 params->disposition == NEW_POPUP &&
584 params->user_gesture == false) {
585 params->window_action = NavigateParams::SHOW_WINDOW_INACTIVE;
588 // Determine if the navigation was user initiated. If it was, we need to
589 // inform the target WebContents, and we may need to update the UI.
590 ui::PageTransition base_transition =
591 ui::PageTransitionStripQualifier(params->transition);
592 bool user_initiated =
593 params->transition & ui::PAGE_TRANSITION_FROM_ADDRESS_BAR ||
594 base_transition == ui::PAGE_TRANSITION_TYPED ||
595 base_transition == ui::PAGE_TRANSITION_AUTO_BOOKMARK ||
596 base_transition == ui::PAGE_TRANSITION_GENERATED ||
597 base_transition == ui::PAGE_TRANSITION_AUTO_TOPLEVEL ||
598 base_transition == ui::PAGE_TRANSITION_RELOAD ||
599 base_transition == ui::PAGE_TRANSITION_KEYWORD;
601 // Check if this is a singleton tab that already exists
602 int singleton_index = chrome::GetIndexOfSingletonTab(params);
604 // Did we use a prerender?
605 bool swapped_in_prerender = false;
607 // If no target WebContents was specified, we need to construct one if
608 // we are supposed to target a new tab; unless it's a singleton that already
609 // exists.
610 if (!params->target_contents && singleton_index < 0) {
611 DCHECK(!params->url.is_empty());
612 if (params->disposition != CURRENT_TAB) {
613 params->target_contents = CreateTargetContents(*params, params->url);
615 // This function takes ownership of |params->target_contents| until it
616 // is added to a TabStripModel.
617 target_contents_owner.TakeOwnership();
618 } else {
619 // ... otherwise if we're loading in the current tab, the target is the
620 // same as the source.
621 DCHECK(params->source_contents);
622 params->target_contents = params->source_contents;
624 // Prerender can only swap in CURRENT_TAB navigations; others have
625 // different sessionStorage namespaces.
626 swapped_in_prerender = SwapInPrerender(params->url, params);
629 if (user_initiated)
630 params->target_contents->UserGestureDone();
632 if (!swapped_in_prerender) {
633 // Try to handle non-navigational URLs that popup dialogs and such, these
634 // should not actually navigate.
635 if (!HandleNonNavigationAboutURL(params->url)) {
636 // Perform the actual navigation, tracking whether it came from the
637 // renderer.
639 LoadURLInContents(params->target_contents, params->url, params);
642 } else {
643 // |target_contents| was specified non-NULL, and so we assume it has already
644 // been navigated appropriately. We need to do nothing more other than
645 // add it to the appropriate tabstrip.
648 // If the user navigated from the omnibox, and the selected tab is going to
649 // lose focus, then make sure the focus for the source tab goes away from the
650 // omnibox.
651 if (params->source_contents &&
652 (params->disposition == NEW_FOREGROUND_TAB ||
653 params->disposition == NEW_WINDOW) &&
654 (params->tabstrip_add_types & TabStripModel::ADD_INHERIT_OPENER))
655 params->source_contents->Focus();
657 if (params->source_contents == params->target_contents ||
658 (swapped_in_prerender && params->disposition == CURRENT_TAB)) {
659 // The navigation occurred in the source tab.
660 params->browser->UpdateUIForNavigationInTab(params->target_contents,
661 params->transition,
662 user_initiated);
663 } else if (singleton_index == -1) {
664 // If some non-default value is set for the index, we should tell the
665 // TabStripModel to respect it.
666 if (params->tabstrip_index != -1)
667 params->tabstrip_add_types |= TabStripModel::ADD_FORCE_INDEX;
669 // The navigation should insert a new tab into the target Browser.
670 params->browser->tab_strip_model()->AddWebContents(
671 params->target_contents,
672 params->tabstrip_index,
673 params->transition,
674 params->tabstrip_add_types);
675 // Now that the |params->target_contents| is safely owned by the target
676 // Browser's TabStripModel, we can release ownership.
677 target_contents_owner.ReleaseOwnership();
680 if (singleton_index >= 0) {
681 WebContents* target =
682 params->browser->tab_strip_model()->GetWebContentsAt(singleton_index);
684 if (target->IsCrashed()) {
685 target->GetController().Reload(true);
686 } else if (params->path_behavior == NavigateParams::IGNORE_AND_NAVIGATE &&
687 target->GetURL() != params->url) {
688 LoadURLInContents(target, params->url, params);
691 // If the singleton tab isn't already selected, select it.
692 if (params->source_contents != params->target_contents) {
693 params->browser->tab_strip_model()->ActivateTabAt(singleton_index,
694 user_initiated);
698 if (params->disposition != CURRENT_TAB) {
699 content::NotificationService::current()->Notify(
700 chrome::NOTIFICATION_TAB_ADDED,
701 content::Source<content::WebContentsDelegate>(params->browser),
702 content::Details<WebContents>(params->target_contents));
706 bool IsURLAllowedInIncognito(const GURL& url,
707 content::BrowserContext* browser_context) {
708 if (url.scheme() == content::kViewSourceScheme) {
709 // A view-source URL is allowed in incognito mode only if the URL itself
710 // is allowed in incognito mode. Remove the "view-source:" from the start
711 // of the URL and validate the rest.
712 std::string stripped_spec = url.spec();
713 DCHECK_GT(stripped_spec.size(), strlen(content::kViewSourceScheme));
714 stripped_spec.erase(0, strlen(content::kViewSourceScheme) + 1);
715 GURL stripped_url(stripped_spec);
716 return stripped_url.is_valid() &&
717 IsURLAllowedInIncognito(stripped_url, browser_context);
719 // Most URLs are allowed in incognito; the following are exceptions.
720 // chrome://extensions is on the list because it redirects to
721 // chrome://settings.
722 if (url.scheme() == content::kChromeUIScheme &&
723 (url.host() == chrome::kChromeUISettingsHost ||
724 url.host() == chrome::kChromeUISettingsFrameHost ||
725 url.host() == chrome::kChromeUIHelpHost ||
726 url.host() == chrome::kChromeUIExtensionsHost ||
727 url.host() == chrome::kChromeUIBookmarksHost ||
728 #if !defined(OS_CHROMEOS)
729 url.host() == chrome::kChromeUIChromeSigninHost ||
730 #endif
731 url.host() == chrome::kChromeUIUberHost ||
732 url.host() == chrome::kChromeUIThumbnailHost ||
733 url.host() == chrome::kChromeUIThumbnailHost2 ||
734 url.host() == chrome::kChromeUIThumbnailListHost ||
735 url.host() == chrome::kChromeUISuggestionsHost ||
736 url.host() == chrome::kChromeUIDevicesHost ||
737 url.host() == chrome::kChromeUIVoiceSearchHost)) {
738 return false;
741 if (url.scheme() == chrome::kChromeSearchScheme &&
742 (url.host() == chrome::kChromeUIThumbnailHost ||
743 url.host() == chrome::kChromeUIThumbnailHost2 ||
744 url.host() == chrome::kChromeUIThumbnailListHost ||
745 url.host() == chrome::kChromeUISuggestionsHost)) {
746 return false;
749 GURL rewritten_url = url;
750 bool reverse_on_redirect = false;
751 content::BrowserURLHandler::GetInstance()->RewriteURLIfNecessary(
752 &rewritten_url, browser_context, &reverse_on_redirect);
754 // Some URLs are mapped to uber subpages. Do not allow them in incognito.
755 return !(rewritten_url.scheme() == content::kChromeUIScheme &&
756 rewritten_url.host() == chrome::kChromeUIUberHost);
759 } // namespace chrome