Cast: Stop logging kVideoFrameSentToEncoder and rename a couple events.
[chromium-blink-merge.git] / chrome / browser / ui / browser_navigator.cc
blob39cf2b550b1763980479d9e781b65c27d219efe2
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/extensions/tab_helper.h"
16 #include "chrome/browser/google/google_url_tracker.h"
17 #include "chrome/browser/prefs/incognito_mode_prefs.h"
18 #include "chrome/browser/prerender/prerender_manager.h"
19 #include "chrome/browser/prerender/prerender_manager_factory.h"
20 #include "chrome/browser/prerender/prerender_util.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_window.h"
27 #include "chrome/browser/ui/host_desktop.h"
28 #include "chrome/browser/ui/omnibox/location_bar.h"
29 #include "chrome/browser/ui/search/instant_search_prerenderer.h"
30 #include "chrome/browser/ui/singleton_tabs.h"
31 #include "chrome/browser/ui/status_bubble.h"
32 #include "chrome/browser/ui/tab_helpers.h"
33 #include "chrome/browser/ui/tabs/tab_strip_model.h"
34 #include "chrome/browser/web_applications/web_app.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/navigation_entry.h"
39 #include "content/public/browser/notification_service.h"
40 #include "content/public/browser/render_view_host.h"
41 #include "content/public/browser/web_contents.h"
42 #include "extensions/browser/extension_registry.h"
43 #include "extensions/common/extension.h"
44 #include "extensions/common/extension_set.h"
46 #if defined(USE_ASH)
47 #include "chrome/browser/ui/ash/multi_user/multi_user_window_manager.h"
48 #endif
49 #if defined(USE_AURA)
50 #include "ui/aura/window.h"
51 #endif
53 using content::GlobalRequestID;
54 using content::NavigationController;
55 using content::WebContents;
57 class BrowserNavigatorWebContentsAdoption {
58 public:
59 static void AttachTabHelpers(content::WebContents* contents) {
60 TabHelpers::AttachTabHelpers(contents);
64 namespace {
66 // Returns true if the specified Browser can open tabs. Not all Browsers support
67 // multiple tabs, such as app frames and popups. This function returns false for
68 // those types of Browser.
69 bool WindowCanOpenTabs(Browser* browser) {
70 return browser->CanSupportWindowFeature(Browser::FEATURE_TABSTRIP) ||
71 browser->tab_strip_model()->empty();
74 // Finds an existing Browser compatible with |profile|, making a new one if no
75 // such Browser is located.
76 Browser* GetOrCreateBrowser(Profile* profile,
77 chrome::HostDesktopType host_desktop_type) {
78 Browser* browser = chrome::FindTabbedBrowser(profile, false,
79 host_desktop_type);
80 return browser ? browser : new Browser(
81 Browser::CreateParams(profile, host_desktop_type));
84 // Change some of the navigation parameters based on the particular URL.
85 // Currently this applies to some chrome:// pages which we always want to open
86 // in a non-incognito window. Note that even though a ChromeOS guest session is
87 // technically an incognito window, these URLs are allowed.
88 // Returns true on success. Otherwise, if changing params leads the browser into
89 // an erroneous state, returns false.
90 bool AdjustNavigateParamsForURL(chrome::NavigateParams* params) {
91 if (params->target_contents != NULL ||
92 chrome::IsURLAllowedInIncognito(params->url,
93 params->initiating_profile) ||
94 params->initiating_profile->IsGuestSession()) {
95 return true;
98 Profile* profile = params->initiating_profile;
100 if (profile->IsOffTheRecord() || params->disposition == OFF_THE_RECORD) {
101 profile = profile->GetOriginalProfile();
103 // If incognito is forced, we punt.
104 PrefService* prefs = profile->GetPrefs();
105 if (prefs && IncognitoModePrefs::GetAvailability(prefs) ==
106 IncognitoModePrefs::FORCED) {
107 return false;
110 params->disposition = SINGLETON_TAB;
111 params->browser = GetOrCreateBrowser(profile, params->host_desktop_type);
112 params->window_action = chrome::NavigateParams::SHOW_WINDOW;
115 return true;
118 // Returns a Browser that can host the navigation or tab addition specified in
119 // |params|. This might just return the same Browser specified in |params|, or
120 // some other if that Browser is deemed incompatible.
121 Browser* GetBrowserForDisposition(chrome::NavigateParams* params) {
122 // If no source WebContents was specified, we use the selected one from
123 // the target browser. This must happen first, before
124 // GetBrowserForDisposition() has a chance to replace |params->browser| with
125 // another one.
126 if (!params->source_contents && params->browser) {
127 params->source_contents =
128 params->browser->tab_strip_model()->GetActiveWebContents();
131 Profile* profile = params->initiating_profile;
133 switch (params->disposition) {
134 case CURRENT_TAB:
135 if (params->browser)
136 return params->browser;
137 // Find a compatible window and re-execute this command in it. Otherwise
138 // re-run with NEW_WINDOW.
139 return GetOrCreateBrowser(profile, params->host_desktop_type);
140 case SINGLETON_TAB:
141 case NEW_FOREGROUND_TAB:
142 case NEW_BACKGROUND_TAB:
143 // See if we can open the tab in the window this navigator is bound to.
144 if (params->browser && WindowCanOpenTabs(params->browser))
145 return params->browser;
146 // Find a compatible window and re-execute this command in it. Otherwise
147 // re-run with NEW_WINDOW.
148 return GetOrCreateBrowser(profile, params->host_desktop_type);
149 case NEW_POPUP: {
150 // Make a new popup window.
151 // Coerce app-style if |source| represents an app.
152 std::string app_name;
153 if (!params->extension_app_id.empty()) {
154 app_name = web_app::GenerateApplicationNameFromExtensionId(
155 params->extension_app_id);
156 } else if (params->browser && !params->browser->app_name().empty()) {
157 app_name = params->browser->app_name();
158 } else if (params->source_contents) {
159 extensions::TabHelper* extensions_tab_helper =
160 extensions::TabHelper::FromWebContents(params->source_contents);
161 if (extensions_tab_helper && extensions_tab_helper->is_app()) {
162 app_name = web_app::GenerateApplicationNameFromExtensionId(
163 extensions_tab_helper->extension_app()->id());
166 if (app_name.empty()) {
167 Browser::CreateParams browser_params(
168 Browser::TYPE_POPUP, profile, params->host_desktop_type);
169 browser_params.trusted_source = params->trusted_source;
170 browser_params.initial_bounds = params->window_bounds;
171 return new Browser(browser_params);
174 return new Browser(Browser::CreateParams::CreateForApp(
175 app_name,
176 params->trusted_source,
177 params->window_bounds,
178 profile,
179 params->host_desktop_type));
181 case NEW_WINDOW: {
182 // Make a new normal browser window.
183 return new Browser(Browser::CreateParams(profile,
184 params->host_desktop_type));
186 case OFF_THE_RECORD:
187 // Make or find an incognito window.
188 return GetOrCreateBrowser(profile->GetOffTheRecordProfile(),
189 params->host_desktop_type);
190 // The following types all result in no navigation.
191 case SUPPRESS_OPEN:
192 case SAVE_TO_DISK:
193 case IGNORE_ACTION:
194 return NULL;
195 default:
196 NOTREACHED();
198 return NULL;
201 // Fix disposition and other parameter values depending on prevailing
202 // conditions.
203 void NormalizeDisposition(chrome::NavigateParams* params) {
204 // Calculate the WindowOpenDisposition if necessary.
205 if (params->browser->tab_strip_model()->empty() &&
206 (params->disposition == NEW_BACKGROUND_TAB ||
207 params->disposition == CURRENT_TAB ||
208 params->disposition == SINGLETON_TAB)) {
209 params->disposition = NEW_FOREGROUND_TAB;
211 if (params->browser->profile()->IsOffTheRecord() &&
212 params->disposition == OFF_THE_RECORD) {
213 params->disposition = NEW_FOREGROUND_TAB;
215 if (!params->source_contents && params->disposition == CURRENT_TAB)
216 params->disposition = NEW_FOREGROUND_TAB;
218 switch (params->disposition) {
219 case NEW_BACKGROUND_TAB:
220 // Disposition trumps add types. ADD_ACTIVE is a default, so we need to
221 // remove it if disposition implies the tab is going to open in the
222 // background.
223 params->tabstrip_add_types &= ~TabStripModel::ADD_ACTIVE;
224 break;
226 case NEW_WINDOW:
227 case NEW_POPUP:
228 // Code that wants to open a new window typically expects it to be shown
229 // automatically.
230 if (params->window_action == chrome::NavigateParams::NO_ACTION)
231 params->window_action = chrome::NavigateParams::SHOW_WINDOW;
232 // Fall-through.
233 case NEW_FOREGROUND_TAB:
234 case SINGLETON_TAB:
235 params->tabstrip_add_types |= TabStripModel::ADD_ACTIVE;
236 break;
238 default:
239 break;
243 // Obtain the profile used by the code that originated the Navigate() request.
244 Profile* GetSourceProfile(chrome::NavigateParams* params) {
245 if (params->source_contents) {
246 return Profile::FromBrowserContext(
247 params->source_contents->GetBrowserContext());
250 return params->initiating_profile;
253 void LoadURLInContents(WebContents* target_contents,
254 const GURL& url,
255 chrome::NavigateParams* params) {
256 NavigationController::LoadURLParams load_url_params(url);
257 load_url_params.referrer = params->referrer;
258 load_url_params.frame_tree_node_id = params->frame_tree_node_id;
259 load_url_params.redirect_chain = params->redirect_chain;
260 load_url_params.transition_type = params->transition;
261 load_url_params.extra_headers = params->extra_headers;
262 load_url_params.should_replace_current_entry =
263 params->should_replace_current_entry;
265 if (params->transferred_global_request_id != GlobalRequestID()) {
266 load_url_params.is_renderer_initiated = params->is_renderer_initiated;
267 load_url_params.transferred_global_request_id =
268 params->transferred_global_request_id;
269 } else if (params->is_renderer_initiated) {
270 load_url_params.is_renderer_initiated = true;
273 // Only allows the browser-initiated navigation to use POST.
274 if (params->uses_post && !params->is_renderer_initiated) {
275 load_url_params.load_type =
276 NavigationController::LOAD_TYPE_BROWSER_INITIATED_HTTP_POST;
277 load_url_params.browser_initiated_post_data =
278 params->browser_initiated_post_data;
280 target_contents->GetController().LoadURLWithParams(load_url_params);
283 // This class makes sure the Browser object held in |params| is made visible
284 // by the time it goes out of scope, provided |params| wants it to be shown.
285 class ScopedBrowserShower {
286 public:
287 explicit ScopedBrowserShower(chrome::NavigateParams* params)
288 : params_(params) {
290 ~ScopedBrowserShower() {
291 if (params_->window_action == chrome::NavigateParams::SHOW_WINDOW_INACTIVE)
292 params_->browser->window()->ShowInactive();
293 else if (params_->window_action == chrome::NavigateParams::SHOW_WINDOW)
294 params_->browser->window()->Show();
296 private:
297 chrome::NavigateParams* params_;
298 DISALLOW_COPY_AND_ASSIGN(ScopedBrowserShower);
301 // This class manages the lifetime of a WebContents created by the
302 // Navigate() function. When Navigate() creates a WebContents for a URL,
303 // an instance of this class takes ownership of it via TakeOwnership() until the
304 // WebContents is added to a tab strip at which time ownership is
305 // relinquished via ReleaseOwnership(). If this object goes out of scope without
306 // being added to a tab strip, the created WebContents is deleted to
307 // avoid a leak and the params->target_contents field is set to NULL.
308 class ScopedTargetContentsOwner {
309 public:
310 explicit ScopedTargetContentsOwner(chrome::NavigateParams* params)
311 : params_(params) {
313 ~ScopedTargetContentsOwner() {
314 if (target_contents_owner_.get())
315 params_->target_contents = NULL;
318 // Assumes ownership of |params_|' target_contents until ReleaseOwnership
319 // is called.
320 void TakeOwnership() {
321 target_contents_owner_.reset(params_->target_contents);
324 // Relinquishes ownership of |params_|' target_contents.
325 WebContents* ReleaseOwnership() {
326 return target_contents_owner_.release();
329 private:
330 chrome::NavigateParams* params_;
331 scoped_ptr<WebContents> target_contents_owner_;
332 DISALLOW_COPY_AND_ASSIGN(ScopedTargetContentsOwner);
335 content::WebContents* CreateTargetContents(const chrome::NavigateParams& params,
336 const GURL& url) {
337 WebContents::CreateParams create_params(
338 params.browser->profile(),
339 tab_util::GetSiteInstanceForNewTab(params.browser->profile(), url));
340 if (params.source_contents) {
341 create_params.initial_size =
342 params.source_contents->GetContainerBounds().size();
343 if (params.should_set_opener)
344 create_params.opener = params.source_contents;
346 if (params.disposition == NEW_BACKGROUND_TAB)
347 create_params.initially_hidden = true;
349 #if defined(USE_AURA)
350 if (params.browser->window() &&
351 params.browser->window()->GetNativeWindow()) {
352 create_params.context =
353 params.browser->window()->GetNativeWindow();
355 #endif
357 WebContents* target_contents = WebContents::Create(create_params);
359 // New tabs can have WebUI URLs that will make calls back to arbitrary
360 // tab helpers, so the entire set of tab helpers needs to be set up
361 // immediately.
362 BrowserNavigatorWebContentsAdoption::AttachTabHelpers(target_contents);
363 extensions::TabHelper::FromWebContents(target_contents)->
364 SetExtensionAppById(params.extension_app_id);
365 return target_contents;
368 // If a prerendered page exists for |url|, replace the page at
369 // |params->target_contents| with it and update to point to the swapped-in
370 // WebContents.
371 bool SwapInPrerender(const GURL& url, chrome::NavigateParams* params) {
372 Profile* profile =
373 Profile::FromBrowserContext(params->target_contents->GetBrowserContext());
374 InstantSearchPrerenderer* prerenderer =
375 InstantSearchPrerenderer::GetForProfile(profile);
376 if (prerenderer && prerenderer->UsePrerenderedPage(url, params))
377 return true;
379 prerender::PrerenderManager* prerender_manager =
380 prerender::PrerenderManagerFactory::GetForProfile(profile);
381 return prerender_manager &&
382 prerender_manager->MaybeUsePrerenderedPage(url, params);
385 chrome::HostDesktopType GetHostDesktop(Browser* browser) {
386 if (browser)
387 return browser->host_desktop_type();
388 return chrome::GetActiveDesktop();
391 } // namespace
393 namespace chrome {
395 NavigateParams::NavigateParams(Browser* a_browser,
396 const GURL& a_url,
397 content::PageTransition a_transition)
398 : url(a_url),
399 frame_tree_node_id(-1),
400 uses_post(false),
401 target_contents(NULL),
402 source_contents(NULL),
403 disposition(CURRENT_TAB),
404 trusted_source(false),
405 transition(a_transition),
406 is_renderer_initiated(false),
407 tabstrip_index(-1),
408 tabstrip_add_types(TabStripModel::ADD_ACTIVE),
409 window_action(NO_ACTION),
410 user_gesture(true),
411 path_behavior(RESPECT),
412 ref_behavior(IGNORE_REF),
413 browser(a_browser),
414 initiating_profile(NULL),
415 host_desktop_type(GetHostDesktop(a_browser)),
416 should_replace_current_entry(false),
417 should_set_opener(false) {
420 NavigateParams::NavigateParams(Browser* a_browser,
421 WebContents* a_target_contents)
422 : frame_tree_node_id(-1),
423 uses_post(false),
424 target_contents(a_target_contents),
425 source_contents(NULL),
426 disposition(CURRENT_TAB),
427 trusted_source(false),
428 transition(content::PAGE_TRANSITION_LINK),
429 is_renderer_initiated(false),
430 tabstrip_index(-1),
431 tabstrip_add_types(TabStripModel::ADD_ACTIVE),
432 window_action(NO_ACTION),
433 user_gesture(true),
434 path_behavior(RESPECT),
435 ref_behavior(IGNORE_REF),
436 browser(a_browser),
437 initiating_profile(NULL),
438 host_desktop_type(GetHostDesktop(a_browser)),
439 should_replace_current_entry(false),
440 should_set_opener(false) {
443 NavigateParams::NavigateParams(Profile* a_profile,
444 const GURL& a_url,
445 content::PageTransition a_transition)
446 : url(a_url),
447 frame_tree_node_id(-1),
448 uses_post(false),
449 target_contents(NULL),
450 source_contents(NULL),
451 disposition(NEW_FOREGROUND_TAB),
452 trusted_source(false),
453 transition(a_transition),
454 is_renderer_initiated(false),
455 tabstrip_index(-1),
456 tabstrip_add_types(TabStripModel::ADD_ACTIVE),
457 window_action(SHOW_WINDOW),
458 user_gesture(true),
459 path_behavior(RESPECT),
460 ref_behavior(IGNORE_REF),
461 browser(NULL),
462 initiating_profile(a_profile),
463 host_desktop_type(chrome::GetActiveDesktop()),
464 should_replace_current_entry(false),
465 should_set_opener(false) {
468 NavigateParams::~NavigateParams() {}
470 void FillNavigateParamsFromOpenURLParams(chrome::NavigateParams* nav_params,
471 const content::OpenURLParams& params) {
472 nav_params->referrer = params.referrer;
473 nav_params->frame_tree_node_id = params.frame_tree_node_id;
474 nav_params->redirect_chain = params.redirect_chain;
475 nav_params->extra_headers = params.extra_headers;
476 nav_params->disposition = params.disposition;
477 nav_params->trusted_source = false;
478 nav_params->is_renderer_initiated = params.is_renderer_initiated;
479 nav_params->transferred_global_request_id =
480 params.transferred_global_request_id;
481 nav_params->should_replace_current_entry =
482 params.should_replace_current_entry;
483 nav_params->uses_post = params.uses_post;
484 nav_params->browser_initiated_post_data = params.browser_initiated_post_data;
487 void Navigate(NavigateParams* params) {
488 Browser* source_browser = params->browser;
489 if (source_browser)
490 params->initiating_profile = source_browser->profile();
491 DCHECK(params->initiating_profile);
493 if (!AdjustNavigateParamsForURL(params))
494 return;
496 const extensions::Extension* extension =
497 extensions::ExtensionRegistry::Get(params->initiating_profile)->
498 enabled_extensions().GetExtensionOrAppByURL(params->url);
499 // Platform apps cannot navigate. Block the request.
500 if (extension && extension->is_platform_app())
501 params->url = GURL(chrome::kExtensionInvalidRequestURL);
503 // The browser window may want to adjust the disposition.
504 if (params->disposition == NEW_POPUP &&
505 source_browser &&
506 source_browser->window()) {
507 params->disposition =
508 source_browser->window()->GetDispositionForPopupBounds(
509 params->window_bounds);
512 params->browser = GetBrowserForDisposition(params);
513 if (!params->browser)
514 return;
516 #if defined(USE_ASH)
517 if (source_browser && source_browser != params->browser) {
518 // When the newly created browser was spawned by a browser which visits
519 // another user's desktop, it should be shown on the same desktop as the
520 // originating one. (This is part of the desktop separation per profile).
521 MultiUserWindowManager* manager = MultiUserWindowManager::GetInstance();
522 // Some unit tests have no manager instantiated.
523 if (manager) {
524 aura::Window* src_window = source_browser->window()->GetNativeWindow();
525 aura::Window* new_window = params->browser->window()->GetNativeWindow();
526 const std::string& src_user =
527 manager->GetUserPresentingWindow(src_window);
528 if (src_user != manager->GetUserPresentingWindow(new_window)) {
529 // Once the window gets presented, it should be shown on the same
530 // desktop as the desktop of the creating browser. Note that this
531 // command will not show the window if it wasn't shown yet by the
532 // browser creation.
533 manager->ShowWindowForUser(new_window, src_user);
537 #endif
539 // Navigate() must not return early after this point.
541 if (GetSourceProfile(params) != params->browser->profile()) {
542 // A tab is being opened from a link from a different profile, we must reset
543 // source information that may cause state to be shared.
544 params->source_contents = NULL;
545 params->referrer = content::Referrer();
548 // Make sure the Browser is shown if params call for it.
549 ScopedBrowserShower shower(params);
551 // Makes sure any WebContents created by this function is destroyed if
552 // not properly added to a tab strip.
553 ScopedTargetContentsOwner target_contents_owner(params);
555 // Some dispositions need coercion to base types.
556 NormalizeDisposition(params);
558 // If a new window has been created, it needs to be shown.
559 if (params->window_action == NavigateParams::NO_ACTION &&
560 source_browser != params->browser &&
561 params->browser->tab_strip_model()->empty()) {
562 params->window_action = NavigateParams::SHOW_WINDOW;
565 // If we create a popup window from a non user-gesture, don't activate it.
566 if (params->window_action == NavigateParams::SHOW_WINDOW &&
567 params->disposition == NEW_POPUP &&
568 params->user_gesture == false) {
569 params->window_action = NavigateParams::SHOW_WINDOW_INACTIVE;
572 // Determine if the navigation was user initiated. If it was, we need to
573 // inform the target WebContents, and we may need to update the UI.
574 content::PageTransition base_transition =
575 content::PageTransitionStripQualifier(params->transition);
576 bool user_initiated =
577 params->transition & content::PAGE_TRANSITION_FROM_ADDRESS_BAR ||
578 base_transition == content::PAGE_TRANSITION_TYPED ||
579 base_transition == content::PAGE_TRANSITION_AUTO_BOOKMARK ||
580 base_transition == content::PAGE_TRANSITION_GENERATED ||
581 base_transition == content::PAGE_TRANSITION_AUTO_TOPLEVEL ||
582 base_transition == content::PAGE_TRANSITION_RELOAD ||
583 base_transition == content::PAGE_TRANSITION_KEYWORD;
585 // Check if this is a singleton tab that already exists
586 int singleton_index = chrome::GetIndexOfSingletonTab(params);
588 // Did we use a prerender?
589 bool swapped_in_prerender = false;
591 // If no target WebContents was specified, we need to construct one if
592 // we are supposed to target a new tab; unless it's a singleton that already
593 // exists.
594 if (!params->target_contents && singleton_index < 0) {
595 GURL url;
596 if (params->url.is_empty()) {
597 url = params->browser->profile()->GetHomePage();
598 params->transition = content::PageTransitionFromInt(
599 params->transition | content::PAGE_TRANSITION_HOME_PAGE);
600 } else {
601 url = params->url;
604 if (params->disposition != CURRENT_TAB) {
605 params->target_contents = CreateTargetContents(*params, url);
607 // This function takes ownership of |params->target_contents| until it
608 // is added to a TabStripModel.
609 target_contents_owner.TakeOwnership();
610 } else {
611 // ... otherwise if we're loading in the current tab, the target is the
612 // same as the source.
613 DCHECK(params->source_contents);
614 params->target_contents = params->source_contents;
615 DCHECK(params->target_contents);
616 // Prerender expects |params->target_contents| to be attached to a browser
617 // window, so only call for CURRENT_TAB navigations. (Others are currently
618 // unsupported because of session storage namespaces anyway.)
619 // Notice that this includes middle-clicking, since middle clicking
620 // translates into a chrome::Navigate call with no URL followed by a
621 // CURRENT_TAB navigation.
622 // TODO(tburkard): We can actually swap in in non-CURRENT_TAB cases, as
623 // long as the WebContents we swap into is part of a TabStrip model.
624 // Therefore, we should swap in regardless of CURRENT_TAB, and instead,
625 // check in the swapin function whether the WebContents is not in a
626 // TabStrip model, in which case we must not swap in.
627 swapped_in_prerender = SwapInPrerender(url, params);
630 if (user_initiated)
631 params->target_contents->UserGestureDone();
633 if (!swapped_in_prerender) {
634 // Try to handle non-navigational URLs that popup dialogs and such, these
635 // should not actually navigate.
636 if (!HandleNonNavigationAboutURL(url)) {
637 // Perform the actual navigation, tracking whether it came from the
638 // renderer.
640 LoadURLInContents(params->target_contents, url, params);
641 // For prerender bookkeeping purposes, record that this pending navigate
642 // originated from chrome::Navigate.
643 content::NavigationEntry* entry =
644 params->target_contents->GetController().GetPendingEntry();
645 if (entry)
646 entry->SetExtraData(prerender::kChromeNavigateExtraDataKey,
647 base::string16());
650 } else {
651 // |target_contents| was specified non-NULL, and so we assume it has already
652 // been navigated appropriately. We need to do nothing more other than
653 // add it to the appropriate tabstrip.
656 // If the user navigated from the omnibox, and the selected tab is going to
657 // lose focus, then make sure the focus for the source tab goes away from the
658 // omnibox.
659 if (params->source_contents &&
660 (params->disposition == NEW_FOREGROUND_TAB ||
661 params->disposition == NEW_WINDOW) &&
662 (params->tabstrip_add_types & TabStripModel::ADD_INHERIT_OPENER))
663 params->source_contents->Focus();
665 if (params->source_contents == params->target_contents ||
666 (swapped_in_prerender && params->disposition == CURRENT_TAB)) {
667 // The navigation occurred in the source tab.
668 params->browser->UpdateUIForNavigationInTab(params->target_contents,
669 params->transition,
670 user_initiated);
671 } else if (singleton_index == -1) {
672 // If some non-default value is set for the index, we should tell the
673 // TabStripModel to respect it.
674 if (params->tabstrip_index != -1)
675 params->tabstrip_add_types |= TabStripModel::ADD_FORCE_INDEX;
677 // The navigation should insert a new tab into the target Browser.
678 params->browser->tab_strip_model()->AddWebContents(
679 params->target_contents,
680 params->tabstrip_index,
681 params->transition,
682 params->tabstrip_add_types);
683 // Now that the |params->target_contents| is safely owned by the target
684 // Browser's TabStripModel, we can release ownership.
685 target_contents_owner.ReleaseOwnership();
688 if (singleton_index >= 0) {
689 WebContents* target =
690 params->browser->tab_strip_model()->GetWebContentsAt(singleton_index);
692 if (target->IsCrashed()) {
693 target->GetController().Reload(true);
694 } else if (params->path_behavior == NavigateParams::IGNORE_AND_NAVIGATE &&
695 target->GetURL() != params->url) {
696 LoadURLInContents(target, params->url, params);
697 // For prerender bookkeeping purposes, record that this pending navigate
698 // originated from chrome::Navigate.
699 content::NavigationEntry* entry =
700 target->GetController().GetPendingEntry();
701 if (entry)
702 entry->SetExtraData(prerender::kChromeNavigateExtraDataKey,
703 base::string16());
706 // If the singleton tab isn't already selected, select it.
707 if (params->source_contents != params->target_contents) {
708 params->browser->tab_strip_model()->ActivateTabAt(singleton_index,
709 user_initiated);
713 if (params->disposition != CURRENT_TAB) {
714 content::NotificationService::current()->Notify(
715 chrome::NOTIFICATION_TAB_ADDED,
716 content::Source<content::WebContentsDelegate>(params->browser),
717 content::Details<WebContents>(params->target_contents));
721 bool IsURLAllowedInIncognito(const GURL& url,
722 content::BrowserContext* browser_context) {
723 if (url.scheme() == content::kViewSourceScheme) {
724 // A view-source URL is allowed in incognito mode only if the URL itself
725 // is allowed in incognito mode. Remove the "view-source:" from the start
726 // of the URL and validate the rest.
727 std::string stripped_spec = url.spec();
728 DCHECK_GT(stripped_spec.size(), strlen(content::kViewSourceScheme));
729 stripped_spec.erase(0, strlen(content::kViewSourceScheme) + 1);
730 GURL stripped_url(stripped_spec);
731 return stripped_url.is_valid() &&
732 IsURLAllowedInIncognito(stripped_url, browser_context);
734 // Most URLs are allowed in incognito; the following are exceptions.
735 // chrome://extensions is on the list because it redirects to
736 // chrome://settings.
737 if (url.scheme() == content::kChromeUIScheme &&
738 (url.host() == chrome::kChromeUISettingsHost ||
739 url.host() == chrome::kChromeUISettingsFrameHost ||
740 url.host() == chrome::kChromeUIExtensionsHost ||
741 url.host() == chrome::kChromeUIBookmarksHost ||
742 #if !defined(OS_CHROMEOS)
743 url.host() == chrome::kChromeUIChromeSigninHost ||
744 #endif
745 url.host() == chrome::kChromeUIUberHost ||
746 url.host() == chrome::kChromeUIThumbnailHost ||
747 url.host() == chrome::kChromeUIThumbnailHost2 ||
748 url.host() == chrome::kChromeUIThumbnailListHost ||
749 url.host() == chrome::kChromeUISuggestionsHost ||
750 url.host() == chrome::kChromeUIDevicesHost)) {
751 return false;
754 if (url.scheme() == chrome::kChromeSearchScheme &&
755 (url.host() == chrome::kChromeUIThumbnailHost ||
756 url.host() == chrome::kChromeUIThumbnailHost2 ||
757 url.host() == chrome::kChromeUIThumbnailListHost ||
758 url.host() == chrome::kChromeUISuggestionsHost)) {
759 return false;
762 GURL rewritten_url = url;
763 bool reverse_on_redirect = false;
764 content::BrowserURLHandler::GetInstance()->RewriteURLIfNecessary(
765 &rewritten_url, browser_context, &reverse_on_redirect);
767 // Some URLs are mapped to uber subpages. Do not allow them in incognito.
768 return !(rewritten_url.scheme() == content::kChromeUIScheme &&
769 rewritten_url.host() == chrome::kChromeUIUberHost);
772 } // namespace chrome