diff options
Diffstat (limited to 'chrome')
48 files changed, 206 insertions, 13264 deletions
diff --git a/chrome/DEPS b/chrome/DEPS index 752b1c60..a64c1c0 100644 --- a/chrome/DEPS +++ b/chrome/DEPS @@ -1,5 +1,6 @@ include_rules = [ "+app", + "+content", "+gpu", "+net", "+printing", diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc index a4f2f26..c29c2d1 100644 --- a/chrome/browser/prefs/browser_prefs.cc +++ b/chrome/browser/prefs/browser_prefs.cc @@ -46,11 +46,11 @@ #include "chrome/browser/search_engines/template_url_prepopulate_data.h" #include "chrome/browser/ssl/ssl_manager.h" #include "chrome/browser/sync/signin_manager.h" -#include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/browser/tabs/pinned_tab_codec.h" #include "chrome/browser/task_manager/task_manager.h" #include "chrome/browser/translate/translate_prefs.h" #include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" #include "chrome/browser/upgrade_detector.h" #include "chrome/browser/webui/flags_ui.h" #include "chrome/common/pref_names.h" @@ -124,7 +124,7 @@ void RegisterUserPrefs(PrefService* user_prefs) { chrome_browser_net::RegisterUserPrefs(user_prefs); DownloadPrefs::RegisterUserPrefs(user_prefs); bookmark_utils::RegisterUserPrefs(user_prefs); - TabContents::RegisterUserPrefs(user_prefs); + TabContentsWrapper::RegisterUserPrefs(user_prefs); TemplateURLPrepopulateData::RegisterUserPrefs(user_prefs); ExtensionWebUI::RegisterUserPrefs(user_prefs); ExtensionsUI::RegisterUserPrefs(user_prefs); diff --git a/chrome/browser/renderer_host/render_view_host.cc b/chrome/browser/renderer_host/render_view_host.cc index 88c4746..9c96e6f 100644 --- a/chrome/browser/renderer_host/render_view_host.cc +++ b/chrome/browser/renderer_host/render_view_host.cc @@ -792,8 +792,6 @@ bool RenderViewHost::OnMessageReceived(const IPC::Message& msg) { OnRequestUndockDevToolsWindow) IPC_MESSAGE_HANDLER(ViewHostMsg_DevToolsRuntimePropertyChanged, OnDevToolsRuntimePropertyChanged) - IPC_MESSAGE_FORWARD(ViewHostMsg_JSOutOfMemory, delegate_, - RenderViewHostDelegate::OnJSOutOfMemory) IPC_MESSAGE_HANDLER(ViewHostMsg_ShouldClose_ACK, OnMsgShouldCloseACK) IPC_MESSAGE_HANDLER(ViewHostMsg_ExtensionRequest, OnExtensionRequest) IPC_MESSAGE_HANDLER(ViewHostMsg_SelectionChanged, OnMsgSelectionChanged) diff --git a/chrome/browser/renderer_host/render_view_host_delegate.h b/chrome/browser/renderer_host/render_view_host_delegate.h index 123b2b8c..b98e7ea 100644 --- a/chrome/browser/renderer_host/render_view_host_delegate.h +++ b/chrome/browser/renderer_host/render_view_host_delegate.h @@ -546,9 +546,6 @@ class RenderViewHostDelegate : public IPC::Channel::Listener { // refocus on the modal dialog, flash title etc). virtual void OnIgnoredUIEvent() {} - // Notification from the renderer that JS runs out of memory. - virtual void OnJSOutOfMemory() {} - // Notification that the renderer has become unresponsive. The // delegate can use this notification to show a warning to the user. virtual void RendererUnresponsive(RenderViewHost* render_view_host, diff --git a/chrome/browser/tab_contents/background_contents.cc b/chrome/browser/tab_contents/background_contents.cc deleted file mode 100644 index 059d393..0000000 --- a/chrome/browser/tab_contents/background_contents.cc +++ /dev/null @@ -1,269 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/tab_contents/background_contents.h" - -#include "chrome/browser/background_contents_service.h" -#include "chrome/browser/browsing_instance.h" -#include "chrome/browser/desktop_notification_handler.h" -#include "chrome/browser/profiles/profile.h" -#include "chrome/browser/renderer_host/render_view_host.h" -#include "chrome/browser/renderer_host/site_instance.h" -#include "chrome/browser/renderer_preferences_util.h" -#include "chrome/common/extensions/extension_constants.h" -#include "chrome/common/notification_service.h" -#include "chrome/common/url_constants.h" -#include "chrome/common/view_types.h" -#include "chrome/common/render_messages_params.h" -#include "ui/gfx/rect.h" - -//////////////// -// BackgroundContents - -BackgroundContents::BackgroundContents(SiteInstance* site_instance, - int routing_id, - Delegate* delegate) - : delegate_(delegate) { - Profile* profile = site_instance->browsing_instance()->profile(); - - // TODO(rafaelw): Implement correct session storage. - render_view_host_ = new RenderViewHost(site_instance, this, routing_id, NULL); - render_view_host_->AllowScriptToClose(true); - - // Close ourselves when the application is shutting down. - registrar_.Add(this, NotificationType::APP_TERMINATING, - NotificationService::AllSources()); - - // Register for our parent profile to shutdown, so we can shut ourselves down - // as well (should only be called for OTR profiles, as we should receive - // APP_TERMINATING before non-OTR profiles are destroyed). - registrar_.Add(this, NotificationType::PROFILE_DESTROYED, - Source<Profile>(profile)); - desktop_notification_handler_.reset( - new DesktopNotificationHandler(NULL, site_instance->GetProcess())); -} - -// Exposed to allow creating mocks. -BackgroundContents::BackgroundContents() - : delegate_(NULL), - render_view_host_(NULL) { -} - -BackgroundContents::~BackgroundContents() { - if (!render_view_host_) // Will be null for unit tests. - return; - Profile* profile = render_view_host_->process()->profile(); - NotificationService::current()->Notify( - NotificationType::BACKGROUND_CONTENTS_DELETED, - Source<Profile>(profile), - Details<BackgroundContents>(this)); - render_view_host_->Shutdown(); // deletes render_view_host -} - -BackgroundContents* BackgroundContents::GetAsBackgroundContents() { - return this; -} - -RenderViewHostDelegate::View* BackgroundContents::GetViewDelegate() { - return this; -} - -const GURL& BackgroundContents::GetURL() const { - return url_; -} - -ViewType::Type BackgroundContents::GetRenderViewType() const { - return ViewType::BACKGROUND_CONTENTS; -} - -int BackgroundContents::GetBrowserWindowID() const { - return extension_misc::kUnknownWindowId; -} - -void BackgroundContents::DidNavigate( - RenderViewHost* render_view_host, - const ViewHostMsg_FrameNavigate_Params& params) { - // We only care when the outer frame changes. - if (!PageTransition::IsMainFrame(params.transition)) - return; - - // Note: because BackgroundContents are only available to extension apps, - // navigation is limited to urls within the app's extent. This is enforced in - // RenderView::decidePolicyForNaviation. If BackgroundContents become - // available as a part of the web platform, it probably makes sense to have - // some way to scope navigation of a background page to its opener's security - // origin. Note: if the first navigation is to a URL outside the app's - // extent a background page will be opened but will remain at about:blank. - url_ = params.url; - - Profile* profile = render_view_host->process()->profile(); - NotificationService::current()->Notify( - NotificationType::BACKGROUND_CONTENTS_NAVIGATED, - Source<Profile>(profile), - Details<BackgroundContents>(this)); -} - -void BackgroundContents::RunJavaScriptMessage( - const std::wstring& message, - const std::wstring& default_prompt, - const GURL& frame_url, - const int flags, - IPC::Message* reply_msg, - bool* did_suppress_message) { - // TODO(rafaelw): Implement, The JavaScriptModalDialog needs to learn about - // BackgroundContents. - *did_suppress_message = true; -} - -bool BackgroundContents::PreHandleKeyboardEvent( - const NativeWebKeyboardEvent& event, - bool* is_keyboard_shortcut) { - return false; -} - -void BackgroundContents::Observe(NotificationType type, - const NotificationSource& source, - const NotificationDetails& details) { - // TODO(rafaelw): Implement pagegroup ref-counting so that non-persistent - // background pages are closed when the last referencing frame is closed. - switch (type.value) { - case NotificationType::PROFILE_DESTROYED: - case NotificationType::APP_TERMINATING: { - delete this; - break; - } - default: - NOTREACHED() << "Unexpected notification sent."; - break; - } -} - -void BackgroundContents::OnMessageBoxClosed(IPC::Message* reply_msg, - bool success, - const std::wstring& prompt) { - render_view_host_->JavaScriptMessageBoxClosed(reply_msg, success, prompt); -} - -gfx::NativeWindow BackgroundContents::GetMessageBoxRootWindow() { - NOTIMPLEMENTED(); - return NULL; -} - -TabContents* BackgroundContents::AsTabContents() { - return NULL; -} - -ExtensionHost* BackgroundContents::AsExtensionHost() { - return NULL; -} - -void BackgroundContents::UpdateInspectorSetting(const std::string& key, - const std::string& value) { - Profile* profile = render_view_host_->process()->profile(); - RenderViewHostDelegateHelper::UpdateInspectorSetting(profile, key, value); -} - -void BackgroundContents::ClearInspectorSettings() { - Profile* profile = render_view_host_->process()->profile(); - RenderViewHostDelegateHelper::ClearInspectorSettings(profile); -} - -void BackgroundContents::Close(RenderViewHost* render_view_host) { - Profile* profile = render_view_host->process()->profile(); - NotificationService::current()->Notify( - NotificationType::BACKGROUND_CONTENTS_CLOSED, - Source<Profile>(profile), - Details<BackgroundContents>(this)); - delete this; -} - -void BackgroundContents::RenderViewGone(RenderViewHost* rvh, - base::TerminationStatus status, - int error_code) { - // Our RenderView went away, so we should go away also, so killing the process - // via the TaskManager doesn't permanently leave a BackgroundContents hanging - // around the system, blocking future instances from being created - // (http://crbug.com/65189). - delete this; -} - -bool BackgroundContents::OnMessageReceived(const IPC::Message& message) { - // Forward desktop notification IPCs if any to the - // DesktopNotificationHandler. - return desktop_notification_handler_->OnMessageReceived(message); -} - -RendererPreferences BackgroundContents::GetRendererPrefs( - Profile* profile) const { - RendererPreferences preferences; - renderer_preferences_util::UpdateFromSystemSettings(&preferences, profile); - return preferences; -} - -WebPreferences BackgroundContents::GetWebkitPrefs() { - // TODO(rafaelw): Consider enabling the webkit_prefs.dom_paste_enabled for - // apps. - Profile* profile = render_view_host_->process()->profile(); - return RenderViewHostDelegateHelper::GetWebkitPrefs(profile, - false); // is_dom_ui -} - -void BackgroundContents::ProcessWebUIMessage( - const ViewHostMsg_DomMessage_Params& params) { - // TODO(rafaelw): It may make sense for extensions to be able to open - // BackgroundContents to chrome-extension://<id> pages. Consider implementing. - render_view_host_->BlockExtensionRequest(params.request_id); -} - -void BackgroundContents::CreateNewWindow( - int route_id, - const ViewHostMsg_CreateWindow_Params& params) { - delegate_view_helper_.CreateNewWindow( - route_id, - render_view_host_->process()->profile(), - render_view_host_->site_instance(), - WebUIFactory::GetWebUIType(render_view_host_->process()->profile(), url_), - this, - params.window_container_type, - params.frame_name); -} - -void BackgroundContents::CreateNewWidget(int route_id, - WebKit::WebPopupType popup_type) { - NOTREACHED(); -} - -void BackgroundContents::CreateNewFullscreenWidget(int route_id) { - NOTREACHED(); -} - -void BackgroundContents::ShowCreatedWindow(int route_id, - WindowOpenDisposition disposition, - const gfx::Rect& initial_pos, - bool user_gesture) { - TabContents* contents = delegate_view_helper_.GetCreatedWindow(route_id); - if (contents) - delegate_->AddTabContents(contents, disposition, initial_pos, user_gesture); -} - -void BackgroundContents::ShowCreatedWidget(int route_id, - const gfx::Rect& initial_pos) { - NOTIMPLEMENTED(); -} - -void BackgroundContents::ShowCreatedFullscreenWidget(int route_id) { - NOTIMPLEMENTED(); -} - -// static -BackgroundContents* -BackgroundContents::GetBackgroundContentsByID(int render_process_id, - int render_view_id) { - RenderViewHost* render_view_host = - RenderViewHost::FromID(render_process_id, render_view_id); - if (!render_view_host) - return NULL; - - return render_view_host->delegate()->GetAsBackgroundContents(); -} diff --git a/chrome/browser/tab_contents/background_contents.h b/chrome/browser/tab_contents/background_contents.h index 11aa3e2..ea0d6ab 100644 --- a/chrome/browser/tab_contents/background_contents.h +++ b/chrome/browser/tab_contents/background_contents.h @@ -6,181 +6,7 @@ #define CHROME_BROWSER_TAB_CONTENTS_BACKGROUND_CONTENTS_H_ #pragma once -#include <string> -#include <vector> - -#include "chrome/browser/renderer_host/render_view_host_delegate.h" -#include "chrome/browser/tab_contents/render_view_host_delegate_helper.h" -#include "chrome/browser/ui/app_modal_dialogs/js_modal_dialog.h" -#include "chrome/common/notification_registrar.h" -#include "chrome/common/view_types.h" -#include "chrome/common/window_container_type.h" -#include "webkit/glue/window_open_disposition.h" - -class TabContents; -struct WebPreferences; -class DesktopNotificationHandler; - -namespace gfx { -class Rect; -} - -// This class is a peer of TabContents. It can host a renderer, but does not -// have any visible display. Its navigation is not managed by a -// NavigationController because is has no facility for navigating (other than -// programatically view window.location.href) or RenderViewHostManager because -// it is never allowed to navigate across a SiteInstance boundary. -class BackgroundContents : public RenderViewHostDelegate, - public RenderViewHostDelegate::View, - public NotificationObserver, - public JavaScriptAppModalDialogDelegate { - public: - class Delegate { - public: - // Called by ShowCreatedWindow. Asks the delegate to attach the opened - // TabContents to a suitable container (e.g. browser) or to show it if it's - // a popup window. - virtual void AddTabContents(TabContents* new_contents, - WindowOpenDisposition disposition, - const gfx::Rect& initial_pos, - bool user_gesture) = 0; - - protected: - virtual ~Delegate() {} - }; - - BackgroundContents(SiteInstance* site_instance, - int routing_id, - Delegate* delegate); - virtual ~BackgroundContents(); - - // Provide access to the RenderViewHost for the - // RenderViewHostDelegateViewHelper - RenderViewHost* render_view_host() { return render_view_host_; } - - // RenderViewHostDelegate implementation. - virtual BackgroundContents* GetAsBackgroundContents(); - virtual RenderViewHostDelegate::View* GetViewDelegate(); - virtual const GURL& GetURL() const; - virtual ViewType::Type GetRenderViewType() const; - virtual int GetBrowserWindowID() const; - virtual void DidNavigate(RenderViewHost* render_view_host, - const ViewHostMsg_FrameNavigate_Params& params); - virtual WebPreferences GetWebkitPrefs(); - virtual void ProcessWebUIMessage(const ViewHostMsg_DomMessage_Params& params); - virtual void RunJavaScriptMessage(const std::wstring& message, - const std::wstring& default_prompt, - const GURL& frame_url, - const int flags, - IPC::Message* reply_msg, - bool* did_suppress_message); - virtual void Close(RenderViewHost* render_view_host); - virtual RendererPreferences GetRendererPrefs(Profile* profile) const; - virtual void RenderViewGone(RenderViewHost* rvh, - base::TerminationStatus status, - int error_code); - virtual bool OnMessageReceived(const IPC::Message& message); - - // RenderViewHostDelegate::View - virtual void CreateNewWindow( - int route_id, - const ViewHostMsg_CreateWindow_Params& params); - virtual void CreateNewWidget(int route_id, WebKit::WebPopupType popup_type); - virtual void CreateNewFullscreenWidget(int route_id); - virtual void ShowCreatedWindow(int route_id, - WindowOpenDisposition disposition, - const gfx::Rect& initial_pos, - bool user_gesture); - virtual void ShowCreatedWidget(int route_id, - const gfx::Rect& initial_pos); - virtual void ShowCreatedFullscreenWidget(int route_id); - virtual void ShowContextMenu(const ContextMenuParams& params) {} - virtual void ShowPopupMenu(const gfx::Rect& bounds, - int item_height, - double item_font_size, - int selected_item, - const std::vector<WebMenuItem>& items, - bool right_aligned) {} - virtual void StartDragging(const WebDropData& drop_data, - WebKit::WebDragOperationsMask allowed_operations, - const SkBitmap& image, - const gfx::Point& image_offset) {} - virtual void UpdateDragCursor(WebKit::WebDragOperation operation) {} - virtual void GotFocus() {} - virtual void TakeFocus(bool reverse) {} - virtual void LostCapture() {} - virtual void Activate() {} - virtual void Deactivate() {} - virtual bool PreHandleKeyboardEvent(const NativeWebKeyboardEvent& event, - bool* is_keyboard_shortcut); - virtual void HandleKeyboardEvent(const NativeWebKeyboardEvent& event) {} - virtual void HandleMouseMove() {} - virtual void HandleMouseDown() {} - virtual void HandleMouseLeave() {} - virtual void HandleMouseUp() {} - virtual void HandleMouseActivate() {} - virtual void UpdatePreferredSize(const gfx::Size& new_size) {} - - // NotificationObserver - virtual void Observe(NotificationType type, - const NotificationSource& source, - const NotificationDetails& details); - - // Overridden from JavaScriptAppModalDialogDelegate: - virtual void OnMessageBoxClosed(IPC::Message* reply_msg, - bool success, - const std::wstring& prompt); - virtual void SetSuppressMessageBoxes(bool suppress_message_boxes) {} - virtual gfx::NativeWindow GetMessageBoxRootWindow(); - virtual TabContents* AsTabContents(); - virtual ExtensionHost* AsExtensionHost(); - - virtual void UpdateInspectorSetting(const std::string& key, - const std::string& value); - virtual void ClearInspectorSettings(); - - // Helper to find the BackgroundContents that originated the given request. - // Can be NULL if the page has been closed or some other error occurs. - // Should only be called from the UI thread, since it accesses - // BackgroundContents. - static BackgroundContents* GetBackgroundContentsByID(int render_process_id, - int render_view_id); - - protected: - // Exposed for testing. - BackgroundContents(); - - private: - // The delegate for this BackgroundContents. - Delegate* delegate_; - - // The host for our HTML content. - RenderViewHost* render_view_host_; - - // Common implementations of some RenderViewHostDelegate::View methods. - RenderViewHostDelegateViewHelper delegate_view_helper_; - - // The URL being hosted. - GURL url_; - - NotificationRegistrar registrar_; - - // Handles desktop notification IPCs. - scoped_ptr<DesktopNotificationHandler> desktop_notification_handler_; - - DISALLOW_COPY_AND_ASSIGN(BackgroundContents); -}; - -// This is the data sent out as the details with BACKGROUND_CONTENTS_OPENED. -struct BackgroundContentsOpenedDetails { - // The BackgroundContents object that has just been opened. - BackgroundContents* contents; - - // The name of the parent frame for these contents. - const string16& frame_name; - - // The ID of the parent application (if any). - const string16& application_id; -}; +// TODO(jam): remove this file when all files have been converted. +#include "content/browser/tab_contents/background_contents.h" #endif // CHROME_BROWSER_TAB_CONTENTS_BACKGROUND_CONTENTS_H_ diff --git a/chrome/browser/tab_contents/constrained_window.h b/chrome/browser/tab_contents/constrained_window.h index 2143e99..b20a60e 100644 --- a/chrome/browser/tab_contents/constrained_window.h +++ b/chrome/browser/tab_contents/constrained_window.h @@ -6,57 +6,7 @@ #define CHROME_BROWSER_TAB_CONTENTS_CONSTRAINED_WINDOW_H_ #pragma once -#include "build/build_config.h" - -// The different platform specific subclasses use different delegates for their -// dialogs. -#if defined(OS_WIN) -namespace views { -class WindowDelegate; -class DialogDelegate; -} -typedef views::WindowDelegate ConstrainedWindowDelegate; -typedef views::DialogDelegate ConstrainedDialogDelegate; -#elif defined(OS_MACOSX) -class ConstrainedWindowMacDelegate; -class ConstrainedWindowMacDelegateSystemSheet; -typedef ConstrainedWindowMacDelegate ConstrainedWindowDelegate; -typedef ConstrainedWindowMacDelegateSystemSheet ConstrainedDialogDelegate; -#elif defined(TOOLKIT_USES_GTK) -class ConstrainedWindowGtkDelegate; -typedef ConstrainedWindowGtkDelegate ConstrainedWindowDelegate; -typedef ConstrainedWindowGtkDelegate ConstrainedDialogDelegate; -#endif - -class TabContents; - -/////////////////////////////////////////////////////////////////////////////// -// ConstrainedWindow -// -// This interface represents a window that is constrained to a TabContents' -// bounds. -// -class ConstrainedWindow { - public: - // Create a Constrained Window that contains a platform specific client - // area. Typical uses include the HTTP Basic Auth prompt. The caller must - // provide a delegate to describe the content area and to respond to events. - static ConstrainedWindow* CreateConstrainedDialog( - TabContents* owner, - ConstrainedWindowDelegate* delegate); - - // Makes the Constrained Window visible. Only one Constrained Window is shown - // at a time per tab. - virtual void ShowConstrainedWindow() = 0; - - // Closes the Constrained Window. - virtual void CloseConstrainedWindow() = 0; - - // Sets focus on the Constrained Window. - virtual void FocusConstrainedWindow() {} - - protected: - virtual ~ConstrainedWindow() {} -}; +// TODO(jam): remove this file when all files have been converted. +#include "content/browser/tab_contents/constrained_window.h" #endif // CHROME_BROWSER_TAB_CONTENTS_CONSTRAINED_WINDOW_H_ diff --git a/chrome/browser/tab_contents/infobar_delegate.cc b/chrome/browser/tab_contents/infobar_delegate.cc index b6115d1..8b9ed7e 100644 --- a/chrome/browser/tab_contents/infobar_delegate.cc +++ b/chrome/browser/tab_contents/infobar_delegate.cc @@ -12,79 +12,6 @@ #include "grit/generated_resources.h" #include "ui/base/l10n/l10n_util.h" -// InfoBarDelegate ------------------------------------------------------------ - -InfoBarDelegate::~InfoBarDelegate() { -} - -bool InfoBarDelegate::EqualsDelegate(InfoBarDelegate* delegate) const { - return false; -} - -bool InfoBarDelegate::ShouldExpire( - const NavigationController::LoadCommittedDetails& details) const { - return (contents_unique_id_ != details.entry->unique_id()) || - (PageTransition::StripQualifier(details.entry->transition_type()) == - PageTransition::RELOAD); -} - -void InfoBarDelegate::InfoBarDismissed() { -} - -void InfoBarDelegate::InfoBarClosed() { -} - -SkBitmap* InfoBarDelegate::GetIcon() const { - return NULL; -} - -InfoBarDelegate::Type InfoBarDelegate::GetInfoBarType() const { - return WARNING_TYPE; -} - -ConfirmInfoBarDelegate* InfoBarDelegate::AsConfirmInfoBarDelegate() { - return NULL; -} - -CrashedExtensionInfoBarDelegate* - InfoBarDelegate::AsCrashedExtensionInfoBarDelegate() { - return NULL; -} - -ExtensionInfoBarDelegate* InfoBarDelegate::AsExtensionInfoBarDelegate() { - return NULL; -} - -LinkInfoBarDelegate* InfoBarDelegate::AsLinkInfoBarDelegate() { - return NULL; -} - -PluginInstallerInfoBarDelegate* - InfoBarDelegate::AsPluginInstallerInfoBarDelegate() { - return NULL; -} - -ThemeInstalledInfoBarDelegate* - InfoBarDelegate::AsThemePreviewInfobarDelegate() { - return NULL; -} - -TranslateInfoBarDelegate* InfoBarDelegate::AsTranslateInfoBarDelegate() { - return NULL; -} - -InfoBarDelegate::InfoBarDelegate(TabContents* contents) - : contents_unique_id_(0) { - if (contents) - StoreActiveEntryUniqueID(contents); -} - -void InfoBarDelegate::StoreActiveEntryUniqueID(TabContents* contents) { - NavigationEntry* active_entry = contents->controller().GetActiveEntry(); - contents_unique_id_ = active_entry ? active_entry->unique_id() : 0; -} - - // LinkInfoBarDelegate -------------------------------------------------------- string16 LinkInfoBarDelegate::GetMessageTextWithOffset( diff --git a/chrome/browser/tab_contents/infobar_delegate.h b/chrome/browser/tab_contents/infobar_delegate.h index 04b58b2..2408ec3 100644 --- a/chrome/browser/tab_contents/infobar_delegate.h +++ b/chrome/browser/tab_contents/infobar_delegate.h @@ -6,114 +6,7 @@ #define CHROME_BROWSER_TAB_CONTENTS_INFOBAR_DELEGATE_H_ #pragma once -#include "base/basictypes.h" -#include "base/string16.h" -#include "chrome/browser/tab_contents/navigation_controller.h" -#include "webkit/glue/window_open_disposition.h" - -class ConfirmInfoBarDelegate; -class CrashedExtensionInfoBarDelegate; -class ExtensionInfoBarDelegate; -class InfoBar; -class LinkInfoBarDelegate; -class PluginInstallerInfoBarDelegate; -class SkBitmap; -class ThemeInstalledInfoBarDelegate; -class TranslateInfoBarDelegate; - -// An interface implemented by objects wishing to control an InfoBar. -// Implementing this interface is not sufficient to use an InfoBar, since it -// does not map to a specific InfoBar type. Instead, you must implement either -// LinkInfoBarDelegate or ConfirmInfoBarDelegate, or override with your own -// delegate for your own InfoBar variety. -// -// --- WARNING --- -// When creating your InfoBarDelegate subclass, it is recommended that you -// design it such that you instantiate a brand new delegate for every call to -// AddInfoBar, rather than re-using/sharing a delegate object. Otherwise, -// you need to consider the fact that more than one InfoBar instance can exist -// and reference the same delegate -- even though it is also true that we only -// ever fully show one infobar (they don't stack). The dual-references occur -// because a second InfoBar can be added while the first one is in the process -// of closing (the animations). This can cause problems because when the first -// one does finally fully close InfoBarDelegate::InfoBarClosed() is called, -// and the delegate is free to clean itself up or reset state, which may have -// fatal consequences for the InfoBar that was in the process of opening (or is -// now fully opened) -- it is referencing a delegate that may not even exist -// anymore. -// As such, it is generally much safer to dedicate a delegate instance to -// AddInfoBar! -class InfoBarDelegate { - public: - // The type of the infobar. It controls its appearance, such as its background - // color. - enum Type { - WARNING_TYPE, - PAGE_ACTION_TYPE, - }; - - virtual ~InfoBarDelegate(); - - // Called to create the InfoBar. Implementation of this method is - // platform-specific. - virtual InfoBar* CreateInfoBar() = 0; - - // Returns true if the supplied |delegate| is equal to this one. Equality is - // left to the implementation to define. This function is called by the - // TabContents when determining whether or not a delegate should be added - // because a matching one already exists. If this function returns true, the - // TabContents will not add the new delegate because it considers one to - // already be present. - virtual bool EqualsDelegate(InfoBarDelegate* delegate) const; - - // Returns true if the InfoBar should be closed automatically after the page - // is navigated. The default behavior is to return true if the page is - // navigated somewhere else or reloaded. - virtual bool ShouldExpire( - const NavigationController::LoadCommittedDetails& details) const; - - // Called when the user clicks on the close button to dismiss the infobar. - virtual void InfoBarDismissed(); - - // Called after the InfoBar is closed. The delegate is free to delete itself - // at this point. - virtual void InfoBarClosed(); - - // Return the icon to be shown for this InfoBar. If the returned bitmap is - // NULL, no icon is shown. - virtual SkBitmap* GetIcon() const; - - // Returns the type of the infobar. The type determines the appearance (such - // as background color) of the infobar. - virtual Type GetInfoBarType() const; - - // Type-checking downcast routines: - virtual ConfirmInfoBarDelegate* AsConfirmInfoBarDelegate(); - virtual CrashedExtensionInfoBarDelegate* AsCrashedExtensionInfoBarDelegate(); - virtual ExtensionInfoBarDelegate* AsExtensionInfoBarDelegate(); - virtual LinkInfoBarDelegate* AsLinkInfoBarDelegate(); - virtual PluginInstallerInfoBarDelegate* AsPluginInstallerInfoBarDelegate(); - virtual ThemeInstalledInfoBarDelegate* AsThemePreviewInfobarDelegate(); - virtual TranslateInfoBarDelegate* AsTranslateInfoBarDelegate(); - - protected: - // Provided to subclasses as a convenience to initialize the state of this - // object. If |contents| is non-NULL, its active entry's unique ID will be - // stored using StoreActiveEntryUniqueID automatically. - explicit InfoBarDelegate(TabContents* contents); - - // Store the unique id for the active entry in the specified TabContents, to - // be used later upon navigation to determine if this InfoBarDelegate should - // be expired from |contents_|. - void StoreActiveEntryUniqueID(TabContents* contents); - - private: - // The unique id of the active NavigationEntry of the TabContents that we were - // opened for. Used to help expire on navigations. - int contents_unique_id_; - - DISALLOW_COPY_AND_ASSIGN(InfoBarDelegate); -}; +#include "content/browser/tab_contents/infobar_delegate.h" // An interface derived from InfoBarDelegate implemented by objects wishing to // control a LinkInfoBar. diff --git a/chrome/browser/tab_contents/interstitial_page.cc b/chrome/browser/tab_contents/interstitial_page.cc deleted file mode 100644 index 47fb774..0000000 --- a/chrome/browser/tab_contents/interstitial_page.cc +++ /dev/null @@ -1,733 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/tab_contents/interstitial_page.h" - -#include <vector> - -#include "base/compiler_specific.h" -#include "base/message_loop.h" -#include "base/string_util.h" -#include "base/threading/thread.h" -#include "base/utf_string_conversions.h" -#include "chrome/browser/browser_list.h" -#include "chrome/browser/browser_process.h" -#include "chrome/browser/browser_thread.h" -#include "chrome/browser/dom_operation_notification_details.h" -#include "chrome/browser/profiles/profile.h" -#include "chrome/browser/renderer_host/render_process_host.h" -#include "chrome/browser/renderer_host/render_view_host.h" -#include "chrome/browser/renderer_host/render_widget_host_view.h" -#include "chrome/browser/renderer_host/resource_dispatcher_host.h" -#include "chrome/browser/renderer_host/site_instance.h" -#include "chrome/browser/renderer_preferences_util.h" -#include "chrome/browser/tab_contents/navigation_controller.h" -#include "chrome/browser/tab_contents/navigation_entry.h" -#include "chrome/browser/tab_contents/tab_contents.h" -#include "chrome/browser/tab_contents/tab_contents_view.h" -#include "chrome/common/bindings_policy.h" -#include "chrome/common/dom_storage_common.h" -#include "chrome/common/net/url_request_context_getter.h" -#include "chrome/common/notification_source.h" -#include "grit/browser_resources.h" -#include "net/base/escape.h" - -#if defined(TOOLKIT_GTK) -#include "chrome/browser/ui/gtk/gtk_theme_provider.h" -#endif - -using WebKit::WebDragOperation; -using WebKit::WebDragOperationsMask; - -namespace { - -class ResourceRequestTask : public Task { - public: - ResourceRequestTask(int process_id, - int render_view_host_id, - ResourceRequestAction action) - : action_(action), - process_id_(process_id), - render_view_host_id_(render_view_host_id), - resource_dispatcher_host_( - g_browser_process->resource_dispatcher_host()) { - } - - virtual void Run() { - switch (action_) { - case BLOCK: - resource_dispatcher_host_->BlockRequestsForRoute( - process_id_, render_view_host_id_); - break; - case RESUME: - resource_dispatcher_host_->ResumeBlockedRequestsForRoute( - process_id_, render_view_host_id_); - break; - case CANCEL: - resource_dispatcher_host_->CancelBlockedRequestsForRoute( - process_id_, render_view_host_id_); - break; - default: - NOTREACHED(); - } - } - - private: - ResourceRequestAction action_; - int process_id_; - int render_view_host_id_; - ResourceDispatcherHost* resource_dispatcher_host_; - - DISALLOW_COPY_AND_ASSIGN(ResourceRequestTask); -}; - -} // namespace - -class InterstitialPage::InterstitialPageRVHViewDelegate - : public RenderViewHostDelegate::View { - public: - explicit InterstitialPageRVHViewDelegate(InterstitialPage* page); - - // RenderViewHostDelegate::View implementation: - virtual void CreateNewWindow( - int route_id, - const ViewHostMsg_CreateWindow_Params& params); - virtual void CreateNewWidget(int route_id, - WebKit::WebPopupType popup_type); - virtual void CreateNewFullscreenWidget(int route_id); - virtual void ShowCreatedWindow(int route_id, - WindowOpenDisposition disposition, - const gfx::Rect& initial_pos, - bool user_gesture); - virtual void ShowCreatedWidget(int route_id, - const gfx::Rect& initial_pos); - virtual void ShowCreatedFullscreenWidget(int route_id); - virtual void ShowContextMenu(const ContextMenuParams& params); - virtual void ShowPopupMenu(const gfx::Rect& bounds, - int item_height, - double item_font_size, - int selected_item, - const std::vector<WebMenuItem>& items, - bool right_aligned); - virtual void StartDragging(const WebDropData& drop_data, - WebDragOperationsMask operations_allowed, - const SkBitmap& image, - const gfx::Point& image_offset); - virtual void UpdateDragCursor(WebDragOperation operation); - virtual void GotFocus(); - virtual void TakeFocus(bool reverse); - virtual void LostCapture(); - virtual void Activate(); - virtual void Deactivate(); - virtual bool PreHandleKeyboardEvent(const NativeWebKeyboardEvent& event, - bool* is_keyboard_shortcut); - virtual void HandleKeyboardEvent(const NativeWebKeyboardEvent& event); - virtual void HandleMouseMove(); - virtual void HandleMouseDown(); - virtual void HandleMouseLeave(); - virtual void HandleMouseUp(); - virtual void HandleMouseActivate(); - virtual void OnFindReply(int request_id, - int number_of_matches, - const gfx::Rect& selection_rect, - int active_match_ordinal, - bool final_update); - virtual void UpdatePreferredSize(const gfx::Size& pref_size); - - private: - InterstitialPage* interstitial_page_; - - DISALLOW_COPY_AND_ASSIGN(InterstitialPageRVHViewDelegate); -}; - -// static -InterstitialPage::InterstitialPageMap* - InterstitialPage::tab_to_interstitial_page_ = NULL; - -InterstitialPage::InterstitialPage(TabContents* tab, - bool new_navigation, - const GURL& url) - : tab_(tab), - url_(url), - new_navigation_(new_navigation), - should_discard_pending_nav_entry_(new_navigation), - reload_on_dont_proceed_(false), - enabled_(true), - action_taken_(NO_ACTION), - render_view_host_(NULL), - original_child_id_(tab->render_view_host()->process()->id()), - original_rvh_id_(tab->render_view_host()->routing_id()), - should_revert_tab_title_(false), - resource_dispatcher_host_notified_(false), - ALLOW_THIS_IN_INITIALIZER_LIST(rvh_view_delegate_( - new InterstitialPageRVHViewDelegate(this))) { - renderer_preferences_util::UpdateFromSystemSettings( - &renderer_preferences_, tab_->profile()); - - InitInterstitialPageMap(); - // It would be inconsistent to create an interstitial with no new navigation - // (which is the case when the interstitial was triggered by a sub-resource on - // a page) when we have a pending entry (in the process of loading a new top - // frame). - DCHECK(new_navigation || !tab->controller().pending_entry()); -} - -InterstitialPage::~InterstitialPage() { - InterstitialPageMap::iterator iter = tab_to_interstitial_page_->find(tab_); - DCHECK(iter != tab_to_interstitial_page_->end()); - if (iter != tab_to_interstitial_page_->end()) - tab_to_interstitial_page_->erase(iter); - DCHECK(!render_view_host_); -} - -void InterstitialPage::Show() { - // If an interstitial is already showing or about to be shown, close it before - // showing the new one. - // Be careful not to take an action on the old interstitial more than once. - InterstitialPageMap::const_iterator iter = - tab_to_interstitial_page_->find(tab_); - if (iter != tab_to_interstitial_page_->end()) { - InterstitialPage* interstitial = iter->second; - if (interstitial->action_taken_ != NO_ACTION) { - interstitial->Hide(); - } else { - // If we are currently showing an interstitial page for which we created - // a transient entry and a new interstitial is shown as the result of a - // new browser initiated navigation, then that transient entry has already - // been discarded and a new pending navigation entry created. - // So we should not discard that new pending navigation entry. - // See http://crbug.com/9791 - if (new_navigation_ && interstitial->new_navigation_) - interstitial->should_discard_pending_nav_entry_= false; - interstitial->DontProceed(); - } - } - - // Block the resource requests for the render view host while it is hidden. - TakeActionOnResourceDispatcher(BLOCK); - // We need to be notified when the RenderViewHost is destroyed so we can - // cancel the blocked requests. We cannot do that on - // NOTIFY_TAB_CONTENTS_DESTROYED as at that point the RenderViewHost has - // already been destroyed. - notification_registrar_.Add( - this, NotificationType::RENDER_WIDGET_HOST_DESTROYED, - Source<RenderWidgetHost>(tab_->render_view_host())); - - // Update the tab_to_interstitial_page_ map. - iter = tab_to_interstitial_page_->find(tab_); - DCHECK(iter == tab_to_interstitial_page_->end()); - (*tab_to_interstitial_page_)[tab_] = this; - - if (new_navigation_) { - NavigationEntry* entry = new NavigationEntry; - entry->set_url(url_); - entry->set_virtual_url(url_); - entry->set_page_type(INTERSTITIAL_PAGE); - - // Give sub-classes a chance to set some states on the navigation entry. - UpdateEntry(entry); - - tab_->controller().AddTransientEntry(entry); - } - - DCHECK(!render_view_host_); - render_view_host_ = CreateRenderViewHost(); - CreateTabContentsView(); - - std::string data_url = "data:text/html;charset=utf-8," + - EscapePath(GetHTMLContents()); - render_view_host_->NavigateToURL(GURL(data_url)); - - notification_registrar_.Add(this, NotificationType::TAB_CONTENTS_DESTROYED, - Source<TabContents>(tab_)); - notification_registrar_.Add(this, NotificationType::NAV_ENTRY_COMMITTED, - Source<NavigationController>(&tab_->controller())); - notification_registrar_.Add(this, NotificationType::NAV_ENTRY_PENDING, - Source<NavigationController>(&tab_->controller())); -} - -void InterstitialPage::Hide() { - RenderWidgetHostView* old_view = tab_->render_view_host()->view(); - if (old_view && !old_view->IsShowing()) { - // Show the original RVH since we're going away. Note it might not exist if - // the renderer crashed while the interstitial was showing. - // Note that it is important that we don't call Show() if the view is - // already showing. That would result in bad things (unparented HWND on - // Windows for example) happening. - old_view->Show(); - } - - // If the focus was on the interstitial, let's keep it to the page. - // (Note that in unit-tests the RVH may not have a view). - if (render_view_host_->view() && render_view_host_->view()->HasFocus() && - tab_->render_view_host()->view()) { - tab_->render_view_host()->view()->Focus(); - } - - render_view_host_->Shutdown(); - render_view_host_ = NULL; - if (tab_->interstitial_page()) - tab_->remove_interstitial_page(); - // Let's revert to the original title if necessary. - NavigationEntry* entry = tab_->controller().GetActiveEntry(); - if (!new_navigation_ && should_revert_tab_title_) { - entry->set_title(WideToUTF16Hack(original_tab_title_)); - tab_->NotifyNavigationStateChanged(TabContents::INVALIDATE_TITLE); - } - delete this; -} - -void InterstitialPage::Observe(NotificationType type, - const NotificationSource& source, - const NotificationDetails& details) { - switch (type.value) { - case NotificationType::NAV_ENTRY_PENDING: - // We are navigating away from the interstitial (the user has typed a URL - // in the location bar or clicked a bookmark). Make sure clicking on the - // interstitial will have no effect. Also cancel any blocked requests - // on the ResourceDispatcherHost. Note that when we get this notification - // the RenderViewHost has not yet navigated so we'll unblock the - // RenderViewHost before the resource request for the new page we are - // navigating arrives in the ResourceDispatcherHost. This ensures that - // request won't be blocked if the same RenderViewHost was used for the - // new navigation. - Disable(); - TakeActionOnResourceDispatcher(CANCEL); - break; - case NotificationType::RENDER_WIDGET_HOST_DESTROYED: - if (action_taken_ == NO_ACTION) { - // The RenderViewHost is being destroyed (as part of the tab being - // closed), make sure we clear the blocked requests. - RenderViewHost* rvh = Source<RenderViewHost>(source).ptr(); - DCHECK(rvh->process()->id() == original_child_id_ && - rvh->routing_id() == original_rvh_id_); - TakeActionOnResourceDispatcher(CANCEL); - } - break; - case NotificationType::TAB_CONTENTS_DESTROYED: - case NotificationType::NAV_ENTRY_COMMITTED: - if (action_taken_ == NO_ACTION) { - // We are navigating away from the interstitial or closing a tab with an - // interstitial. Default to DontProceed(). We don't just call Hide as - // subclasses will almost certainly override DontProceed to do some work - // (ex: close pending connections). - DontProceed(); - } else { - // User decided to proceed and either the navigation was committed or - // the tab was closed before that. - Hide(); - // WARNING: we are now deleted! - } - break; - default: - NOTREACHED(); - } -} - -RenderViewHostDelegate::View* InterstitialPage::GetViewDelegate() { - return rvh_view_delegate_.get(); -} - -const GURL& InterstitialPage::GetURL() const { - return url_; -} - -void InterstitialPage::RenderViewGone(RenderViewHost* render_view_host, - base::TerminationStatus status, - int error_code) { - // Our renderer died. This should not happen in normal cases. - // Just dismiss the interstitial. - DontProceed(); -} - -void InterstitialPage::DidNavigate( - RenderViewHost* render_view_host, - const ViewHostMsg_FrameNavigate_Params& params) { - // A fast user could have navigated away from the page that triggered the - // interstitial while the interstitial was loading, that would have disabled - // us. In that case we can dismiss ourselves. - if (!enabled_) { - DontProceed(); - return; - } - - // The RenderViewHost has loaded its contents, we can show it now. - render_view_host_->view()->Show(); - tab_->set_interstitial_page(this); - - RenderWidgetHostView* rwh_view = tab_->render_view_host()->view(); - - // The RenderViewHost may already have crashed before we even get here. - if (rwh_view) { - // If the page has focus, focus the interstitial. - if (rwh_view->HasFocus()) - Focus(); - - // Hide the original RVH since we're showing the interstitial instead. - rwh_view->Hide(); - } - - // Notify the tab we are not loading so the throbber is stopped. It also - // causes a NOTIFY_LOAD_STOP notification, that the AutomationProvider (used - // by the UI tests) expects to consider a navigation as complete. Without - // this, navigating in a UI test to a URL that triggers an interstitial would - // hang. - tab_->SetIsLoading(false, NULL); -} - -void InterstitialPage::UpdateTitle(RenderViewHost* render_view_host, - int32 page_id, - const std::wstring& title) { - DCHECK(render_view_host == render_view_host_); - NavigationEntry* entry = tab_->controller().GetActiveEntry(); - if (!entry) { - // Crash reports from the field indicate this can be NULL. - // This is unexpected as InterstitialPages constructed with the - // new_navigation flag set to true create a transient navigation entry - // (that is returned as the active entry). And the only case so far of - // interstitial created with that flag set to false is with the - // SafeBrowsingBlockingPage, when the resource triggering the interstitial - // is a sub-resource, meaning the main page has already been loaded and a - // navigation entry should have been created. - NOTREACHED(); - return; - } - - // If this interstitial is shown on an existing navigation entry, we'll need - // to remember its title so we can revert to it when hidden. - if (!new_navigation_ && !should_revert_tab_title_) { - original_tab_title_ = UTF16ToWideHack(entry->title()); - should_revert_tab_title_ = true; - } - entry->set_title(WideToUTF16Hack(title)); - tab_->NotifyNavigationStateChanged(TabContents::INVALIDATE_TITLE); -} - -void InterstitialPage::DomOperationResponse(const std::string& json_string, - int automation_id) { - if (enabled_) - CommandReceived(json_string); -} - -RendererPreferences InterstitialPage::GetRendererPrefs(Profile* profile) const { - return renderer_preferences_; -} - -RenderViewHost* InterstitialPage::CreateRenderViewHost() { - RenderViewHost* render_view_host = new RenderViewHost( - SiteInstance::CreateSiteInstance(tab()->profile()), - this, MSG_ROUTING_NONE, kInvalidSessionStorageNamespaceId); - return render_view_host; -} - -TabContentsView* InterstitialPage::CreateTabContentsView() { - TabContentsView* tab_contents_view = tab()->view(); - RenderWidgetHostView* view = - tab_contents_view->CreateViewForWidget(render_view_host_); - render_view_host_->set_view(view); - render_view_host_->AllowBindings(BindingsPolicy::DOM_AUTOMATION); - - render_view_host_->CreateRenderView(string16()); - view->SetSize(tab_contents_view->GetContainerSize()); - // Don't show the interstitial until we have navigated to it. - view->Hide(); - return tab_contents_view; -} - -void InterstitialPage::Proceed() { - if (action_taken_ != NO_ACTION) { - NOTREACHED(); - return; - } - Disable(); - action_taken_ = PROCEED_ACTION; - - // Resumes the throbber. - tab_->SetIsLoading(true, NULL); - - // If this is a new navigation, the old page is going away, so we cancel any - // blocked requests for it. If it is not a new navigation, then it means the - // interstitial was shown as a result of a resource loading in the page. - // Since the user wants to proceed, we'll let any blocked request go through. - if (new_navigation_) - TakeActionOnResourceDispatcher(CANCEL); - else - TakeActionOnResourceDispatcher(RESUME); - - // No need to hide if we are a new navigation, we'll get hidden when the - // navigation is committed. - if (!new_navigation_) { - Hide(); - // WARNING: we are now deleted! - } -} - -std::string InterstitialPage::GetHTMLContents() { - return std::string(); -} - -void InterstitialPage::DontProceed() { - DCHECK(action_taken_ != DONT_PROCEED_ACTION); - - Disable(); - action_taken_ = DONT_PROCEED_ACTION; - - // If this is a new navigation, we are returning to the original page, so we - // resume blocked requests for it. If it is not a new navigation, then it - // means the interstitial was shown as a result of a resource loading in the - // page and we won't return to the original page, so we cancel blocked - // requests in that case. - if (new_navigation_) - TakeActionOnResourceDispatcher(RESUME); - else - TakeActionOnResourceDispatcher(CANCEL); - - if (should_discard_pending_nav_entry_) { - // Since no navigation happens we have to discard the transient entry - // explicitely. Note that by calling DiscardNonCommittedEntries() we also - // discard the pending entry, which is what we want, since the navigation is - // cancelled. - tab_->controller().DiscardNonCommittedEntries(); - } - - if (reload_on_dont_proceed_) - tab_->controller().Reload(true); - - Hide(); - // WARNING: we are now deleted! -} - -void InterstitialPage::CancelForNavigation() { - // The user is trying to navigate away. We should unblock the renderer and - // disable the interstitial, but keep it visible until the navigation - // completes. - Disable(); - // If this interstitial was shown for a new navigation, allow any navigations - // on the original page to resume (e.g., subresource requests, XHRs, etc). - // Otherwise, cancel the pending, possibly dangerous navigations. - if (new_navigation_) - TakeActionOnResourceDispatcher(RESUME); - else - TakeActionOnResourceDispatcher(CANCEL); -} - -void InterstitialPage::SetSize(const gfx::Size& size) { -#if !defined(OS_MACOSX) - // When a tab is closed, we might be resized after our view was NULLed - // (typically if there was an info-bar). - if (render_view_host_->view()) - render_view_host_->view()->SetSize(size); -#else - // TODO(port): Does Mac need to SetSize? - NOTIMPLEMENTED(); -#endif -} - -void InterstitialPage::Focus() { - // Focus the native window. - render_view_host_->view()->Focus(); -} - -void InterstitialPage::FocusThroughTabTraversal(bool reverse) { - render_view_host_->SetInitialFocus(reverse); -} - -ViewType::Type InterstitialPage::GetRenderViewType() const { - return ViewType::INTERSTITIAL_PAGE; -} - -void InterstitialPage::Disable() { - enabled_ = false; -} - -void InterstitialPage::TakeActionOnResourceDispatcher( - ResourceRequestAction action) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)) << - "TakeActionOnResourceDispatcher should be called on the main thread."; - - if (action == CANCEL || action == RESUME) { - if (resource_dispatcher_host_notified_) - return; - resource_dispatcher_host_notified_ = true; - } - - // The tab might not have a render_view_host if it was closed (in which case, - // we have taken care of the blocked requests when processing - // NOTIFY_RENDER_WIDGET_HOST_DESTROYED. - // Also we need to test there is a ResourceDispatcherHost, as when unit-tests - // we don't have one. - RenderViewHost* rvh = RenderViewHost::FromID(original_child_id_, - original_rvh_id_); - if (!rvh || !g_browser_process->resource_dispatcher_host()) - return; - - BrowserThread::PostTask( - BrowserThread::IO, FROM_HERE, - new ResourceRequestTask(original_child_id_, original_rvh_id_, action)); -} - -// static -void InterstitialPage::InitInterstitialPageMap() { - if (!tab_to_interstitial_page_) - tab_to_interstitial_page_ = new InterstitialPageMap; -} - -// static -InterstitialPage* InterstitialPage::GetInterstitialPage( - TabContents* tab_contents) { - InitInterstitialPageMap(); - InterstitialPageMap::const_iterator iter = - tab_to_interstitial_page_->find(tab_contents); - if (iter == tab_to_interstitial_page_->end()) - return NULL; - - return iter->second; -} - -InterstitialPage::InterstitialPageRVHViewDelegate:: - InterstitialPageRVHViewDelegate(InterstitialPage* page) - : interstitial_page_(page) { -} - -void InterstitialPage::InterstitialPageRVHViewDelegate::CreateNewWindow( - int route_id, - const ViewHostMsg_CreateWindow_Params& params) { - NOTREACHED() << "InterstitialPage does not support showing popups yet."; -} - -void InterstitialPage::InterstitialPageRVHViewDelegate::CreateNewWidget( - int route_id, WebKit::WebPopupType popup_type) { - NOTREACHED() << "InterstitialPage does not support showing drop-downs yet."; -} - -void -InterstitialPage::InterstitialPageRVHViewDelegate::CreateNewFullscreenWidget( - int route_id) { - NOTREACHED() - << "InterstitialPage does not support showing full screen popups."; -} - -void InterstitialPage::InterstitialPageRVHViewDelegate::ShowCreatedWindow( - int route_id, WindowOpenDisposition disposition, - const gfx::Rect& initial_pos, bool user_gesture) { - NOTREACHED() << "InterstitialPage does not support showing popups yet."; -} - -void InterstitialPage::InterstitialPageRVHViewDelegate::ShowCreatedWidget( - int route_id, const gfx::Rect& initial_pos) { - NOTREACHED() << "InterstitialPage does not support showing drop-downs yet."; -} - -void -InterstitialPage::InterstitialPageRVHViewDelegate::ShowCreatedFullscreenWidget( - int route_id) { - NOTREACHED() - << "InterstitialPage does not support showing full screen popups."; -} - -void InterstitialPage::InterstitialPageRVHViewDelegate::ShowContextMenu( - const ContextMenuParams& params) { -} - -void InterstitialPage::InterstitialPageRVHViewDelegate::ShowPopupMenu( - const gfx::Rect& bounds, - int item_height, - double item_font_size, - int selected_item, - const std::vector<WebMenuItem>& items, - bool right_aligned) { -} - -void InterstitialPage::InterstitialPageRVHViewDelegate::StartDragging( - const WebDropData& drop_data, - WebDragOperationsMask allowed_operations, - const SkBitmap& image, - const gfx::Point& image_offset) { - NOTREACHED() << "InterstitialPage does not support dragging yet."; -} - -void InterstitialPage::InterstitialPageRVHViewDelegate::UpdateDragCursor( - WebDragOperation) { - NOTREACHED() << "InterstitialPage does not support dragging yet."; -} - -void InterstitialPage::InterstitialPageRVHViewDelegate::GotFocus() { -} - -void InterstitialPage::InterstitialPageRVHViewDelegate::UpdatePreferredSize( - const gfx::Size& pref_size) { -} - -void InterstitialPage::InterstitialPageRVHViewDelegate::TakeFocus( - bool reverse) { - if (interstitial_page_->tab() && interstitial_page_->tab()->GetViewDelegate()) - interstitial_page_->tab()->GetViewDelegate()->TakeFocus(reverse); -} - -void InterstitialPage::InterstitialPageRVHViewDelegate::LostCapture() { -} - -void InterstitialPage::InterstitialPageRVHViewDelegate::Activate() { - if (interstitial_page_->tab() && interstitial_page_->tab()->GetViewDelegate()) - interstitial_page_->tab()->GetViewDelegate()->Activate(); -} - -void InterstitialPage::InterstitialPageRVHViewDelegate::Deactivate() { - if (interstitial_page_->tab() && interstitial_page_->tab()->GetViewDelegate()) - interstitial_page_->tab()->GetViewDelegate()->Deactivate(); -} - -bool InterstitialPage::InterstitialPageRVHViewDelegate::PreHandleKeyboardEvent( - const NativeWebKeyboardEvent& event, bool* is_keyboard_shortcut) { - if (interstitial_page_->tab() && interstitial_page_->tab()->GetViewDelegate()) - return interstitial_page_->tab()->GetViewDelegate()->PreHandleKeyboardEvent( - event, is_keyboard_shortcut); - return false; -} - -void InterstitialPage::InterstitialPageRVHViewDelegate::HandleKeyboardEvent( - const NativeWebKeyboardEvent& event) { - if (interstitial_page_->tab() && interstitial_page_->tab()->GetViewDelegate()) - interstitial_page_->tab()->GetViewDelegate()->HandleKeyboardEvent(event); -} - -void InterstitialPage::InterstitialPageRVHViewDelegate::HandleMouseMove() { - if (interstitial_page_->tab() && interstitial_page_->tab()->GetViewDelegate()) - interstitial_page_->tab()->GetViewDelegate()->HandleMouseMove(); -} - -void InterstitialPage::InterstitialPageRVHViewDelegate::HandleMouseDown() { - if (interstitial_page_->tab() && interstitial_page_->tab()->GetViewDelegate()) - interstitial_page_->tab()->GetViewDelegate()->HandleMouseDown(); -} - -void InterstitialPage::InterstitialPageRVHViewDelegate::HandleMouseLeave() { - if (interstitial_page_->tab() && interstitial_page_->tab()->GetViewDelegate()) - interstitial_page_->tab()->GetViewDelegate()->HandleMouseLeave(); -} - -void InterstitialPage::InterstitialPageRVHViewDelegate::HandleMouseUp() { -} - -void InterstitialPage::InterstitialPageRVHViewDelegate::HandleMouseActivate() { -} - -void InterstitialPage::InterstitialPageRVHViewDelegate::OnFindReply( - int request_id, int number_of_matches, const gfx::Rect& selection_rect, - int active_match_ordinal, bool final_update) { -} - -int InterstitialPage::GetBrowserWindowID() const { - return tab_->GetBrowserWindowID(); -} - -void InterstitialPage::UpdateInspectorSetting(const std::string& key, - const std::string& value) { - RenderViewHostDelegateHelper::UpdateInspectorSetting( - tab_->profile(), key, value); -} - -void InterstitialPage::ClearInspectorSettings() { - RenderViewHostDelegateHelper::ClearInspectorSettings(tab_->profile()); -} diff --git a/chrome/browser/tab_contents/interstitial_page.h b/chrome/browser/tab_contents/interstitial_page.h index f7d1edd..6a1ddb9 100644 --- a/chrome/browser/tab_contents/interstitial_page.h +++ b/chrome/browser/tab_contents/interstitial_page.h @@ -6,240 +6,7 @@ #define CHROME_BROWSER_TAB_CONTENTS_INTERSTITIAL_PAGE_H_ #pragma once -#include <map> -#include <string> - -#include "base/process_util.h" -#include "base/scoped_ptr.h" -#include "chrome/browser/renderer_host/render_view_host_delegate.h" -#include "chrome/common/notification_observer.h" -#include "chrome/common/notification_registrar.h" -#include "chrome/common/renderer_preferences.h" -#include "googleurl/src/gurl.h" -#include "ui/gfx/size.h" - -class NavigationEntry; -class TabContents; -class TabContentsView; - -// This class is a base class for interstitial pages, pages that show some -// informative message asking for user validation before reaching the target -// page. (Navigating to a page served over bad HTTPS or a page containing -// malware are typical cases where an interstitial is required.) -// -// If specified in its constructor, this class creates a navigation entry so -// that when the interstitial shows, the current entry is the target URL. -// -// InterstitialPage instances take care of deleting themselves when closed -// through a navigation, the TabContents closing them or the tab containing them -// being closed. - -enum ResourceRequestAction { - BLOCK, - RESUME, - CANCEL -}; - -class InterstitialPage : public NotificationObserver, - public RenderViewHostDelegate { - public: - // The different state of actions the user can take in an interstitial. - enum ActionState { - NO_ACTION, // No action has been taken yet. - PROCEED_ACTION, // "Proceed" was selected. - DONT_PROCEED_ACTION // "Don't proceed" was selected. - }; - - // Creates an interstitial page to show in |tab|. |new_navigation| should be - // set to true when the interstitial is caused by loading a new page, in which - // case a temporary navigation entry is created with the URL |url| and - // added to the navigation controller (so the interstitial page appears as a - // new navigation entry). |new_navigation| should be false when the - // interstitial was triggered by a loading a sub-resource in a page. - InterstitialPage(TabContents* tab, bool new_navigation, const GURL& url); - virtual ~InterstitialPage(); - - // Shows the interstitial page in the tab. - virtual void Show(); - - // Hides the interstitial page. Warning: this deletes the InterstitialPage. - void Hide(); - - // Retrieves the InterstitialPage if any associated with the specified - // |tab_contents| (used by ui tests). - static InterstitialPage* GetInterstitialPage(TabContents* tab_contents); - - // Sub-classes should return the HTML that should be displayed in the page. - virtual std::string GetHTMLContents(); - - // Reverts to the page showing before the interstitial. - // Sub-classes should call this method when the user has chosen NOT to proceed - // to the target URL. - // Warning: if |new_navigation| was set to true in the constructor, 'this' - // will be deleted when this method returns. - virtual void DontProceed(); - - // Sub-classes should call this method when the user has chosen to proceed to - // the target URL. - // Warning: 'this' has been deleted when this method returns. - virtual void Proceed(); - - // Allows the user to navigate away by disabling the interstitial, canceling - // the pending request, and unblocking the hidden renderer. The interstitial - // will stay visible until the navigation completes. - void CancelForNavigation(); - - // Sizes the RenderViewHost showing the actual interstitial page contents. - void SetSize(const gfx::Size& size); - - ActionState action_taken() const { return action_taken_; } - - // Sets the focus to the interstitial. - void Focus(); - - // Focus the first (last if reverse is true) element in the interstitial page. - // Called when tab traversing. - void FocusThroughTabTraversal(bool reverse); - - virtual ViewType::Type GetRenderViewType() const; - virtual int GetBrowserWindowID() const; - - // See description above field. - void set_reload_on_dont_proceed(bool value) { - reload_on_dont_proceed_ = value; - } - bool reload_on_dont_proceed() const { return reload_on_dont_proceed_; } - - virtual void UpdateInspectorSetting(const std::string& key, - const std::string& value); - virtual void ClearInspectorSettings(); - - protected: - // NotificationObserver method: - virtual void Observe(NotificationType type, - const NotificationSource& source, - const NotificationDetails& details); - - // RenderViewHostDelegate implementation: - virtual View* GetViewDelegate(); - virtual const GURL& GetURL() const; - virtual void RenderViewGone(RenderViewHost* render_view_host, - base::TerminationStatus status, - int error_code); - virtual void DidNavigate(RenderViewHost* render_view_host, - const ViewHostMsg_FrameNavigate_Params& params); - virtual void UpdateTitle(RenderViewHost* render_view_host, - int32 page_id, - const std::wstring& title); - virtual void DomOperationResponse(const std::string& json_string, - int automation_id); - virtual RendererPreferences GetRendererPrefs(Profile* profile) const; - - // Invoked when the page sent a command through DOMAutomation. - virtual void CommandReceived(const std::string& command) {} - - // Invoked with the NavigationEntry that is going to be added to the - // navigation controller. - // Gives an opportunity to sub-classes to set states on the |entry|. - // Note that this is only called if the InterstitialPage was constructed with - // |create_navigation_entry| set to true. - virtual void UpdateEntry(NavigationEntry* entry) {} - - TabContents* tab() const { return tab_; } - const GURL& url() const { return url_; } - RenderViewHost* render_view_host() const { return render_view_host_; } - - // Creates the RenderViewHost containing the interstitial content. - // Overriden in unit tests. - virtual RenderViewHost* CreateRenderViewHost(); - - // Creates the TabContentsView that shows the interstitial RVH. - // Overriden in unit tests. - virtual TabContentsView* CreateTabContentsView(); - - private: - // AutomationProvider needs access to Proceed and DontProceed to simulate - // user actions. - friend class AutomationProvider; - - class InterstitialPageRVHViewDelegate; - - // Initializes tab_to_interstitial_page_ in a thread-safe manner. - // Should be called before accessing tab_to_interstitial_page_. - static void InitInterstitialPageMap(); - - // Disable the interstitial: - // - if it is not yet showing, then it won't be shown. - // - any command sent by the RenderViewHost will be ignored. - void Disable(); - - // Executes the passed action on the ResourceDispatcher (on the IO thread). - // Used to block/resume/cancel requests for the RenderViewHost hidden by this - // interstitial. - void TakeActionOnResourceDispatcher(ResourceRequestAction action); - - // The tab in which we are displayed. - TabContents* tab_; - - // The URL that is shown when the interstitial is showing. - GURL url_; - - // Whether this interstitial is shown as a result of a new navigation (in - // which case a transient navigation entry is created). - bool new_navigation_; - - // Whether we should discard the pending navigation entry when not proceeding. - // This is to deal with cases where |new_navigation_| is true but a new - // pending entry was created since this interstitial was shown and we should - // not discard it. - bool should_discard_pending_nav_entry_; - - // If true and the user chooses not to proceed the target NavigationController - // is reloaded. This is used when two NavigationControllers are merged - // (CopyStateFromAndPrune). - // The default is false. - bool reload_on_dont_proceed_; - - // Whether this interstitial is enabled. See Disable() for more info. - bool enabled_; - - // Whether the Proceed or DontProceed methods have been called yet. - ActionState action_taken_; - - // Notification magic. - NotificationRegistrar notification_registrar_; - - // The RenderViewHost displaying the interstitial contents. - RenderViewHost* render_view_host_; - - // The IDs for the Render[View|Process]Host hidden by this interstitial. - int original_child_id_; - int original_rvh_id_; - - // Whether or not we should change the title of the tab when hidden (to revert - // it to its original value). - bool should_revert_tab_title_; - - // Whether the ResourceDispatcherHost has been notified to cancel/resume the - // resource requests blocked for the RenderViewHost. - bool resource_dispatcher_host_notified_; - - // The original title of the tab that should be reverted to when the - // interstitial is hidden. - std::wstring original_tab_title_; - - // Our RenderViewHostViewDelegate, necessary for accelerators to work. - scoped_ptr<InterstitialPageRVHViewDelegate> rvh_view_delegate_; - - // We keep a map of the various blocking pages shown as the UI tests need to - // be able to retrieve them. - typedef std::map<TabContents*, InterstitialPage*> InterstitialPageMap; - static InterstitialPageMap* tab_to_interstitial_page_; - - // Settings passed to the renderer. - RendererPreferences renderer_preferences_; - - DISALLOW_COPY_AND_ASSIGN(InterstitialPage); -}; +// TODO(jam): remove this file when all files have been converted. +#include "content/browser/tab_contents/interstitial_page.h" #endif // CHROME_BROWSER_TAB_CONTENTS_INTERSTITIAL_PAGE_H_ diff --git a/chrome/browser/tab_contents/language_state.cc b/chrome/browser/tab_contents/language_state.cc deleted file mode 100644 index 5f78876..0000000 --- a/chrome/browser/tab_contents/language_state.cc +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/tab_contents/language_state.h" - -#include "chrome/browser/tab_contents/navigation_controller.h" -#include "chrome/browser/tab_contents/navigation_entry.h" - -LanguageState::LanguageState(NavigationController* nav_controller) - : navigation_controller_(nav_controller), - page_translatable_(false), - translation_pending_(false), - translation_declined_(false), - in_page_navigation_(false) { -} - -LanguageState::~LanguageState() { -} - -void LanguageState::DidNavigate( - const NavigationController::LoadCommittedDetails& details) { - in_page_navigation_ = details.is_in_page; - if (in_page_navigation_ || !details.is_main_frame) - return; // Don't reset our states, the page has not changed. - - bool reload = details.entry->transition_type() == PageTransition::RELOAD || - details.type == NavigationType::SAME_PAGE; - if (reload) { - // We might not get a LanguageDetermined notifications on reloads. Make sure - // to keep the original language and to set current_lang_ so - // IsPageTranslated() returns false. - current_lang_ = original_lang_; - } else { - prev_original_lang_ = original_lang_; - prev_current_lang_ = current_lang_; - original_lang_.clear(); - current_lang_.clear(); - } - - translation_pending_ = false; - translation_declined_ = false; -} - -void LanguageState::LanguageDetermined(const std::string& page_language, - bool page_translatable) { - if (in_page_navigation_ && !original_lang_.empty()) { - // In-page navigation, we don't expect our states to change. - // Note that we'll set the languages if original_lang_ is empty. This might - // happen if the we did not get called on the top-page. - return; - } - page_translatable_ = page_translatable; - original_lang_ = page_language; - current_lang_ = page_language; -} - -std::string LanguageState::AutoTranslateTo() const { - // Only auto-translate if: - // - no translation is pending - // - this page is in the same language as the previous page - // - the previous page had been translated - // - this page is not already translated - // - the new page was navigated through a link. - if (!translation_pending_ && - prev_original_lang_ == original_lang_ && - prev_original_lang_ != prev_current_lang_ && - original_lang_ == current_lang_ && - navigation_controller_->GetActiveEntry() && - navigation_controller_->GetActiveEntry()->transition_type() == - PageTransition::LINK) { - return prev_current_lang_; - } - - return std::string(); -} diff --git a/chrome/browser/tab_contents/language_state.h b/chrome/browser/tab_contents/language_state.h index b3728a3..6c35545 100644 --- a/chrome/browser/tab_contents/language_state.h +++ b/chrome/browser/tab_contents/language_state.h @@ -6,105 +6,8 @@ #define CHROME_BROWSER_TAB_CONTENTS_LANGUAGE_STATE_H_ #pragma once -#include <string> - -#include "base/basictypes.h" -#include "chrome/browser/tab_contents/navigation_controller.h" - -// This class holds the language state of the current page. -// There is one LanguageState instance per TabContents. -// It is used to determine when navigating to a new page whether it should -// automatically be translated. -// This auto-translate behavior is the expected behavior when: -// - user is on page in language A that they had translated to language B. -// - user clicks a link in that page that takes them to a page also in language -// A. - -class LanguageState { - public: - explicit LanguageState(NavigationController* nav_controller); - ~LanguageState(); - - // Should be called when the page did a new navigation (whether it is a main - // frame or sub-frame navigation). - void DidNavigate(const NavigationController::LoadCommittedDetails& details); - - // Should be called when the language of the page has been determined. - // |page_translatable| when false indicates that the browser should not offer - // to translate the page. - void LanguageDetermined(const std::string& page_language, - bool page_translatable); - - // Returns the language the current page should be translated to, based on the - // previous page languages and the transition. This should be called after - // the language page has been determined. - // Returns an empty string if the page should not be auto-translated. - std::string AutoTranslateTo() const; - - // Returns true if the current page in the associated tab has been translated. - bool IsPageTranslated() const { return original_lang_ != current_lang_; } - - const std::string& original_language() const { return original_lang_; } - - void set_current_language(const std::string& language) { - current_lang_ = language; - } - const std::string& current_language() const { return current_lang_; } - - bool page_translatable() const { return page_translatable_; } - - // Whether the page is currently in the process of being translated. - bool translation_pending() const { return translation_pending_; } - void set_translation_pending(bool value) { translation_pending_ = value; } - - // Whether the user has already declined to translate the page. - bool translation_declined() const { return translation_declined_; } - void set_translation_declined(bool value) { translation_declined_ = value; } - - // Whether the current page was navigated through an in-page (fragment) - // navigation. - bool in_page_navigation() const { return in_page_navigation_; } - - private: - // The languages this page is in. Note that current_lang_ is different from - // original_lang_ when the page has been translated. - // Note that these might be empty if the page language has not been determined - // yet. - std::string original_lang_; - std::string current_lang_; - - // Same as above but for the previous page. - std::string prev_original_lang_; - std::string prev_current_lang_; - - // The navigation controller of the tab we are associated with. - NavigationController* navigation_controller_; - - // Whether it is OK to offer to translate the page. Some pages explictly - // specify that they should not be translated by the browser (this is the case - // for GMail for example, which provides its own translation features). - bool page_translatable_; - - // Whether a translation is currently pending (TabContents waiting for the - // PAGE_TRANSLATED notification). This is needed to avoid sending duplicate - // translate requests to a page. TranslateManager initiates translations - // when it received the LANGUAGE_DETERMINED notification. This is sent by - // the renderer with the page contents, every time the load stops for the - // main frame, so we may get several. - // TODO(jcampan): make the renderer send the language just once per navigation - // then we can get rid of that state. - bool translation_pending_; - - // Whether the user has declined to translate the page (by closing the infobar - // for example). This is necessary as a new infobar could be shown if a new - // load happens in the page after the user closed the infobar. - bool translation_declined_; - - // Whether the current navigation is a fragment navigation (in page). - bool in_page_navigation_; - - DISALLOW_COPY_AND_ASSIGN(LanguageState); -}; +// TODO(jam): remove this file when all files have been converted. +#include "content/browser/tab_contents/language_state.h" #endif // CHROME_BROWSER_TAB_CONTENTS_LANGUAGE_STATE_H_ diff --git a/chrome/browser/tab_contents/navigation_controller.cc b/chrome/browser/tab_contents/navigation_controller.cc deleted file mode 100644 index f294535..0000000 --- a/chrome/browser/tab_contents/navigation_controller.cc +++ /dev/null @@ -1,1203 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/tab_contents/navigation_controller.h" - -#include "base/file_util.h" -#include "base/logging.h" -#include "base/string_util.h" -#include "base/time.h" -#include "base/utf_string_conversions.h" -#include "chrome/browser/browser_about_handler.h" -#include "chrome/browser/browser_url_handler.h" -#include "chrome/browser/in_process_webkit/session_storage_namespace.h" -#include "chrome/browser/prefs/pref_service.h" -#include "chrome/browser/profiles/profile.h" -#include "chrome/browser/renderer_host/site_instance.h" -#include "chrome/browser/sessions/session_types.h" -#include "chrome/browser/tab_contents/interstitial_page.h" -#include "chrome/browser/tab_contents/navigation_entry.h" -#include "chrome/browser/tab_contents/tab_contents.h" -#include "chrome/browser/tab_contents/tab_contents_delegate.h" -#include "chrome/common/chrome_constants.h" -#include "chrome/common/navigation_types.h" -#include "chrome/common/notification_service.h" -#include "chrome/common/pref_names.h" -#include "chrome/common/render_messages_params.h" -#include "chrome/common/url_constants.h" -#include "grit/app_resources.h" -#include "net/base/escape.h" -#include "net/base/net_util.h" -#include "net/base/mime_util.h" -#include "webkit/glue/webkit_glue.h" - -namespace { - -const int kInvalidateAllButShelves = - 0xFFFFFFFF & ~TabContents::INVALIDATE_BOOKMARK_BAR; - -// Invoked when entries have been pruned, or removed. For example, if the -// current entries are [google, digg, yahoo], with the current entry google, -// and the user types in cnet, then digg and yahoo are pruned. -void NotifyPrunedEntries(NavigationController* nav_controller, - bool from_front, - int count) { - NavigationController::PrunedDetails details; - details.from_front = from_front; - details.count = count; - NotificationService::current()->Notify( - NotificationType::NAV_LIST_PRUNED, - Source<NavigationController>(nav_controller), - Details<NavigationController::PrunedDetails>(&details)); -} - -// Ensure the given NavigationEntry has a valid state, so that WebKit does not -// get confused if we navigate back to it. -// -// An empty state is treated as a new navigation by WebKit, which would mean -// losing the navigation entries and generating a new navigation entry after -// this one. We don't want that. To avoid this we create a valid state which -// WebKit will not treat as a new navigation. -void SetContentStateIfEmpty(NavigationEntry* entry) { - if (entry->content_state().empty()) { - entry->set_content_state( - webkit_glue::CreateHistoryStateForURL(entry->url())); - } -} - -// Configure all the NavigationEntries in entries for restore. This resets -// the transition type to reload and makes sure the content state isn't empty. -void ConfigureEntriesForRestore( - std::vector<linked_ptr<NavigationEntry> >* entries, - bool from_last_session) { - for (size_t i = 0; i < entries->size(); ++i) { - // Use a transition type of reload so that we don't incorrectly increase - // the typed count. - (*entries)[i]->set_transition_type(PageTransition::RELOAD); - (*entries)[i]->set_restore_type(from_last_session ? - NavigationEntry::RESTORE_LAST_SESSION : - NavigationEntry::RESTORE_CURRENT_SESSION); - // NOTE(darin): This code is only needed for backwards compat. - SetContentStateIfEmpty((*entries)[i].get()); - } -} - -// See NavigationController::IsURLInPageNavigation for how this works and why. -bool AreURLsInPageNavigation(const GURL& existing_url, const GURL& new_url) { - if (existing_url == new_url || !new_url.has_ref()) { - // TODO(jcampan): what about when navigating back from a ref URL to the top - // non ref URL? Nothing is loaded in that case but we return false here. - // The user could also navigate from the ref URL to the non ref URL by - // entering the non ref URL in the location bar or through a bookmark, in - // which case there would be a load. I am not sure if the non-load/load - // scenarios can be differentiated with the TransitionType. - return false; - } - - url_canon::Replacements<char> replacements; - replacements.ClearRef(); - return existing_url.ReplaceComponents(replacements) == - new_url.ReplaceComponents(replacements); -} - -} // namespace - -// NavigationController --------------------------------------------------- - -// static -size_t NavigationController::max_entry_count_ = - chrome::kMaxSessionHistoryEntries; - -// static -bool NavigationController::check_for_repost_ = true; - -NavigationController::NavigationController( - TabContents* contents, - Profile* profile, - SessionStorageNamespace* session_storage_namespace) - : profile_(profile), - pending_entry_(NULL), - last_committed_entry_index_(-1), - pending_entry_index_(-1), - transient_entry_index_(-1), - tab_contents_(contents), - max_restored_page_id_(-1), - ALLOW_THIS_IN_INITIALIZER_LIST(ssl_manager_(this)), - needs_reload_(false), - session_storage_namespace_(session_storage_namespace), - pending_reload_(NO_RELOAD) { - DCHECK(profile_); - if (!session_storage_namespace_) - session_storage_namespace_ = new SessionStorageNamespace(profile_); -} - -NavigationController::~NavigationController() { - DiscardNonCommittedEntriesInternal(); - - NotificationService::current()->Notify( - NotificationType::TAB_CLOSED, - Source<NavigationController>(this), - NotificationService::NoDetails()); -} - -void NavigationController::RestoreFromState( - const std::vector<TabNavigation>& navigations, - int selected_navigation, - bool from_last_session) { - // Verify that this controller is unused and that the input is valid. - DCHECK(entry_count() == 0 && !pending_entry()); - DCHECK(selected_navigation >= 0 && - selected_navigation < static_cast<int>(navigations.size())); - - // Populate entries_ from the supplied TabNavigations. - needs_reload_ = true; - CreateNavigationEntriesFromTabNavigations(navigations, &entries_); - - // And finish the restore. - FinishRestore(selected_navigation, from_last_session); -} - -void NavigationController::Reload(bool check_for_repost) { - ReloadInternal(check_for_repost, RELOAD); -} -void NavigationController::ReloadIgnoringCache(bool check_for_repost) { - ReloadInternal(check_for_repost, RELOAD_IGNORING_CACHE); -} - -void NavigationController::ReloadInternal(bool check_for_repost, - ReloadType reload_type) { - // Reloading a transient entry does nothing. - if (transient_entry_index_ != -1) - return; - - DiscardNonCommittedEntriesInternal(); - int current_index = GetCurrentEntryIndex(); - // If we are no where, then we can't reload. TODO(darin): We should add a - // CanReload method. - if (current_index == -1) { - return; - } - - if (check_for_repost_ && check_for_repost && - GetEntryAtIndex(current_index)->has_post_data()) { - // The user is asking to reload a page with POST data. Prompt to make sure - // they really want to do this. If they do, the dialog will call us back - // with check_for_repost = false. - NotificationService::current()->Notify( - NotificationType::REPOST_WARNING_SHOWN, - Source<NavigationController>(this), - NotificationService::NoDetails()); - - pending_reload_ = reload_type; - tab_contents_->Activate(); - tab_contents_->delegate()->ShowRepostFormWarningDialog(tab_contents_); - } else { - DiscardNonCommittedEntriesInternal(); - - pending_entry_index_ = current_index; - entries_[pending_entry_index_]->set_transition_type(PageTransition::RELOAD); - NavigateToPendingEntry(reload_type); - } -} - -void NavigationController::CancelPendingReload() { - DCHECK(pending_reload_ != NO_RELOAD); - pending_reload_ = NO_RELOAD; -} - -void NavigationController::ContinuePendingReload() { - if (pending_reload_ == NO_RELOAD) { - NOTREACHED(); - } else { - ReloadInternal(false, pending_reload_); - pending_reload_ = NO_RELOAD; - } -} - -bool NavigationController::IsInitialNavigation() { - return last_document_loaded_.is_null(); -} - -// static -NavigationEntry* NavigationController::CreateNavigationEntry( - const GURL& url, const GURL& referrer, PageTransition::Type transition, - Profile* profile) { - // Allow the browser URL handler to rewrite the URL. This will, for example, - // remove "view-source:" from the beginning of the URL to get the URL that - // will actually be loaded. This real URL won't be shown to the user, just - // used internally. - GURL loaded_url(url); - bool reverse_on_redirect = false; - BrowserURLHandler::RewriteURLIfNecessary( - &loaded_url, profile, &reverse_on_redirect); - - NavigationEntry* entry = new NavigationEntry( - NULL, // The site instance for tabs is sent on navigation - // (TabContents::GetSiteInstance). - -1, - loaded_url, - referrer, - string16(), - transition); - entry->set_virtual_url(url); - entry->set_user_typed_url(url); - entry->set_update_virtual_url_with_url(reverse_on_redirect); - if (url.SchemeIsFile()) { - // Use the filename as the title, not the full path. - // We need to call FormatUrl() to perform URL de-escaping; - // it's a bit ugly to grab the filename out of the resulting string. - std::string languages = - profile->GetPrefs()->GetString(prefs::kAcceptLanguages); - std::wstring formatted = UTF16ToWideHack(net::FormatUrl(url, languages)); - std::wstring filename = - FilePath::FromWStringHack(formatted).BaseName().ToWStringHack(); - entry->set_title(WideToUTF16Hack(filename)); - } - return entry; -} - -NavigationEntry* NavigationController::GetEntryWithPageID( - SiteInstance* instance, int32 page_id) const { - int index = GetEntryIndexWithPageID(instance, page_id); - return (index != -1) ? entries_[index].get() : NULL; -} - -void NavigationController::LoadEntry(NavigationEntry* entry) { - // Handle non-navigational URLs that popup dialogs and such, these should not - // actually navigate. - if (HandleNonNavigationAboutURL(entry->url())) - return; - - // When navigating to a new page, we don't know for sure if we will actually - // end up leaving the current page. The new page load could for example - // result in a download or a 'no content' response (e.g., a mailto: URL). - DiscardNonCommittedEntriesInternal(); - pending_entry_ = entry; - NotificationService::current()->Notify( - NotificationType::NAV_ENTRY_PENDING, - Source<NavigationController>(this), - NotificationService::NoDetails()); - NavigateToPendingEntry(NO_RELOAD); -} - -NavigationEntry* NavigationController::GetActiveEntry() const { - if (transient_entry_index_ != -1) - return entries_[transient_entry_index_].get(); - if (pending_entry_) - return pending_entry_; - return GetLastCommittedEntry(); -} - -int NavigationController::GetCurrentEntryIndex() const { - if (transient_entry_index_ != -1) - return transient_entry_index_; - if (pending_entry_index_ != -1) - return pending_entry_index_; - return last_committed_entry_index_; -} - -NavigationEntry* NavigationController::GetLastCommittedEntry() const { - if (last_committed_entry_index_ == -1) - return NULL; - return entries_[last_committed_entry_index_].get(); -} - -bool NavigationController::CanViewSource() const { - bool is_supported_mime_type = net::IsSupportedNonImageMimeType( - tab_contents_->contents_mime_type().c_str()); - NavigationEntry* active_entry = GetActiveEntry(); - return active_entry && !active_entry->IsViewSourceMode() && - is_supported_mime_type; -} - -NavigationEntry* NavigationController::GetEntryAtOffset(int offset) const { - int index = (transient_entry_index_ != -1) ? - transient_entry_index_ + offset : - last_committed_entry_index_ + offset; - if (index < 0 || index >= entry_count()) - return NULL; - - return entries_[index].get(); -} - -bool NavigationController::CanGoBack() const { - return entries_.size() > 1 && GetCurrentEntryIndex() > 0; -} - -bool NavigationController::CanGoForward() const { - int index = GetCurrentEntryIndex(); - return index >= 0 && index < (static_cast<int>(entries_.size()) - 1); -} - -void NavigationController::GoBack() { - if (!CanGoBack()) { - NOTREACHED(); - return; - } - - // If an interstitial page is showing, going back is equivalent to hiding the - // interstitial. - if (tab_contents_->interstitial_page()) { - tab_contents_->interstitial_page()->DontProceed(); - return; - } - - // Base the navigation on where we are now... - int current_index = GetCurrentEntryIndex(); - - DiscardNonCommittedEntries(); - - pending_entry_index_ = current_index - 1; - entries_[pending_entry_index_]->set_transition_type( - entries_[pending_entry_index_]->transition_type() | - PageTransition::FORWARD_BACK); - NavigateToPendingEntry(NO_RELOAD); -} - -void NavigationController::GoForward() { - if (!CanGoForward()) { - NOTREACHED(); - return; - } - - // If an interstitial page is showing, the previous renderer is blocked and - // cannot make new requests. Unblock (and disable) it to allow this - // navigation to succeed. The interstitial will stay visible until the - // resulting DidNavigate. - if (tab_contents_->interstitial_page()) { - tab_contents_->interstitial_page()->CancelForNavigation(); - } - - bool transient = (transient_entry_index_ != -1); - - // Base the navigation on where we are now... - int current_index = GetCurrentEntryIndex(); - - DiscardNonCommittedEntries(); - - pending_entry_index_ = current_index; - // If there was a transient entry, we removed it making the current index - // the next page. - if (!transient) - pending_entry_index_++; - - entries_[pending_entry_index_]->set_transition_type( - entries_[pending_entry_index_]->transition_type() | - PageTransition::FORWARD_BACK); - NavigateToPendingEntry(NO_RELOAD); -} - -void NavigationController::GoToIndex(int index) { - if (index < 0 || index >= static_cast<int>(entries_.size())) { - NOTREACHED(); - return; - } - - if (transient_entry_index_ != -1) { - if (index == transient_entry_index_) { - // Nothing to do when navigating to the transient. - return; - } - if (index > transient_entry_index_) { - // Removing the transient is goint to shift all entries by 1. - index--; - } - } - - // If an interstitial page is showing, the previous renderer is blocked and - // cannot make new requests. - if (tab_contents_->interstitial_page()) { - if (index == GetCurrentEntryIndex() - 1) { - // Going back one entry is equivalent to hiding the interstitial. - tab_contents_->interstitial_page()->DontProceed(); - return; - } else { - // Unblock the renderer (and disable the interstitial) to allow this - // navigation to succeed. The interstitial will stay visible until the - // resulting DidNavigate. - tab_contents_->interstitial_page()->CancelForNavigation(); - } - } - - DiscardNonCommittedEntries(); - - pending_entry_index_ = index; - entries_[pending_entry_index_]->set_transition_type( - entries_[pending_entry_index_]->transition_type() | - PageTransition::FORWARD_BACK); - NavigateToPendingEntry(NO_RELOAD); -} - -void NavigationController::GoToOffset(int offset) { - int index = (transient_entry_index_ != -1) ? - transient_entry_index_ + offset : - last_committed_entry_index_ + offset; - if (index < 0 || index >= entry_count()) - return; - - GoToIndex(index); -} - -void NavigationController::RemoveEntryAtIndex(int index, - const GURL& default_url) { - int size = static_cast<int>(entries_.size()); - DCHECK(index < size); - - DiscardNonCommittedEntries(); - - entries_.erase(entries_.begin() + index); - - if (last_committed_entry_index_ == index) { - last_committed_entry_index_--; - // We removed the currently shown entry, so we have to load something else. - if (last_committed_entry_index_ != -1) { - pending_entry_index_ = last_committed_entry_index_; - NavigateToPendingEntry(NO_RELOAD); - } else { - // If there is nothing to show, show a default page. - LoadURL(default_url.is_empty() ? GURL("about:blank") : default_url, - GURL(), PageTransition::START_PAGE); - } - } else if (last_committed_entry_index_ > index) { - last_committed_entry_index_--; - } -} - -void NavigationController::UpdateVirtualURLToURL( - NavigationEntry* entry, const GURL& new_url) { - GURL new_virtual_url(new_url); - if (BrowserURLHandler::ReverseURLRewrite( - &new_virtual_url, entry->virtual_url(), profile_)) { - entry->set_virtual_url(new_virtual_url); - } -} - -void NavigationController::AddTransientEntry(NavigationEntry* entry) { - // Discard any current transient entry, we can only have one at a time. - int index = 0; - if (last_committed_entry_index_ != -1) - index = last_committed_entry_index_ + 1; - DiscardTransientEntry(); - entries_.insert(entries_.begin() + index, linked_ptr<NavigationEntry>(entry)); - transient_entry_index_ = index; - tab_contents_->NotifyNavigationStateChanged(kInvalidateAllButShelves); -} - -void NavigationController::LoadURL(const GURL& url, const GURL& referrer, - PageTransition::Type transition) { - // The user initiated a load, we don't need to reload anymore. - needs_reload_ = false; - - NavigationEntry* entry = CreateNavigationEntry(url, referrer, transition, - profile_); - - LoadEntry(entry); -} - -void NavigationController::DocumentLoadedInFrame() { - last_document_loaded_ = base::TimeTicks::Now(); -} - -bool NavigationController::RendererDidNavigate( - const ViewHostMsg_FrameNavigate_Params& params, - int extra_invalidate_flags, - LoadCommittedDetails* details) { - - // Save the previous state before we clobber it. - if (GetLastCommittedEntry()) { - details->previous_url = GetLastCommittedEntry()->url(); - details->previous_entry_index = last_committed_entry_index(); - } else { - details->previous_url = GURL(); - details->previous_entry_index = -1; - } - - // Assign the current site instance to any pending entry, so we can find it - // later by calling GetEntryIndexWithPageID. We only care about this if the - // pending entry is an existing navigation and not a new one (or else we - // wouldn't care about finding it with GetEntryIndexWithPageID). - // - // TODO(brettw) this seems slightly bogus as we don't really know if the - // pending entry is what this navigation is for. There is a similar TODO - // w.r.t. the pending entry in RendererDidNavigateToNewPage. - if (pending_entry_index_ >= 0) { - pending_entry_->set_site_instance(tab_contents_->GetSiteInstance()); - pending_entry_->set_restore_type(NavigationEntry::RESTORE_NONE); - } - - // is_in_page must be computed before the entry gets committed. - details->is_in_page = IsURLInPageNavigation(params.url); - - // Do navigation-type specific actions. These will make and commit an entry. - details->type = ClassifyNavigation(params); - - switch (details->type) { - case NavigationType::NEW_PAGE: - RendererDidNavigateToNewPage(params, &(details->did_replace_entry)); - break; - case NavigationType::EXISTING_PAGE: - RendererDidNavigateToExistingPage(params); - break; - case NavigationType::SAME_PAGE: - RendererDidNavigateToSamePage(params); - break; - case NavigationType::IN_PAGE: - RendererDidNavigateInPage(params, &(details->did_replace_entry)); - break; - case NavigationType::NEW_SUBFRAME: - RendererDidNavigateNewSubframe(params); - break; - case NavigationType::AUTO_SUBFRAME: - if (!RendererDidNavigateAutoSubframe(params)) - return false; - break; - case NavigationType::NAV_IGNORE: - // There is nothing we can do with this navigation, so we just return to - // the caller that nothing has happened. - return false; - default: - NOTREACHED(); - } - - // All committed entries should have nonempty content state so WebKit doesn't - // get confused when we go back to them (see the function for details). - SetContentStateIfEmpty(GetActiveEntry()); - - // WebKit doesn't set the "auto" transition on meta refreshes properly (bug - // 1051891) so we manually set it for redirects which we normally treat as - // "non-user-gestures" where we want to update stuff after navigations. - // - // Note that the redirect check also checks for a pending entry to - // differentiate real redirects from browser initiated navigations to a - // redirected entry. This happens when you hit back to go to a page that was - // the destination of a redirect, we don't want to treat it as a redirect - // even though that's what its transition will be. See bug 1117048. - // - // TODO(brettw) write a test for this complicated logic. - details->is_auto = (PageTransition::IsRedirect(params.transition) && - !pending_entry()) || - params.gesture == NavigationGestureAuto; - - // Now prep the rest of the details for the notification and broadcast. - details->entry = GetActiveEntry(); - details->is_main_frame = PageTransition::IsMainFrame(params.transition); - details->serialized_security_info = params.security_info; - details->is_content_filtered = params.is_content_filtered; - details->http_status_code = params.http_status_code; - NotifyNavigationEntryCommitted(details, extra_invalidate_flags); - - return true; -} - -NavigationType::Type NavigationController::ClassifyNavigation( - const ViewHostMsg_FrameNavigate_Params& params) const { - if (params.page_id == -1) { - // The renderer generates the page IDs, and so if it gives us the invalid - // page ID (-1) we know it didn't actually navigate. This happens in a few - // cases: - // - // - If a page makes a popup navigated to about blank, and then writes - // stuff like a subframe navigated to a real page. We'll get the commit - // for the subframe, but there won't be any commit for the outer page. - // - // - We were also getting these for failed loads (for example, bug 21849). - // The guess is that we get a "load commit" for the alternate error page, - // but that doesn't affect the page ID, so we get the "old" one, which - // could be invalid. This can also happen for a cross-site transition - // that causes us to swap processes. Then the error page load will be in - // a new process with no page IDs ever assigned (and hence a -1 value), - // yet the navigation controller still might have previous pages in its - // list. - // - // In these cases, there's nothing we can do with them, so ignore. - return NavigationType::NAV_IGNORE; - } - - if (params.page_id > tab_contents_->GetMaxPageID()) { - // Greater page IDs than we've ever seen before are new pages. We may or may - // not have a pending entry for the page, and this may or may not be the - // main frame. - if (PageTransition::IsMainFrame(params.transition)) - return NavigationType::NEW_PAGE; - - // When this is a new subframe navigation, we should have a committed page - // for which it's a suframe in. This may not be the case when an iframe is - // navigated on a popup navigated to about:blank (the iframe would be - // written into the popup by script on the main page). For these cases, - // there isn't any navigation stuff we can do, so just ignore it. - if (!GetLastCommittedEntry()) - return NavigationType::NAV_IGNORE; - - // Valid subframe navigation. - return NavigationType::NEW_SUBFRAME; - } - - // Now we know that the notification is for an existing page. Find that entry. - int existing_entry_index = GetEntryIndexWithPageID( - tab_contents_->GetSiteInstance(), - params.page_id); - if (existing_entry_index == -1) { - // The page was not found. It could have been pruned because of the limit on - // back/forward entries (not likely since we'll usually tell it to navigate - // to such entries). It could also mean that the renderer is smoking crack. - NOTREACHED(); - return NavigationType::NAV_IGNORE; - } - NavigationEntry* existing_entry = entries_[existing_entry_index].get(); - - if (!PageTransition::IsMainFrame(params.transition)) { - // All manual subframes would get new IDs and were handled above, so we - // know this is auto. Since the current page was found in the navigation - // entry list, we're guaranteed to have a last committed entry. - DCHECK(GetLastCommittedEntry()); - return NavigationType::AUTO_SUBFRAME; - } - - // Anything below here we know is a main frame navigation. - if (pending_entry_ && - existing_entry != pending_entry_ && - pending_entry_->page_id() == -1) { - // In this case, we have a pending entry for a URL but WebCore didn't do a - // new navigation. This happens when you press enter in the URL bar to - // reload. We will create a pending entry, but WebKit will convert it to - // a reload since it's the same page and not create a new entry for it - // (the user doesn't want to have a new back/forward entry when they do - // this). In this case, we want to just ignore the pending entry and go - // back to where we were (the "existing entry"). - return NavigationType::SAME_PAGE; - } - - // Any toplevel navigations with the same base (minus the reference fragment) - // are in-page navigations. We weeded out subframe navigations above. Most of - // the time this doesn't matter since WebKit doesn't tell us about subframe - // navigations that don't actually navigate, but it can happen when there is - // an encoding override (it always sends a navigation request). - if (AreURLsInPageNavigation(existing_entry->url(), params.url)) - return NavigationType::IN_PAGE; - - // Since we weeded out "new" navigations above, we know this is an existing - // (back/forward) navigation. - return NavigationType::EXISTING_PAGE; -} - -bool NavigationController::IsRedirect( - const ViewHostMsg_FrameNavigate_Params& params) { - // For main frame transition, we judge by params.transition. - // Otherwise, by params.redirects. - if (PageTransition::IsMainFrame(params.transition)) { - return PageTransition::IsRedirect(params.transition); - } - return params.redirects.size() > 1; -} - -void NavigationController::CreateNavigationEntriesFromTabNavigations( - const std::vector<TabNavigation>& navigations, - std::vector<linked_ptr<NavigationEntry> >* entries) { - // Create a NavigationEntry for each of the navigations. - int page_id = 0; - for (std::vector<TabNavigation>::const_iterator i = - navigations.begin(); i != navigations.end(); ++i, ++page_id) { - linked_ptr<NavigationEntry> entry(i->ToNavigationEntry(page_id, profile_)); - entries->push_back(entry); - } -} - -void NavigationController::RendererDidNavigateToNewPage( - const ViewHostMsg_FrameNavigate_Params& params, bool* did_replace_entry) { - NavigationEntry* new_entry; - if (pending_entry_) { - // TODO(brettw) this assumes that the pending entry is appropriate for the - // new page that was just loaded. I don't think this is necessarily the - // case! We should have some more tracking to know for sure. This goes along - // with a similar TODO at the top of RendererDidNavigate where we blindly - // set the site instance on the pending entry. - new_entry = new NavigationEntry(*pending_entry_); - - // Don't use the page type from the pending entry. Some interstitial page - // may have set the type to interstitial. Once we commit, however, the page - // type must always be normal. - new_entry->set_page_type(NORMAL_PAGE); - } else { - new_entry = new NavigationEntry; - } - - new_entry->set_url(params.url); - if (new_entry->update_virtual_url_with_url()) - UpdateVirtualURLToURL(new_entry, params.url); - new_entry->set_referrer(params.referrer); - new_entry->set_page_id(params.page_id); - new_entry->set_transition_type(params.transition); - new_entry->set_site_instance(tab_contents_->GetSiteInstance()); - new_entry->set_has_post_data(params.is_post); - - InsertOrReplaceEntry(new_entry, *did_replace_entry); -} - -void NavigationController::RendererDidNavigateToExistingPage( - const ViewHostMsg_FrameNavigate_Params& params) { - // We should only get here for main frame navigations. - DCHECK(PageTransition::IsMainFrame(params.transition)); - - // This is a back/forward navigation. The existing page for the ID is - // guaranteed to exist by ClassifyNavigation, and we just need to update it - // with new information from the renderer. - int entry_index = GetEntryIndexWithPageID(tab_contents_->GetSiteInstance(), - params.page_id); - DCHECK(entry_index >= 0 && - entry_index < static_cast<int>(entries_.size())); - NavigationEntry* entry = entries_[entry_index].get(); - - // The URL may have changed due to redirects. The site instance will normally - // be the same except during session restore, when no site instance will be - // assigned. - entry->set_url(params.url); - if (entry->update_virtual_url_with_url()) - UpdateVirtualURLToURL(entry, params.url); - DCHECK(entry->site_instance() == NULL || - entry->site_instance() == tab_contents_->GetSiteInstance()); - entry->set_site_instance(tab_contents_->GetSiteInstance()); - - entry->set_has_post_data(params.is_post); - - // The entry we found in the list might be pending if the user hit - // back/forward/reload. This load should commit it (since it's already in the - // list, we can just discard the pending pointer). - // - // Note that we need to use the "internal" version since we don't want to - // actually change any other state, just kill the pointer. - if (entry == pending_entry_) - DiscardNonCommittedEntriesInternal(); - - // If a transient entry was removed, the indices might have changed, so we - // have to query the entry index again. - last_committed_entry_index_ = - GetEntryIndexWithPageID(tab_contents_->GetSiteInstance(), params.page_id); -} - -void NavigationController::RendererDidNavigateToSamePage( - const ViewHostMsg_FrameNavigate_Params& params) { - // This mode implies we have a pending entry that's the same as an existing - // entry for this page ID. This entry is guaranteed to exist by - // ClassifyNavigation. All we need to do is update the existing entry. - NavigationEntry* existing_entry = GetEntryWithPageID( - tab_contents_->GetSiteInstance(), - params.page_id); - - // We assign the entry's unique ID to be that of the new one. Since this is - // always the result of a user action, we want to dismiss infobars, etc. like - // a regular user-initiated navigation. - existing_entry->set_unique_id(pending_entry_->unique_id()); - - // The URL may have changed due to redirects. - if (existing_entry->update_virtual_url_with_url()) - UpdateVirtualURLToURL(existing_entry, params.url); - existing_entry->set_url(params.url); - - DiscardNonCommittedEntries(); -} - -void NavigationController::RendererDidNavigateInPage( - const ViewHostMsg_FrameNavigate_Params& params, bool* did_replace_entry) { - DCHECK(PageTransition::IsMainFrame(params.transition)) << - "WebKit should only tell us about in-page navs for the main frame."; - // We're guaranteed to have an entry for this one. - NavigationEntry* existing_entry = GetEntryWithPageID( - tab_contents_->GetSiteInstance(), - params.page_id); - - // Reference fragment navigation. We're guaranteed to have the last_committed - // entry and it will be the same page as the new navigation (minus the - // reference fragments, of course). - NavigationEntry* new_entry = new NavigationEntry(*existing_entry); - new_entry->set_page_id(params.page_id); - if (new_entry->update_virtual_url_with_url()) - UpdateVirtualURLToURL(new_entry, params.url); - new_entry->set_url(params.url); - - // This replaces the existing entry since the page ID didn't change. - *did_replace_entry = true; - InsertOrReplaceEntry(new_entry, true); -} - -void NavigationController::RendererDidNavigateNewSubframe( - const ViewHostMsg_FrameNavigate_Params& params) { - if (PageTransition::StripQualifier(params.transition) == - PageTransition::AUTO_SUBFRAME) { - // This is not user-initiated. Ignore. - return; - } - - // Manual subframe navigations just get the current entry cloned so the user - // can go back or forward to it. The actual subframe information will be - // stored in the page state for each of those entries. This happens out of - // band with the actual navigations. - DCHECK(GetLastCommittedEntry()) << "ClassifyNavigation should guarantee " - << "that a last committed entry exists."; - NavigationEntry* new_entry = new NavigationEntry(*GetLastCommittedEntry()); - new_entry->set_page_id(params.page_id); - InsertOrReplaceEntry(new_entry, false); -} - -bool NavigationController::RendererDidNavigateAutoSubframe( - const ViewHostMsg_FrameNavigate_Params& params) { - // We're guaranteed to have a previously committed entry, and we now need to - // handle navigation inside of a subframe in it without creating a new entry. - DCHECK(GetLastCommittedEntry()); - - // Handle the case where we're navigating back/forward to a previous subframe - // navigation entry. This is case "2." in NAV_AUTO_SUBFRAME comment in the - // header file. In case "1." this will be a NOP. - int entry_index = GetEntryIndexWithPageID( - tab_contents_->GetSiteInstance(), - params.page_id); - if (entry_index < 0 || - entry_index >= static_cast<int>(entries_.size())) { - NOTREACHED(); - return false; - } - - // Update the current navigation entry in case we're going back/forward. - if (entry_index != last_committed_entry_index_) { - last_committed_entry_index_ = entry_index; - return true; - } - return false; -} - -// TODO(brettw) I think this function is unnecessary. -void NavigationController::CommitPendingEntry() { - DiscardTransientEntry(); - - if (!pending_entry()) - return; // Nothing to do. - - // Need to save the previous URL for the notification. - LoadCommittedDetails details; - if (GetLastCommittedEntry()) { - details.previous_url = GetLastCommittedEntry()->url(); - details.previous_entry_index = last_committed_entry_index(); - } else { - details.previous_entry_index = -1; - } - - if (pending_entry_index_ >= 0) { - // This is a previous navigation (back/forward) that we're just now - // committing. Just mark it as committed. - details.type = NavigationType::EXISTING_PAGE; - int new_entry_index = pending_entry_index_; - DiscardNonCommittedEntriesInternal(); - - // Mark that entry as committed. - last_committed_entry_index_ = new_entry_index; - } else { - // This is a new navigation. It's easiest to just copy the entry and insert - // it new again, since InsertOrReplaceEntry expects to take ownership and - // also discard the pending entry. We also need to synthesize a page ID. We - // can only do this because this function will only be called by our custom - // TabContents types. For TabContents, the IDs are generated by the - // renderer, so we can't do this. - details.type = NavigationType::NEW_PAGE; - pending_entry_->set_page_id(tab_contents_->GetMaxPageID() + 1); - tab_contents_->UpdateMaxPageID(pending_entry_->page_id()); - InsertOrReplaceEntry(new NavigationEntry(*pending_entry_), false); - } - - // Broadcast the notification of the navigation. - details.entry = GetActiveEntry(); - details.is_auto = false; - details.is_in_page = AreURLsInPageNavigation(details.previous_url, - details.entry->url()); - details.is_main_frame = true; - NotifyNavigationEntryCommitted(&details, 0); -} - -int NavigationController::GetIndexOfEntry( - const NavigationEntry* entry) const { - const NavigationEntries::const_iterator i(std::find( - entries_.begin(), - entries_.end(), - entry)); - return (i == entries_.end()) ? -1 : static_cast<int>(i - entries_.begin()); -} - -bool NavigationController::IsURLInPageNavigation(const GURL& url) const { - NavigationEntry* last_committed = GetLastCommittedEntry(); - if (!last_committed) - return false; - return AreURLsInPageNavigation(last_committed->url(), url); -} - -void NavigationController::CopyStateFrom(const NavigationController& source) { - // Verify that we look new. - DCHECK(entry_count() == 0 && !pending_entry()); - - if (source.entry_count() == 0) - return; // Nothing new to do. - - needs_reload_ = true; - InsertEntriesFrom(source, source.entry_count()); - - session_storage_namespace_ = source.session_storage_namespace_->Clone(); - - FinishRestore(source.last_committed_entry_index_, false); -} - -void NavigationController::CopyStateFromAndPrune(NavigationController* source) { - // This code is intended for use when the last entry is the active entry. - DCHECK((transient_entry_index_ != -1 && - transient_entry_index_ == entry_count() - 1) || - (pending_entry_ && (pending_entry_index_ == -1 || - pending_entry_index_ == entry_count() - 1)) || - (!pending_entry_ && last_committed_entry_index_ == entry_count() - 1)); - - // Remove all the entries leaving the active entry. - PruneAllButActive(); - - // Insert the entries from source. Don't use source->GetCurrentEntryIndex as - // we don't want to copy over the transient entry. - int max_source_index = source->pending_entry_index_ != -1 ? - source->pending_entry_index_ : source->last_committed_entry_index_; - if (max_source_index == -1) - max_source_index = source->entry_count(); - else - max_source_index++; - InsertEntriesFrom(*source, max_source_index); - - // Adjust indices such that the last entry and pending are at the end now. - last_committed_entry_index_ = entry_count() - 1; - if (pending_entry_index_ != -1) - pending_entry_index_ = entry_count() - 1; - if (transient_entry_index_ != -1) { - // There's a transient entry. In this case we want the last committed to - // point to the previous entry. - transient_entry_index_ = entry_count() - 1; - if (last_committed_entry_index_ != -1) - last_committed_entry_index_--; - } -} - -void NavigationController::PruneAllButActive() { - if (transient_entry_index_ != -1) { - // There is a transient entry. Prune up to it. - DCHECK_EQ(entry_count() - 1, transient_entry_index_); - entries_.erase(entries_.begin(), entries_.begin() + transient_entry_index_); - transient_entry_index_ = 0; - last_committed_entry_index_ = -1; - pending_entry_index_ = -1; - } else if (!pending_entry_) { - // There's no pending entry. Leave the last entry (if there is one). - if (!entry_count()) - return; - - DCHECK(last_committed_entry_index_ >= 0); - entries_.erase(entries_.begin(), - entries_.begin() + last_committed_entry_index_); - entries_.erase(entries_.begin() + 1, entries_.end()); - last_committed_entry_index_ = 0; - } else if (pending_entry_index_ != -1) { - entries_.erase(entries_.begin(), entries_.begin() + pending_entry_index_); - entries_.erase(entries_.begin() + 1, entries_.end()); - pending_entry_index_ = 0; - last_committed_entry_index_ = 0; - } else { - // There is a pending_entry, but it's not in entries_. - pending_entry_index_ = -1; - last_committed_entry_index_ = -1; - entries_.clear(); - } - - if (tab_contents_->interstitial_page()) { - // Normally the interstitial page hides itself if the user doesn't proceeed. - // This would result in showing a NavigationEntry we just removed. Set this - // so the interstitial triggers a reload if the user doesn't proceed. - tab_contents_->interstitial_page()->set_reload_on_dont_proceed(true); - } -} - -void NavigationController::DiscardNonCommittedEntries() { - bool transient = transient_entry_index_ != -1; - DiscardNonCommittedEntriesInternal(); - - // If there was a transient entry, invalidate everything so the new active - // entry state is shown. - if (transient) { - tab_contents_->NotifyNavigationStateChanged(kInvalidateAllButShelves); - } -} - -void NavigationController::InsertOrReplaceEntry(NavigationEntry* entry, - bool replace) { - DCHECK(entry->transition_type() != PageTransition::AUTO_SUBFRAME); - - // Copy the pending entry's unique ID to the committed entry. - // I don't know if pending_entry_index_ can be other than -1 here. - const NavigationEntry* const pending_entry = (pending_entry_index_ == -1) ? - pending_entry_ : entries_[pending_entry_index_].get(); - if (pending_entry) - entry->set_unique_id(pending_entry->unique_id()); - - DiscardNonCommittedEntriesInternal(); - - int current_size = static_cast<int>(entries_.size()); - - if (current_size > 0) { - // Prune any entries which are in front of the current entry. - // Also prune the current entry if we are to replace the current entry. - int prune_up_to = replace ? last_committed_entry_index_ - 1 - : last_committed_entry_index_; - int num_pruned = 0; - while (prune_up_to < (current_size - 1)) { - num_pruned++; - entries_.pop_back(); - current_size--; - } - if (num_pruned > 0) // Only notify if we did prune something. - NotifyPrunedEntries(this, false, num_pruned); - } - - if (entries_.size() >= max_entry_count_) { - RemoveEntryAtIndex(0, GURL()); - NotifyPrunedEntries(this, true, 1); - } - - entries_.push_back(linked_ptr<NavigationEntry>(entry)); - last_committed_entry_index_ = static_cast<int>(entries_.size()) - 1; - - // This is a new page ID, so we need everybody to know about it. - tab_contents_->UpdateMaxPageID(entry->page_id()); -} - -void NavigationController::SetWindowID(const SessionID& id) { - window_id_ = id; - NotificationService::current()->Notify(NotificationType::TAB_PARENTED, - Source<NavigationController>(this), - NotificationService::NoDetails()); -} - -void NavigationController::NavigateToPendingEntry(ReloadType reload_type) { - needs_reload_ = false; - - // For session history navigations only the pending_entry_index_ is set. - if (!pending_entry_) { - DCHECK_NE(pending_entry_index_, -1); - pending_entry_ = entries_[pending_entry_index_].get(); - } - - if (!tab_contents_->NavigateToPendingEntry(reload_type)) - DiscardNonCommittedEntries(); -} - -void NavigationController::NotifyNavigationEntryCommitted( - LoadCommittedDetails* details, - int extra_invalidate_flags) { - details->entry = GetActiveEntry(); - NotificationDetails notification_details = - Details<LoadCommittedDetails>(details); - - // We need to notify the ssl_manager_ before the tab_contents_ so the - // location bar will have up-to-date information about the security style - // when it wants to draw. See http://crbug.com/11157 - ssl_manager_.DidCommitProvisionalLoad(notification_details); - - // TODO(pkasting): http://b/1113079 Probably these explicit notification paths - // should be removed, and interested parties should just listen for the - // notification below instead. - tab_contents_->NotifyNavigationStateChanged( - kInvalidateAllButShelves | extra_invalidate_flags); - - NotificationService::current()->Notify( - NotificationType::NAV_ENTRY_COMMITTED, - Source<NavigationController>(this), - notification_details); -} - -// static -void NavigationController::DisablePromptOnRepost() { - check_for_repost_ = false; -} - -void NavigationController::SetActive(bool is_active) { - if (is_active && needs_reload_) - LoadIfNecessary(); -} - -void NavigationController::LoadIfNecessary() { - if (!needs_reload_) - return; - - // Calling Reload() results in ignoring state, and not loading. - // Explicitly use NavigateToPendingEntry so that the renderer uses the - // cached state. - pending_entry_index_ = last_committed_entry_index_; - NavigateToPendingEntry(NO_RELOAD); -} - -void NavigationController::NotifyEntryChanged(const NavigationEntry* entry, - int index) { - EntryChangedDetails det; - det.changed_entry = entry; - det.index = index; - NotificationService::current()->Notify(NotificationType::NAV_ENTRY_CHANGED, - Source<NavigationController>(this), - Details<EntryChangedDetails>(&det)); -} - -void NavigationController::FinishRestore(int selected_index, - bool from_last_session) { - DCHECK(selected_index >= 0 && selected_index < entry_count()); - ConfigureEntriesForRestore(&entries_, from_last_session); - - set_max_restored_page_id(static_cast<int32>(entry_count())); - - last_committed_entry_index_ = selected_index; -} - -void NavigationController::DiscardNonCommittedEntriesInternal() { - if (pending_entry_index_ == -1) - delete pending_entry_; - pending_entry_ = NULL; - pending_entry_index_ = -1; - - DiscardTransientEntry(); -} - -void NavigationController::DiscardTransientEntry() { - if (transient_entry_index_ == -1) - return; - entries_.erase(entries_.begin() + transient_entry_index_); - if (last_committed_entry_index_ > transient_entry_index_) - last_committed_entry_index_--; - transient_entry_index_ = -1; -} - -int NavigationController::GetEntryIndexWithPageID( - SiteInstance* instance, int32 page_id) const { - for (int i = static_cast<int>(entries_.size()) - 1; i >= 0; --i) { - if ((entries_[i]->site_instance() == instance) && - (entries_[i]->page_id() == page_id)) - return i; - } - return -1; -} - -NavigationEntry* NavigationController::GetTransientEntry() const { - if (transient_entry_index_ == -1) - return NULL; - return entries_[transient_entry_index_].get(); -} - -void NavigationController::InsertEntriesFrom( - const NavigationController& source, - int max_index) { - DCHECK_LE(max_index, source.entry_count()); - size_t insert_index = 0; - for (int i = 0; i < max_index; i++) { - // When cloning a tab, copy all entries except interstitial pages - if (source.entries_[i].get()->page_type() != INTERSTITIAL_PAGE) { - entries_.insert(entries_.begin() + insert_index++, - linked_ptr<NavigationEntry>( - new NavigationEntry(*source.entries_[i]))); - } - } -} diff --git a/chrome/browser/tab_contents/navigation_controller.h b/chrome/browser/tab_contents/navigation_controller.h index adbc348..7eb9d11 100644 --- a/chrome/browser/tab_contents/navigation_controller.h +++ b/chrome/browser/tab_contents/navigation_controller.h @@ -6,598 +6,7 @@ #define CHROME_BROWSER_TAB_CONTENTS_NAVIGATION_CONTROLLER_H_ #pragma once -#include "build/build_config.h" - -#include <string> -#include <vector> - -#include "base/linked_ptr.h" -#include "base/time.h" -#include "googleurl/src/gurl.h" -#include "chrome/browser/sessions/session_id.h" -#include "chrome/browser/ssl/ssl_manager.h" -#include "chrome/common/navigation_types.h" -#include "chrome/common/page_transition_types.h" - -class NavigationEntry; -class Profile; -class SessionStorageNamespace; -class SiteInstance; -class TabContents; -class TabNavigation; -struct ViewHostMsg_FrameNavigate_Params; - -// A NavigationController maintains the back-forward list for a single tab and -// manages all navigation within that list. -// -// The NavigationController also owns all TabContents for the tab. This is to -// make sure that we have at most one TabContents instance per type. -class NavigationController { - public: - // Notification details ------------------------------------------------------ - - // Provides the details for a NOTIFY_NAV_ENTRY_CHANGED notification. - struct EntryChangedDetails { - // The changed navigation entry after it has been updated. - const NavigationEntry* changed_entry; - - // Indicates the current index in the back/forward list of the entry. - int index; - }; - - // Provides the details for a NOTIFY_NAV_ENTRY_COMMITTED notification. - // TODO(brettw) this mostly duplicates ProvisionalLoadDetails, it would be - // nice to unify these somehow. - struct LoadCommittedDetails { - // By default, the entry will be filled according to a new main frame - // navigation. - LoadCommittedDetails() - : entry(NULL), - type(NavigationType::UNKNOWN), - previous_entry_index(-1), - is_auto(false), - did_replace_entry(false), - is_in_page(false), - is_main_frame(true), - is_content_filtered(false), - http_status_code(0) { - } - - // The committed entry. This will be the active entry in the controller. - NavigationEntry* entry; - - // The type of navigation that just occurred. Note that not all types of - // navigations in the enum are valid here, since some of them don't actually - // cause a "commit" and won't generate this notification. - NavigationType::Type type; - - // The index of the previously committed navigation entry. This will be -1 - // if there are no previous entries. - int previous_entry_index; - - // The previous URL that the user was on. This may be empty if none. - GURL previous_url; - - // True when this load was non-user initated. This corresponds to a - // a NavigationGestureAuto call from WebKit (see webview_delegate.h). - // We also count reloads and meta-refreshes as "auto" to account for the - // fact that WebKit doesn't always set the user gesture properly in these - // cases (see bug 1051891). - bool is_auto; - - // True if the committed entry has replaced the exisiting one. - // A non-user initiated redirect causes such replacement. - // This is somewhat similiar to is_auto, but not exactly the same. - bool did_replace_entry; - - // True if the navigation was in-page. This means that the active entry's - // URL and the |previous_url| are the same except for reference fragments. - bool is_in_page; - - // True when the main frame was navigated. False means the navigation was a - // sub-frame. - bool is_main_frame; - - // Whether the content of this frame has been altered/blocked because it was - // unsafe. - bool is_content_filtered; - - // When the committed load is a web page from the renderer, this string - // specifies the security state if the page is secure. - // See ViewHostMsg_FrameNavigate_Params.security_info, where it comes from. - // Use SSLManager::DeserializeSecurityInfo to decode it. - std::string serialized_security_info; - - // Returns whether the user probably felt like they navigated somewhere new. - // We often need this logic for showing or hiding something, and this - // returns true only for main frame loads that the user initiated, that go - // to a new page. - bool is_user_initiated_main_frame_load() const { - return !is_auto && !is_in_page && is_main_frame; - } - - // The HTTP status code for this entry.. - int http_status_code; - }; - - // Details sent for NOTIFY_NAV_LIST_PRUNED. - struct PrunedDetails { - // If true, count items were removed from the front of the list, otherwise - // count items were removed from the back of the list. - bool from_front; - - // Number of items removed. - int count; - }; - - enum ReloadType { - NO_RELOAD, // Normal load. - RELOAD, // Normal (cache-validating) reload. - RELOAD_IGNORING_CACHE // Reload bypassing the cache, aka shift-reload. - }; - - // --------------------------------------------------------------------------- - - NavigationController(TabContents* tab_contents, - Profile* profile, - SessionStorageNamespace* session_storage_namespace); - ~NavigationController(); - - // Returns the profile for this controller. It can never be NULL. - Profile* profile() const { - return profile_; - } - - // Sets the profile for this controller. - void set_profile(Profile* profile) { - profile_ = profile; - } - - // Initializes this NavigationController with the given saved navigations, - // using selected_navigation as the currently loaded entry. Before this call - // the controller should be unused (there should be no current entry). If - // from_last_session is true, navigations are from the previous session, - // otherwise they are from the current session (undo tab close). - // This is used for session restore. - void RestoreFromState(const std::vector<TabNavigation>& navigations, - int selected_navigation, bool from_last_session); - - // Active entry -------------------------------------------------------------- - - // Returns the active entry, which is the transient entry if any, the pending - // entry if a navigation is in progress or the last committed entry otherwise. - // NOTE: This can be NULL!! - // - // If you are trying to get the current state of the NavigationController, - // this is the method you will typically want to call. - NavigationEntry* GetActiveEntry() const; - - // Returns the index from which we would go back/forward or reload. This is - // the last_committed_entry_index_ if pending_entry_index_ is -1. Otherwise, - // it is the pending_entry_index_. - int GetCurrentEntryIndex() const; - - // Returns the last committed entry, which may be null if there are no - // committed entries. - NavigationEntry* GetLastCommittedEntry() const; - - // Returns true if the source for the current entry can be viewed. - bool CanViewSource() const; - - // Returns the index of the last committed entry. - int last_committed_entry_index() const { - return last_committed_entry_index_; - } - - // Navigation list ----------------------------------------------------------- - - // Returns the number of entries in the NavigationController, excluding - // the pending entry if there is one, but including the transient entry if - // any. - int entry_count() const { - return static_cast<int>(entries_.size()); - } - - NavigationEntry* GetEntryAtIndex(int index) const { - return entries_.at(index).get(); - } - - // Returns the entry at the specified offset from current. Returns NULL - // if out of bounds. - NavigationEntry* GetEntryAtOffset(int offset) const; - - // Returns the index of the specified entry, or -1 if entry is not contained - // in this NavigationController. - int GetIndexOfEntry(const NavigationEntry* entry) const; - - // Return the index of the entry with the corresponding instance and page_id, - // or -1 if not found. - int GetEntryIndexWithPageID(SiteInstance* instance, - int32 page_id) const; - - // Return the entry with the corresponding instance and page_id, or NULL if - // not found. - NavigationEntry* GetEntryWithPageID(SiteInstance* instance, - int32 page_id) const; - - // Pending entry ------------------------------------------------------------- - - // Commits the current pending entry and issues the NOTIFY_NAV_ENTRY_COMMIT - // notification. No changes are made to the entry during this process, it is - // just moved from pending to committed. This is an alternative to - // RendererDidNavigate for simple TabContents types. - // - // When the pending entry is a new navigation, it will have a page ID of -1. - // The caller should leave this as-is. CommitPendingEntry will generate a - // new page ID for you and update the TabContents with that ID. - void CommitPendingEntry(); - - // Discards the pending and transient entries if any. - void DiscardNonCommittedEntries(); - - // Returns the pending entry corresponding to the navigation that is - // currently in progress, or null if there is none. - NavigationEntry* pending_entry() const { - return pending_entry_; - } - - // Returns the index of the pending entry or -1 if the pending entry - // corresponds to a new navigation (created via LoadURL). - int pending_entry_index() const { - return pending_entry_index_; - } - - // Transient entry ----------------------------------------------------------- - - // Adds an entry that is returned by GetActiveEntry(). The entry is - // transient: any navigation causes it to be removed and discarded. - // The NavigationController becomes the owner of |entry| and deletes it when - // it discards it. This is useful with interstitial page that need to be - // represented as an entry, but should go away when the user navigates away - // from them. - // Note that adding a transient entry does not change the active contents. - void AddTransientEntry(NavigationEntry* entry); - - // Returns the transient entry if any. Note that the returned entry is owned - // by the navigation controller and may be deleted at any time. - NavigationEntry* GetTransientEntry() const; - - // New navigations ----------------------------------------------------------- - - // Loads the specified URL. - void LoadURL(const GURL& url, const GURL& referrer, - PageTransition::Type type); - - // Loads the current page if this NavigationController was restored from - // history and the current page has not loaded yet. - void LoadIfNecessary(); - - // Renavigation -------------------------------------------------------------- - - // Navigation relative to the "current entry" - bool CanGoBack() const; - bool CanGoForward() const; - void GoBack(); - void GoForward(); - - // Navigates to the specified absolute index. - void GoToIndex(int index); - - // Navigates to the specified offset from the "current entry". Does nothing if - // the offset is out of bounds. - void GoToOffset(int offset); - - // Reloads the current entry. If |check_for_repost| is true and the current - // entry has POST data the user is prompted to see if they really want to - // reload the page. In nearly all cases pass in true. - void Reload(bool check_for_repost); - // Like Reload(), but don't use caches (aka "shift-reload"). - void ReloadIgnoringCache(bool check_for_repost); - - // Removing of entries ------------------------------------------------------- - - // Removes the entry at the specified |index|. This call dicards any pending - // and transient entries. |default_url| is the URL that the navigation - // controller navigates to if there are no more entries after the removal. - // If |default_url| is empty, we default to "about:blank". - void RemoveEntryAtIndex(int index, const GURL& default_url); - - // TabContents --------------------------------------------------------------- - - // Returns the tab contents associated with this controller. Non-NULL except - // during set-up of the tab. - TabContents* tab_contents() const { - // This currently returns the active tab contents which should be renamed to - // tab_contents. - return tab_contents_; - } - - // Called when a document has been loaded in a frame. - void DocumentLoadedInFrame(); - - // For use by TabContents ---------------------------------------------------- - - // Handles updating the navigation state after the renderer has navigated. - // This is used by the TabContents. Simpler tab contents types can use - // CommitPendingEntry below. - // - // If a new entry is created, it will return true and will have filled the - // given details structure and broadcast the NOTIFY_NAV_ENTRY_COMMITTED - // notification. The caller can then use the details without worrying about - // listening for the notification. - // - // In the case that nothing has changed, the details structure is undefined - // and it will return false. - // - // |extra_invalidate_flags| are an additional set of flags (InvalidateTypes) - // added to the flags sent to the delegate's NotifyNavigationStateChanged. - bool RendererDidNavigate(const ViewHostMsg_FrameNavigate_Params& params, - int extra_invalidate_flags, - LoadCommittedDetails* details); - - // Notifies us that we just became active. This is used by the TabContents - // so that we know to load URLs that were pending as "lazy" loads. - void SetActive(bool is_active); - - // Broadcasts the NOTIFY_NAV_ENTRY_CHANGED notification for the given entry - // (which must be at the given index). This will keep things in sync like - // the saved session. - void NotifyEntryChanged(const NavigationEntry* entry, int index); - - // Returns true if the given URL would be an in-page navigation (i.e. only - // the reference fragment is different) from the "last committed entry". We do - // not compare it against the "active entry" since the active entry can be - // pending and in page navigations only happen on committed pages. If there - // is no last committed entry, then nothing will be in-page. - // - // Special note: if the URLs are the same, it does NOT count as an in-page - // navigation. Neither does an input URL that has no ref, even if the rest is - // the same. This may seem weird, but when we're considering whether a - // navigation happened without loading anything, the same URL would be a - // reload, while only a different ref would be in-page (pages can't clear - // refs without reload, only change to "#" which we don't count as empty). - bool IsURLInPageNavigation(const GURL& url) const; - - // Copies the navigation state from the given controller to this one. This - // one should be empty (just created). - void CopyStateFrom(const NavigationController& source); - - // A variant of CopyStateFrom. Removes all entries from this except the last - // entry, inserts all entries from |source| before and including the active - // entry. This method is intended for use when the last entry of |this| is the - // active entry. For example: - // source: A B *C* D - // this: E F *G* (last must be active or pending) - // result: A B *G* - // This ignores the transient index of the source and honors that of 'this'. - void CopyStateFromAndPrune(NavigationController* source); - - // Removes all the entries except the active entry. If there is a new pending - // navigation it is preserved. - void PruneAllButActive(); - - // Random data --------------------------------------------------------------- - - // Returns the identifier used by session restore. - const SessionID& session_id() const { return session_id_; } - - // Identifier of the window we're in. - void SetWindowID(const SessionID& id); - const SessionID& window_id() const { return window_id_; } - - SSLManager* ssl_manager() { return &ssl_manager_; } - - // Returns true if a reload happens when activated (SetActive(true) is - // invoked). This is true for session/tab restore and cloned tabs. - bool needs_reload() const { return needs_reload_; } - - // Sets the max restored page ID this NavigationController has seen, if it - // was restored from a previous session. - void set_max_restored_page_id(int32 max_id) { - max_restored_page_id_ = max_id; - } - - // Returns the largest restored page ID seen in this navigation controller, - // if it was restored from a previous session. (-1 otherwise) - int32 max_restored_page_id() const { return max_restored_page_id_; } - - // The session storage namespace that all child render views should use. - SessionStorageNamespace* session_storage_namespace() const { - return session_storage_namespace_; - } - - // Disables checking for a repost and prompting the user. This is used during - // testing. - static void DisablePromptOnRepost(); - - // Maximum number of entries before we start removing entries from the front. -#ifdef UNIT_TEST - static void set_max_entry_count(size_t max_entry_count) { - max_entry_count_ = max_entry_count; - } -#endif - static size_t max_entry_count() { return max_entry_count_; } - - // Cancels a repost that brought up a warning. - void CancelPendingReload(); - // Continues a repost that brought up a warning. - void ContinuePendingReload(); - - // Returns true if we are navigating to the URL the tab is opened with. - bool IsInitialNavigation(); - - // Creates navigation entry and translates the virtual url to a real one. - // Used when restoring a tab from a TabNavigation object and when navigating - // to a new URL using LoadURL. - static NavigationEntry* CreateNavigationEntry(const GURL& url, - const GURL& referrer, - PageTransition::Type transition, - Profile* profile); - - private: - class RestoreHelper; - friend class RestoreHelper; - friend class TabContents; // For invoking OnReservedPageIDRange. - - // Classifies the given renderer navigation (see the NavigationType enum). - NavigationType::Type ClassifyNavigation( - const ViewHostMsg_FrameNavigate_Params& params) const; - - // Causes the controller to load the specified entry. The function assumes - // ownership of the pointer since it is put in the navigation list. - // NOTE: Do not pass an entry that the controller already owns! - void LoadEntry(NavigationEntry* entry); - - // Handlers for the different types of navigation types. They will actually - // handle the navigations corresponding to the different NavClasses above. - // They will NOT broadcast the commit notification, that should be handled by - // the caller. - // - // RendererDidNavigateAutoSubframe is special, it may not actually change - // anything if some random subframe is loaded. It will return true if anything - // changed, or false if not. - // - // The functions taking |did_replace_entry| will fill into the given variable - // whether the last entry has been replaced or not. - // See LoadCommittedDetails.did_replace_entry. - void RendererDidNavigateToNewPage( - const ViewHostMsg_FrameNavigate_Params& params, bool* did_replace_entry); - void RendererDidNavigateToExistingPage( - const ViewHostMsg_FrameNavigate_Params& params); - void RendererDidNavigateToSamePage( - const ViewHostMsg_FrameNavigate_Params& params); - void RendererDidNavigateInPage( - const ViewHostMsg_FrameNavigate_Params& params, bool* did_replace_entry); - void RendererDidNavigateNewSubframe( - const ViewHostMsg_FrameNavigate_Params& params); - bool RendererDidNavigateAutoSubframe( - const ViewHostMsg_FrameNavigate_Params& params); - - // Helper function for code shared between Reload() and ReloadIgnoringCache(). - void ReloadInternal(bool check_for_repost, ReloadType reload_type); - - // Actually issues the navigation held in pending_entry. - void NavigateToPendingEntry(ReloadType reload_type); - - // Allows the derived class to issue notifications that a load has been - // committed. This will fill in the active entry to the details structure. - // - // |extra_invalidate_flags| are an additional set of flags (InvalidateTypes) - // added to the flags sent to the delegate's NotifyNavigationStateChanged. - void NotifyNavigationEntryCommitted(LoadCommittedDetails* details, - int extra_invalidate_flags); - - // Updates the virtual URL of an entry to match a new URL, for cases where - // the real renderer URL is derived from the virtual URL, like view-source: - void UpdateVirtualURLToURL(NavigationEntry* entry, const GURL& new_url); - - // Invoked after session/tab restore or cloning a tab. Resets the transition - // type of the entries, updates the max page id and creates the active - // contents. See RestoreFromState for a description of from_last_session. - void FinishRestore(int selected_index, bool from_last_session); - - // Inserts a new entry or replaces the current entry with a new one, removing - // all entries after it. The new entry will become the active one. - void InsertOrReplaceEntry(NavigationEntry* entry, bool replace); - - // Discards the pending and transient entries. - void DiscardNonCommittedEntriesInternal(); - - // Discards the transient entry. - void DiscardTransientEntry(); - - // Returns true if the navigation is redirect. - bool IsRedirect(const ViewHostMsg_FrameNavigate_Params& params); - - // Returns true if the navigation is likley to be automatic rather than - // user-initiated. - bool IsLikelyAutoNavigation(base::TimeTicks now); - - // Creates a new NavigationEntry for each TabNavigation in navigations, adding - // the NavigationEntry to entries. This is used during session restore. - void CreateNavigationEntriesFromTabNavigations( - const std::vector<TabNavigation>& navigations, - std::vector<linked_ptr<NavigationEntry> >* entries); - - // Inserts up to |max_index| entries from |source| into this. This does NOT - // adjust any of the members that reference entries_ - // (last_committed_entry_index_, pending_entry_index_ or - // transient_entry_index_). - void InsertEntriesFrom(const NavigationController& source, int max_index); - - // --------------------------------------------------------------------------- - - // The user profile associated with this controller - Profile* profile_; - - // List of NavigationEntry for this tab - typedef std::vector<linked_ptr<NavigationEntry> > NavigationEntries; - NavigationEntries entries_; - - // An entry we haven't gotten a response for yet. This will be discarded - // when we navigate again. It's used only so we know what the currently - // displayed tab is. - // - // This may refer to an item in the entries_ list if the pending_entry_index_ - // == -1, or it may be its own entry that should be deleted. Be careful with - // the memory management. - NavigationEntry* pending_entry_; - - // currently visible entry - int last_committed_entry_index_; - - // index of pending entry if it is in entries_, or -1 if pending_entry_ is a - // new entry (created by LoadURL). - int pending_entry_index_; - - // The index for the entry that is shown until a navigation occurs. This is - // used for interstitial pages. -1 if there are no such entry. - // Note that this entry really appears in the list of entries, but only - // temporarily (until the next navigation). Any index pointing to an entry - // after the transient entry will become invalid if you navigate forward. - int transient_entry_index_; - - // The tab contents associated with the controller. Possibly NULL during - // setup. - TabContents* tab_contents_; - - // The max restored page ID in this controller, if it was restored. We must - // store this so that TabContents can tell any renderer in charge of one of - // the restored entries to update its max page ID. - int32 max_restored_page_id_; - - // Manages the SSL security UI - SSLManager ssl_manager_; - - // Whether we need to be reloaded when made active. - bool needs_reload_; - - // Unique identifier of this controller for session restore. This id is only - // unique within the current session, and is not guaranteed to be unique - // across sessions. - SessionID session_id_; - - // Unique identifier of the window we're in. Used by session restore. - SessionID window_id_; - - // The time ticks at which the last document was loaded. - base::TimeTicks last_document_loaded_; - - // The session storage id that any (indirectly) owned RenderView should use. - scoped_refptr<SessionStorageNamespace> session_storage_namespace_; - - // Should Reload check for post data? The default is true, but is set to false - // when testing. - static bool check_for_repost_; - - // The maximum number of entries that a navigation controller can store. - static size_t max_entry_count_; - - // If a repost is pending, its type (RELOAD or RELOAD_IGNORING_CACHE), - // NO_RELOAD otherwise. - ReloadType pending_reload_; - - DISALLOW_COPY_AND_ASSIGN(NavigationController); -}; +// TODO(jam): remove this file when all files have been converted. +#include "content/browser/tab_contents/navigation_controller.h" #endif // CHROME_BROWSER_TAB_CONTENTS_NAVIGATION_CONTROLLER_H_ diff --git a/chrome/browser/tab_contents/navigation_controller_unittest.cc b/chrome/browser/tab_contents/navigation_controller_unittest.cc deleted file mode 100644 index 2691305..0000000 --- a/chrome/browser/tab_contents/navigation_controller_unittest.cc +++ /dev/null @@ -1,2025 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/file_util.h" -#include "base/path_service.h" -#include "base/scoped_ptr.h" -#include "base/stl_util-inl.h" -#include "base/string_util.h" -#include "base/utf_string_conversions.h" -#include "chrome/browser/profiles/profile_manager.h" -#include "chrome/browser/history/history.h" -#include "chrome/browser/renderer_host/site_instance.h" -#include "chrome/browser/renderer_host/test/test_render_view_host.h" -#include "chrome/browser/sessions/session_service.h" -#include "chrome/browser/sessions/session_service_test_helper.h" -#include "chrome/browser/sessions/session_types.h" -#include "chrome/browser/tab_contents/navigation_controller.h" -#include "chrome/browser/tab_contents/navigation_entry.h" -#include "chrome/browser/tab_contents/tab_contents.h" -#include "chrome/browser/tab_contents/tab_contents_delegate.h" -#include "chrome/browser/tab_contents/test_tab_contents.h" -#include "chrome/common/notification_registrar.h" -#include "chrome/common/render_messages.h" -#include "chrome/common/render_messages_params.h" -#include "chrome/test/test_notification_tracker.h" -#include "chrome/test/testing_profile.h" -#include "net/base/net_util.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "webkit/glue/webkit_glue.h" - -using base::Time; - -// NavigationControllerTest ---------------------------------------------------- - -class NavigationControllerTest : public RenderViewHostTestHarness { - public: - NavigationControllerTest() {} -}; - -// NavigationControllerHistoryTest --------------------------------------------- - -class NavigationControllerHistoryTest : public NavigationControllerTest { - public: - NavigationControllerHistoryTest() - : url0("http://foo1"), - url1("http://foo1"), - url2("http://foo1"), - profile_manager_(NULL) { - } - - virtual ~NavigationControllerHistoryTest() { - // Prevent our base class from deleting the profile since profile's - // lifetime is managed by profile_manager_. - STLDeleteElements(&windows_); - } - - // testing::Test overrides. - virtual void SetUp() { - NavigationControllerTest::SetUp(); - - // Force the session service to be created. - SessionService* service = new SessionService(profile()); - profile()->set_session_service(service); - service->SetWindowType(window_id, Browser::TYPE_NORMAL); - service->SetWindowBounds(window_id, gfx::Rect(0, 1, 2, 3), false); - service->SetTabIndexInWindow(window_id, - controller().session_id(), 0); - controller().SetWindowID(window_id); - - session_helper_.set_service(service); - } - - virtual void TearDown() { - // Release profile's reference to the session service. Otherwise the file - // will still be open and we won't be able to delete the directory below. - profile()->set_session_service(NULL); - session_helper_.set_service(NULL); - - // Make sure we wait for history to shut down before continuing. The task - // we add will cause our message loop to quit once it is destroyed. - HistoryService* history = - profile()->GetHistoryService(Profile::IMPLICIT_ACCESS); - if (history) { - history->SetOnBackendDestroyTask(new MessageLoop::QuitTask); - MessageLoop::current()->Run(); - } - - // Do normal cleanup before deleting the profile directory below. - NavigationControllerTest::TearDown(); - - ASSERT_TRUE(file_util::Delete(test_dir_, true)); - ASSERT_FALSE(file_util::PathExists(test_dir_)); - } - - // Deletes the current profile manager and creates a new one. Indirectly this - // shuts down the history database and reopens it. - void ReopenDatabase() { - session_helper_.set_service(NULL); - profile()->set_session_service(NULL); - - SessionService* service = new SessionService(profile()); - profile()->set_session_service(service); - session_helper_.set_service(service); - } - - void GetLastSession() { - profile()->GetSessionService()->TabClosed(controller().window_id(), - controller().session_id(), - false); - - ReopenDatabase(); - Time close_time; - - session_helper_.ReadWindows(&windows_); - } - - CancelableRequestConsumer consumer; - - // URLs for testing. - const GURL url0; - const GURL url1; - const GURL url2; - - std::vector<SessionWindow*> windows_; - - SessionID window_id; - - SessionServiceTestHelper session_helper_; - - private: - ProfileManager* profile_manager_; - FilePath test_dir_; -}; - -void RegisterForAllNavNotifications(TestNotificationTracker* tracker, - NavigationController* controller) { - tracker->ListenFor(NotificationType::NAV_ENTRY_COMMITTED, - Source<NavigationController>(controller)); - tracker->ListenFor(NotificationType::NAV_LIST_PRUNED, - Source<NavigationController>(controller)); - tracker->ListenFor(NotificationType::NAV_ENTRY_CHANGED, - Source<NavigationController>(controller)); -} - -// ----------------------------------------------------------------------------- - -TEST_F(NavigationControllerTest, Defaults) { - EXPECT_FALSE(controller().pending_entry()); - EXPECT_FALSE(controller().GetLastCommittedEntry()); - EXPECT_EQ(controller().pending_entry_index(), -1); - EXPECT_EQ(controller().last_committed_entry_index(), -1); - EXPECT_EQ(controller().entry_count(), 0); - EXPECT_FALSE(controller().CanGoBack()); - EXPECT_FALSE(controller().CanGoForward()); -} - -TEST_F(NavigationControllerTest, LoadURL) { - TestNotificationTracker notifications; - RegisterForAllNavNotifications(¬ifications, &controller()); - - const GURL url1("http://foo1"); - const GURL url2("http://foo2"); - - controller().LoadURL(url1, GURL(), PageTransition::TYPED); - // Creating a pending notification should not have issued any of the - // notifications we're listening for. - EXPECT_EQ(0U, notifications.size()); - - // The load should now be pending. - EXPECT_EQ(controller().entry_count(), 0); - EXPECT_EQ(controller().last_committed_entry_index(), -1); - EXPECT_EQ(controller().pending_entry_index(), -1); - EXPECT_FALSE(controller().GetLastCommittedEntry()); - EXPECT_TRUE(controller().pending_entry()); - EXPECT_FALSE(controller().CanGoBack()); - EXPECT_FALSE(controller().CanGoForward()); - EXPECT_EQ(contents()->GetMaxPageID(), -1); - - // We should have gotten no notifications from the preceeding checks. - EXPECT_EQ(0U, notifications.size()); - - rvh()->SendNavigate(0, url1); - EXPECT_TRUE(notifications.Check1AndReset( - NotificationType::NAV_ENTRY_COMMITTED)); - - // The load should now be committed. - EXPECT_EQ(controller().entry_count(), 1); - EXPECT_EQ(controller().last_committed_entry_index(), 0); - EXPECT_EQ(controller().pending_entry_index(), -1); - EXPECT_TRUE(controller().GetLastCommittedEntry()); - EXPECT_FALSE(controller().pending_entry()); - EXPECT_FALSE(controller().CanGoBack()); - EXPECT_FALSE(controller().CanGoForward()); - EXPECT_EQ(contents()->GetMaxPageID(), 0); - - // Load another... - controller().LoadURL(url2, GURL(), PageTransition::TYPED); - - // The load should now be pending. - EXPECT_EQ(controller().entry_count(), 1); - EXPECT_EQ(controller().last_committed_entry_index(), 0); - EXPECT_EQ(controller().pending_entry_index(), -1); - EXPECT_TRUE(controller().GetLastCommittedEntry()); - EXPECT_TRUE(controller().pending_entry()); - // TODO(darin): maybe this should really be true? - EXPECT_FALSE(controller().CanGoBack()); - EXPECT_FALSE(controller().CanGoForward()); - EXPECT_EQ(contents()->GetMaxPageID(), 0); - - rvh()->SendNavigate(1, url2); - EXPECT_TRUE(notifications.Check1AndReset( - NotificationType::NAV_ENTRY_COMMITTED)); - - // The load should now be committed. - EXPECT_EQ(controller().entry_count(), 2); - EXPECT_EQ(controller().last_committed_entry_index(), 1); - EXPECT_EQ(controller().pending_entry_index(), -1); - EXPECT_TRUE(controller().GetLastCommittedEntry()); - EXPECT_FALSE(controller().pending_entry()); - EXPECT_TRUE(controller().CanGoBack()); - EXPECT_FALSE(controller().CanGoForward()); - EXPECT_EQ(contents()->GetMaxPageID(), 1); -} - -// Tests what happens when the same page is loaded again. Should not create a -// new session history entry. This is what happens when you press enter in the -// URL bar to reload: a pending entry is created and then it is discarded when -// the load commits (because WebCore didn't actually make a new entry). -TEST_F(NavigationControllerTest, LoadURL_SamePage) { - TestNotificationTracker notifications; - RegisterForAllNavNotifications(¬ifications, &controller()); - - const GURL url1("http://foo1"); - - controller().LoadURL(url1, GURL(), PageTransition::TYPED); - EXPECT_EQ(0U, notifications.size()); - rvh()->SendNavigate(0, url1); - EXPECT_TRUE(notifications.Check1AndReset( - NotificationType::NAV_ENTRY_COMMITTED)); - - controller().LoadURL(url1, GURL(), PageTransition::TYPED); - EXPECT_EQ(0U, notifications.size()); - rvh()->SendNavigate(0, url1); - EXPECT_TRUE(notifications.Check1AndReset( - NotificationType::NAV_ENTRY_COMMITTED)); - - // We should not have produced a new session history entry. - EXPECT_EQ(controller().entry_count(), 1); - EXPECT_EQ(controller().last_committed_entry_index(), 0); - EXPECT_EQ(controller().pending_entry_index(), -1); - EXPECT_TRUE(controller().GetLastCommittedEntry()); - EXPECT_FALSE(controller().pending_entry()); - EXPECT_FALSE(controller().CanGoBack()); - EXPECT_FALSE(controller().CanGoForward()); -} - -// Tests loading a URL but discarding it before the load commits. -TEST_F(NavigationControllerTest, LoadURL_Discarded) { - TestNotificationTracker notifications; - RegisterForAllNavNotifications(¬ifications, &controller()); - - const GURL url1("http://foo1"); - const GURL url2("http://foo2"); - - controller().LoadURL(url1, GURL(), PageTransition::TYPED); - EXPECT_EQ(0U, notifications.size()); - rvh()->SendNavigate(0, url1); - EXPECT_TRUE(notifications.Check1AndReset( - NotificationType::NAV_ENTRY_COMMITTED)); - - controller().LoadURL(url2, GURL(), PageTransition::TYPED); - controller().DiscardNonCommittedEntries(); - EXPECT_EQ(0U, notifications.size()); - - // Should not have produced a new session history entry. - EXPECT_EQ(controller().entry_count(), 1); - EXPECT_EQ(controller().last_committed_entry_index(), 0); - EXPECT_EQ(controller().pending_entry_index(), -1); - EXPECT_TRUE(controller().GetLastCommittedEntry()); - EXPECT_FALSE(controller().pending_entry()); - EXPECT_FALSE(controller().CanGoBack()); - EXPECT_FALSE(controller().CanGoForward()); -} - -// Tests navigations that come in unrequested. This happens when the user -// navigates from the web page, and here we test that there is no pending entry. -TEST_F(NavigationControllerTest, LoadURL_NoPending) { - TestNotificationTracker notifications; - RegisterForAllNavNotifications(¬ifications, &controller()); - - // First make an existing committed entry. - const GURL kExistingURL1("http://eh"); - controller().LoadURL(kExistingURL1, GURL(), - PageTransition::TYPED); - rvh()->SendNavigate(0, kExistingURL1); - EXPECT_TRUE(notifications.Check1AndReset( - NotificationType::NAV_ENTRY_COMMITTED)); - - // Do a new navigation without making a pending one. - const GURL kNewURL("http://see"); - rvh()->SendNavigate(99, kNewURL); - - // There should no longer be any pending entry, and the third navigation we - // just made should be committed. - EXPECT_TRUE(notifications.Check1AndReset( - NotificationType::NAV_ENTRY_COMMITTED)); - EXPECT_EQ(-1, controller().pending_entry_index()); - EXPECT_EQ(1, controller().last_committed_entry_index()); - EXPECT_EQ(kNewURL, controller().GetActiveEntry()->url()); -} - -// Tests navigating to a new URL when there is a new pending navigation that is -// not the one that just loaded. This will happen if the user types in a URL to -// somewhere slow, and then navigates the current page before the typed URL -// commits. -TEST_F(NavigationControllerTest, LoadURL_NewPending) { - TestNotificationTracker notifications; - RegisterForAllNavNotifications(¬ifications, &controller()); - - // First make an existing committed entry. - const GURL kExistingURL1("http://eh"); - controller().LoadURL(kExistingURL1, GURL(), - PageTransition::TYPED); - rvh()->SendNavigate(0, kExistingURL1); - EXPECT_TRUE(notifications.Check1AndReset( - NotificationType::NAV_ENTRY_COMMITTED)); - - // Make a pending entry to somewhere new. - const GURL kExistingURL2("http://bee"); - controller().LoadURL(kExistingURL2, GURL(), - PageTransition::TYPED); - EXPECT_EQ(0U, notifications.size()); - - // Before that commits, do a new navigation. - const GURL kNewURL("http://see"); - rvh()->SendNavigate(3, kNewURL); - - // There should no longer be any pending entry, and the third navigation we - // just made should be committed. - EXPECT_TRUE(notifications.Check1AndReset( - NotificationType::NAV_ENTRY_COMMITTED)); - EXPECT_EQ(-1, controller().pending_entry_index()); - EXPECT_EQ(1, controller().last_committed_entry_index()); - EXPECT_EQ(kNewURL, controller().GetActiveEntry()->url()); -} - -// Tests navigating to a new URL when there is a pending back/forward -// navigation. This will happen if the user hits back, but before that commits, -// they navigate somewhere new. -TEST_F(NavigationControllerTest, LoadURL_ExistingPending) { - TestNotificationTracker notifications; - RegisterForAllNavNotifications(¬ifications, &controller()); - - // First make some history. - const GURL kExistingURL1("http://eh"); - controller().LoadURL(kExistingURL1, GURL(), - PageTransition::TYPED); - rvh()->SendNavigate(0, kExistingURL1); - EXPECT_TRUE(notifications.Check1AndReset( - NotificationType::NAV_ENTRY_COMMITTED)); - - const GURL kExistingURL2("http://bee"); - controller().LoadURL(kExistingURL2, GURL(), - PageTransition::TYPED); - rvh()->SendNavigate(1, kExistingURL2); - EXPECT_TRUE(notifications.Check1AndReset( - NotificationType::NAV_ENTRY_COMMITTED)); - - // Now make a pending back/forward navigation. The zeroth entry should be - // pending. - controller().GoBack(); - EXPECT_EQ(0U, notifications.size()); - EXPECT_EQ(0, controller().pending_entry_index()); - EXPECT_EQ(1, controller().last_committed_entry_index()); - - // Before that commits, do a new navigation. - const GURL kNewURL("http://see"); - NavigationController::LoadCommittedDetails details; - rvh()->SendNavigate(3, kNewURL); - - // There should no longer be any pending entry, and the third navigation we - // just made should be committed. - EXPECT_TRUE(notifications.Check1AndReset( - NotificationType::NAV_ENTRY_COMMITTED)); - EXPECT_EQ(-1, controller().pending_entry_index()); - EXPECT_EQ(2, controller().last_committed_entry_index()); - EXPECT_EQ(kNewURL, controller().GetActiveEntry()->url()); -} - -TEST_F(NavigationControllerTest, Reload) { - TestNotificationTracker notifications; - RegisterForAllNavNotifications(¬ifications, &controller()); - - const GURL url1("http://foo1"); - - controller().LoadURL(url1, GURL(), PageTransition::TYPED); - EXPECT_EQ(0U, notifications.size()); - rvh()->SendNavigate(0, url1); - EXPECT_TRUE(notifications.Check1AndReset( - NotificationType::NAV_ENTRY_COMMITTED)); - - controller().Reload(true); - EXPECT_EQ(0U, notifications.size()); - - // The reload is pending. - EXPECT_EQ(controller().entry_count(), 1); - EXPECT_EQ(controller().last_committed_entry_index(), 0); - EXPECT_EQ(controller().pending_entry_index(), 0); - EXPECT_TRUE(controller().GetLastCommittedEntry()); - EXPECT_TRUE(controller().pending_entry()); - EXPECT_FALSE(controller().CanGoBack()); - EXPECT_FALSE(controller().CanGoForward()); - - rvh()->SendNavigate(0, url1); - EXPECT_TRUE(notifications.Check1AndReset( - NotificationType::NAV_ENTRY_COMMITTED)); - - // Now the reload is committed. - EXPECT_EQ(controller().entry_count(), 1); - EXPECT_EQ(controller().last_committed_entry_index(), 0); - EXPECT_EQ(controller().pending_entry_index(), -1); - EXPECT_TRUE(controller().GetLastCommittedEntry()); - EXPECT_FALSE(controller().pending_entry()); - EXPECT_FALSE(controller().CanGoBack()); - EXPECT_FALSE(controller().CanGoForward()); -} - -// Tests what happens when a reload navigation produces a new page. -TEST_F(NavigationControllerTest, Reload_GeneratesNewPage) { - TestNotificationTracker notifications; - RegisterForAllNavNotifications(¬ifications, &controller()); - - const GURL url1("http://foo1"); - const GURL url2("http://foo2"); - - controller().LoadURL(url1, GURL(), PageTransition::TYPED); - rvh()->SendNavigate(0, url1); - EXPECT_TRUE(notifications.Check1AndReset( - NotificationType::NAV_ENTRY_COMMITTED)); - - controller().Reload(true); - EXPECT_EQ(0U, notifications.size()); - - rvh()->SendNavigate(1, url2); - EXPECT_TRUE(notifications.Check1AndReset( - NotificationType::NAV_ENTRY_COMMITTED)); - - // Now the reload is committed. - EXPECT_EQ(controller().entry_count(), 2); - EXPECT_EQ(controller().last_committed_entry_index(), 1); - EXPECT_EQ(controller().pending_entry_index(), -1); - EXPECT_TRUE(controller().GetLastCommittedEntry()); - EXPECT_FALSE(controller().pending_entry()); - EXPECT_TRUE(controller().CanGoBack()); - EXPECT_FALSE(controller().CanGoForward()); -} - -// Tests what happens when we navigate back successfully -TEST_F(NavigationControllerTest, Back) { - TestNotificationTracker notifications; - RegisterForAllNavNotifications(¬ifications, &controller()); - - const GURL url1("http://foo1"); - rvh()->SendNavigate(0, url1); - EXPECT_TRUE(notifications.Check1AndReset( - NotificationType::NAV_ENTRY_COMMITTED)); - - const GURL url2("http://foo2"); - rvh()->SendNavigate(1, url2); - EXPECT_TRUE(notifications.Check1AndReset( - NotificationType::NAV_ENTRY_COMMITTED)); - - controller().GoBack(); - EXPECT_EQ(0U, notifications.size()); - - // We should now have a pending navigation to go back. - EXPECT_EQ(controller().entry_count(), 2); - EXPECT_EQ(controller().last_committed_entry_index(), 1); - EXPECT_EQ(controller().pending_entry_index(), 0); - EXPECT_TRUE(controller().GetLastCommittedEntry()); - EXPECT_TRUE(controller().pending_entry()); - EXPECT_FALSE(controller().CanGoBack()); - EXPECT_TRUE(controller().CanGoForward()); - - rvh()->SendNavigate(0, url2); - EXPECT_TRUE(notifications.Check1AndReset( - NotificationType::NAV_ENTRY_COMMITTED)); - - // The back navigation completed successfully. - EXPECT_EQ(controller().entry_count(), 2); - EXPECT_EQ(controller().last_committed_entry_index(), 0); - EXPECT_EQ(controller().pending_entry_index(), -1); - EXPECT_TRUE(controller().GetLastCommittedEntry()); - EXPECT_FALSE(controller().pending_entry()); - EXPECT_FALSE(controller().CanGoBack()); - EXPECT_TRUE(controller().CanGoForward()); -} - -// Tests what happens when a back navigation produces a new page. -TEST_F(NavigationControllerTest, Back_GeneratesNewPage) { - TestNotificationTracker notifications; - RegisterForAllNavNotifications(¬ifications, &controller()); - - const GURL url1("http://foo1"); - const GURL url2("http://foo2"); - const GURL url3("http://foo3"); - - controller().LoadURL(url1, GURL(), PageTransition::TYPED); - rvh()->SendNavigate(0, url1); - EXPECT_TRUE(notifications.Check1AndReset( - NotificationType::NAV_ENTRY_COMMITTED)); - - controller().LoadURL(url2, GURL(), PageTransition::TYPED); - rvh()->SendNavigate(1, url2); - EXPECT_TRUE(notifications.Check1AndReset( - NotificationType::NAV_ENTRY_COMMITTED)); - - controller().GoBack(); - EXPECT_EQ(0U, notifications.size()); - - // We should now have a pending navigation to go back. - EXPECT_EQ(controller().entry_count(), 2); - EXPECT_EQ(controller().last_committed_entry_index(), 1); - EXPECT_EQ(controller().pending_entry_index(), 0); - EXPECT_TRUE(controller().GetLastCommittedEntry()); - EXPECT_TRUE(controller().pending_entry()); - EXPECT_FALSE(controller().CanGoBack()); - EXPECT_TRUE(controller().CanGoForward()); - - rvh()->SendNavigate(2, url3); - EXPECT_TRUE(notifications.Check1AndReset( - NotificationType::NAV_ENTRY_COMMITTED)); - - // The back navigation resulted in a completely new navigation. - // TODO(darin): perhaps this behavior will be confusing to users? - EXPECT_EQ(controller().entry_count(), 3); - EXPECT_EQ(controller().last_committed_entry_index(), 2); - EXPECT_EQ(controller().pending_entry_index(), -1); - EXPECT_TRUE(controller().GetLastCommittedEntry()); - EXPECT_FALSE(controller().pending_entry()); - EXPECT_TRUE(controller().CanGoBack()); - EXPECT_FALSE(controller().CanGoForward()); -} - -// Receives a back message when there is a new pending navigation entry. -TEST_F(NavigationControllerTest, Back_NewPending) { - TestNotificationTracker notifications; - RegisterForAllNavNotifications(¬ifications, &controller()); - - const GURL kUrl1("http://foo1"); - const GURL kUrl2("http://foo2"); - const GURL kUrl3("http://foo3"); - - // First navigate two places so we have some back history. - rvh()->SendNavigate(0, kUrl1); - EXPECT_TRUE(notifications.Check1AndReset( - NotificationType::NAV_ENTRY_COMMITTED)); - - // controller().LoadURL(kUrl2, PageTransition::TYPED); - rvh()->SendNavigate(1, kUrl2); - EXPECT_TRUE(notifications.Check1AndReset( - NotificationType::NAV_ENTRY_COMMITTED)); - - // Now start a new pending navigation and go back before it commits. - controller().LoadURL(kUrl3, GURL(), PageTransition::TYPED); - EXPECT_EQ(-1, controller().pending_entry_index()); - EXPECT_EQ(kUrl3, controller().pending_entry()->url()); - controller().GoBack(); - - // The pending navigation should now be the "back" item and the new one - // should be gone. - EXPECT_EQ(0, controller().pending_entry_index()); - EXPECT_EQ(kUrl1, controller().pending_entry()->url()); -} - -// Receives a back message when there is a different renavigation already -// pending. -TEST_F(NavigationControllerTest, Back_OtherBackPending) { - const GURL kUrl1("http://foo/1"); - const GURL kUrl2("http://foo/2"); - const GURL kUrl3("http://foo/3"); - - // First navigate three places so we have some back history. - rvh()->SendNavigate(0, kUrl1); - rvh()->SendNavigate(1, kUrl2); - rvh()->SendNavigate(2, kUrl3); - - // With nothing pending, say we get a navigation to the second entry. - rvh()->SendNavigate(1, kUrl2); - - // We know all the entries have the same site instance, so we can just grab - // a random one for looking up other entries. - SiteInstance* site_instance = - controller().GetLastCommittedEntry()->site_instance(); - - // That second URL should be the last committed and it should have gotten the - // new title. - EXPECT_EQ(kUrl2, controller().GetEntryWithPageID(site_instance, 1)->url()); - EXPECT_EQ(1, controller().last_committed_entry_index()); - EXPECT_EQ(-1, controller().pending_entry_index()); - - // Now go forward to the last item again and say it was committed. - controller().GoForward(); - rvh()->SendNavigate(2, kUrl3); - - // Now start going back one to the second page. It will be pending. - controller().GoBack(); - EXPECT_EQ(1, controller().pending_entry_index()); - EXPECT_EQ(2, controller().last_committed_entry_index()); - - // Not synthesize a totally new back event to the first page. This will not - // match the pending one. - rvh()->SendNavigate(0, kUrl1); - - // The navigation should not have affected the pending entry. - EXPECT_EQ(1, controller().pending_entry_index()); - - // But the navigated entry should be the last committed. - EXPECT_EQ(0, controller().last_committed_entry_index()); - EXPECT_EQ(kUrl1, controller().GetLastCommittedEntry()->url()); -} - -// Tests what happens when we navigate forward successfully. -TEST_F(NavigationControllerTest, Forward) { - TestNotificationTracker notifications; - RegisterForAllNavNotifications(¬ifications, &controller()); - - const GURL url1("http://foo1"); - const GURL url2("http://foo2"); - - rvh()->SendNavigate(0, url1); - EXPECT_TRUE(notifications.Check1AndReset( - NotificationType::NAV_ENTRY_COMMITTED)); - - rvh()->SendNavigate(1, url2); - EXPECT_TRUE(notifications.Check1AndReset( - NotificationType::NAV_ENTRY_COMMITTED)); - - controller().GoBack(); - rvh()->SendNavigate(0, url1); - EXPECT_TRUE(notifications.Check1AndReset( - NotificationType::NAV_ENTRY_COMMITTED)); - - controller().GoForward(); - - // We should now have a pending navigation to go forward. - EXPECT_EQ(controller().entry_count(), 2); - EXPECT_EQ(controller().last_committed_entry_index(), 0); - EXPECT_EQ(controller().pending_entry_index(), 1); - EXPECT_TRUE(controller().GetLastCommittedEntry()); - EXPECT_TRUE(controller().pending_entry()); - EXPECT_TRUE(controller().CanGoBack()); - EXPECT_FALSE(controller().CanGoForward()); - - rvh()->SendNavigate(1, url2); - EXPECT_TRUE(notifications.Check1AndReset( - NotificationType::NAV_ENTRY_COMMITTED)); - - // The forward navigation completed successfully. - EXPECT_EQ(controller().entry_count(), 2); - EXPECT_EQ(controller().last_committed_entry_index(), 1); - EXPECT_EQ(controller().pending_entry_index(), -1); - EXPECT_TRUE(controller().GetLastCommittedEntry()); - EXPECT_FALSE(controller().pending_entry()); - EXPECT_TRUE(controller().CanGoBack()); - EXPECT_FALSE(controller().CanGoForward()); -} - -// Tests what happens when a forward navigation produces a new page. -TEST_F(NavigationControllerTest, Forward_GeneratesNewPage) { - TestNotificationTracker notifications; - RegisterForAllNavNotifications(¬ifications, &controller()); - - const GURL url1("http://foo1"); - const GURL url2("http://foo2"); - const GURL url3("http://foo3"); - - rvh()->SendNavigate(0, url1); - EXPECT_TRUE(notifications.Check1AndReset( - NotificationType::NAV_ENTRY_COMMITTED)); - rvh()->SendNavigate(1, url2); - EXPECT_TRUE(notifications.Check1AndReset( - NotificationType::NAV_ENTRY_COMMITTED)); - - controller().GoBack(); - rvh()->SendNavigate(0, url1); - EXPECT_TRUE(notifications.Check1AndReset( - NotificationType::NAV_ENTRY_COMMITTED)); - - controller().GoForward(); - EXPECT_EQ(0U, notifications.size()); - - // Should now have a pending navigation to go forward. - EXPECT_EQ(controller().entry_count(), 2); - EXPECT_EQ(controller().last_committed_entry_index(), 0); - EXPECT_EQ(controller().pending_entry_index(), 1); - EXPECT_TRUE(controller().GetLastCommittedEntry()); - EXPECT_TRUE(controller().pending_entry()); - EXPECT_TRUE(controller().CanGoBack()); - EXPECT_FALSE(controller().CanGoForward()); - - rvh()->SendNavigate(2, url3); - EXPECT_TRUE(notifications.Check2AndReset( - NotificationType::NAV_LIST_PRUNED, - NotificationType::NAV_ENTRY_COMMITTED)); - - EXPECT_EQ(controller().entry_count(), 2); - EXPECT_EQ(controller().last_committed_entry_index(), 1); - EXPECT_EQ(controller().pending_entry_index(), -1); - EXPECT_TRUE(controller().GetLastCommittedEntry()); - EXPECT_FALSE(controller().pending_entry()); - EXPECT_TRUE(controller().CanGoBack()); - EXPECT_FALSE(controller().CanGoForward()); -} - -// Two consequent navigation for the same URL entered in should be considered -// as SAME_PAGE navigation even when we are redirected to some other page. -TEST_F(NavigationControllerTest, Redirect) { - TestNotificationTracker notifications; - RegisterForAllNavNotifications(¬ifications, &controller()); - - const GURL url1("http://foo1"); - const GURL url2("http://foo2"); // Redirection target - - // First request - controller().LoadURL(url1, GURL(), PageTransition::TYPED); - - EXPECT_EQ(0U, notifications.size()); - rvh()->SendNavigate(0, url2); - EXPECT_TRUE(notifications.Check1AndReset( - NotificationType::NAV_ENTRY_COMMITTED)); - - // Second request - controller().LoadURL(url1, GURL(), PageTransition::TYPED); - - EXPECT_TRUE(controller().pending_entry()); - EXPECT_EQ(controller().pending_entry_index(), -1); - EXPECT_EQ(url1, controller().GetActiveEntry()->url()); - - ViewHostMsg_FrameNavigate_Params params; - params.page_id = 0; - params.url = url2; - params.transition = PageTransition::SERVER_REDIRECT; - params.redirects.push_back(GURL("http://foo1")); - params.redirects.push_back(GURL("http://foo2")); - params.should_update_history = false; - params.gesture = NavigationGestureAuto; - params.is_post = false; - - NavigationController::LoadCommittedDetails details; - - EXPECT_EQ(0U, notifications.size()); - EXPECT_TRUE(controller().RendererDidNavigate(params, 0, &details)); - EXPECT_TRUE(notifications.Check1AndReset( - NotificationType::NAV_ENTRY_COMMITTED)); - - EXPECT_TRUE(details.type == NavigationType::SAME_PAGE); - EXPECT_EQ(controller().entry_count(), 1); - EXPECT_EQ(controller().last_committed_entry_index(), 0); - EXPECT_TRUE(controller().GetLastCommittedEntry()); - EXPECT_EQ(controller().pending_entry_index(), -1); - EXPECT_FALSE(controller().pending_entry()); - EXPECT_EQ(url2, controller().GetActiveEntry()->url()); - - EXPECT_FALSE(controller().CanGoBack()); - EXPECT_FALSE(controller().CanGoForward()); -} - -// Similar to Redirect above, but the first URL is requested by POST, -// the second URL is requested by GET. NavigationEntry::has_post_data_ -// must be cleared. http://crbug.com/21245 -TEST_F(NavigationControllerTest, PostThenRedirect) { - TestNotificationTracker notifications; - RegisterForAllNavNotifications(¬ifications, &controller()); - - const GURL url1("http://foo1"); - const GURL url2("http://foo2"); // Redirection target - - // First request as POST - controller().LoadURL(url1, GURL(), PageTransition::TYPED); - controller().GetActiveEntry()->set_has_post_data(true); - - EXPECT_EQ(0U, notifications.size()); - rvh()->SendNavigate(0, url2); - EXPECT_TRUE(notifications.Check1AndReset( - NotificationType::NAV_ENTRY_COMMITTED)); - - // Second request - controller().LoadURL(url1, GURL(), PageTransition::TYPED); - - EXPECT_TRUE(controller().pending_entry()); - EXPECT_EQ(controller().pending_entry_index(), -1); - EXPECT_EQ(url1, controller().GetActiveEntry()->url()); - - ViewHostMsg_FrameNavigate_Params params; - params.page_id = 0; - params.url = url2; - params.transition = PageTransition::SERVER_REDIRECT; - params.redirects.push_back(GURL("http://foo1")); - params.redirects.push_back(GURL("http://foo2")); - params.should_update_history = false; - params.gesture = NavigationGestureAuto; - params.is_post = false; - - NavigationController::LoadCommittedDetails details; - - EXPECT_EQ(0U, notifications.size()); - EXPECT_TRUE(controller().RendererDidNavigate(params, 0, &details)); - EXPECT_TRUE(notifications.Check1AndReset( - NotificationType::NAV_ENTRY_COMMITTED)); - - EXPECT_TRUE(details.type == NavigationType::SAME_PAGE); - EXPECT_EQ(controller().entry_count(), 1); - EXPECT_EQ(controller().last_committed_entry_index(), 0); - EXPECT_TRUE(controller().GetLastCommittedEntry()); - EXPECT_EQ(controller().pending_entry_index(), -1); - EXPECT_FALSE(controller().pending_entry()); - EXPECT_EQ(url2, controller().GetActiveEntry()->url()); - EXPECT_FALSE(controller().GetActiveEntry()->has_post_data()); - - EXPECT_FALSE(controller().CanGoBack()); - EXPECT_FALSE(controller().CanGoForward()); -} - -// A redirect right off the bat should be a NEW_PAGE. -TEST_F(NavigationControllerTest, ImmediateRedirect) { - TestNotificationTracker notifications; - RegisterForAllNavNotifications(¬ifications, &controller()); - - const GURL url1("http://foo1"); - const GURL url2("http://foo2"); // Redirection target - - // First request - controller().LoadURL(url1, GURL(), PageTransition::TYPED); - - EXPECT_TRUE(controller().pending_entry()); - EXPECT_EQ(controller().pending_entry_index(), -1); - EXPECT_EQ(url1, controller().GetActiveEntry()->url()); - - ViewHostMsg_FrameNavigate_Params params; - params.page_id = 0; - params.url = url2; - params.transition = PageTransition::SERVER_REDIRECT; - params.redirects.push_back(GURL("http://foo1")); - params.redirects.push_back(GURL("http://foo2")); - params.should_update_history = false; - params.gesture = NavigationGestureAuto; - params.is_post = false; - - NavigationController::LoadCommittedDetails details; - - EXPECT_EQ(0U, notifications.size()); - EXPECT_TRUE(controller().RendererDidNavigate(params, 0, &details)); - EXPECT_TRUE(notifications.Check1AndReset( - NotificationType::NAV_ENTRY_COMMITTED)); - - EXPECT_TRUE(details.type == NavigationType::NEW_PAGE); - EXPECT_EQ(controller().entry_count(), 1); - EXPECT_EQ(controller().last_committed_entry_index(), 0); - EXPECT_TRUE(controller().GetLastCommittedEntry()); - EXPECT_EQ(controller().pending_entry_index(), -1); - EXPECT_FALSE(controller().pending_entry()); - EXPECT_EQ(url2, controller().GetActiveEntry()->url()); - - EXPECT_FALSE(controller().CanGoBack()); - EXPECT_FALSE(controller().CanGoForward()); -} - -// Tests navigation via link click within a subframe. A new navigation entry -// should be created. -TEST_F(NavigationControllerTest, NewSubframe) { - TestNotificationTracker notifications; - RegisterForAllNavNotifications(¬ifications, &controller()); - - const GURL url1("http://foo1"); - rvh()->SendNavigate(0, url1); - EXPECT_TRUE(notifications.Check1AndReset( - NotificationType::NAV_ENTRY_COMMITTED)); - - const GURL url2("http://foo2"); - ViewHostMsg_FrameNavigate_Params params; - params.page_id = 1; - params.url = url2; - params.transition = PageTransition::MANUAL_SUBFRAME; - params.should_update_history = false; - params.gesture = NavigationGestureUser; - params.is_post = false; - - NavigationController::LoadCommittedDetails details; - EXPECT_TRUE(controller().RendererDidNavigate(params, 0, &details)); - EXPECT_TRUE(notifications.Check1AndReset( - NotificationType::NAV_ENTRY_COMMITTED)); - EXPECT_EQ(url1, details.previous_url); - EXPECT_FALSE(details.is_auto); - EXPECT_FALSE(details.is_in_page); - EXPECT_FALSE(details.is_main_frame); - - // The new entry should be appended. - EXPECT_EQ(2, controller().entry_count()); - - // New entry should refer to the new page, but the old URL (entries only - // reflect the toplevel URL). - EXPECT_EQ(url1, details.entry->url()); - EXPECT_EQ(params.page_id, details.entry->page_id()); -} - -// Some pages create a popup, then write an iframe into it. This causes a -// subframe navigation without having any committed entry. Such navigations -// just get thrown on the ground, but we shouldn't crash. -TEST_F(NavigationControllerTest, SubframeOnEmptyPage) { - TestNotificationTracker notifications; - RegisterForAllNavNotifications(¬ifications, &controller()); - - // Navigation controller currently has no entries. - const GURL url("http://foo2"); - ViewHostMsg_FrameNavigate_Params params; - params.page_id = 1; - params.url = url; - params.transition = PageTransition::AUTO_SUBFRAME; - params.should_update_history = false; - params.gesture = NavigationGestureAuto; - params.is_post = false; - - NavigationController::LoadCommittedDetails details; - EXPECT_FALSE(controller().RendererDidNavigate(params, 0, &details)); - EXPECT_EQ(0U, notifications.size()); -} - -// Auto subframes are ones the page loads automatically like ads. They should -// not create new navigation entries. -TEST_F(NavigationControllerTest, AutoSubframe) { - TestNotificationTracker notifications; - RegisterForAllNavNotifications(¬ifications, &controller()); - - const GURL url1("http://foo1"); - rvh()->SendNavigate(0, url1); - EXPECT_TRUE(notifications.Check1AndReset( - NotificationType::NAV_ENTRY_COMMITTED)); - - const GURL url2("http://foo2"); - ViewHostMsg_FrameNavigate_Params params; - params.page_id = 0; - params.url = url2; - params.transition = PageTransition::AUTO_SUBFRAME; - params.should_update_history = false; - params.gesture = NavigationGestureUser; - params.is_post = false; - - // Navigating should do nothing. - NavigationController::LoadCommittedDetails details; - EXPECT_FALSE(controller().RendererDidNavigate(params, 0, &details)); - EXPECT_EQ(0U, notifications.size()); - - // There should still be only one entry. - EXPECT_EQ(1, controller().entry_count()); -} - -// Tests navigation and then going back to a subframe navigation. -TEST_F(NavigationControllerTest, BackSubframe) { - TestNotificationTracker notifications; - RegisterForAllNavNotifications(¬ifications, &controller()); - - // Main page. - const GURL url1("http://foo1"); - rvh()->SendNavigate(0, url1); - EXPECT_TRUE(notifications.Check1AndReset( - NotificationType::NAV_ENTRY_COMMITTED)); - - // First manual subframe navigation. - const GURL url2("http://foo2"); - ViewHostMsg_FrameNavigate_Params params; - params.page_id = 1; - params.url = url2; - params.transition = PageTransition::MANUAL_SUBFRAME; - params.should_update_history = false; - params.gesture = NavigationGestureUser; - params.is_post = false; - - // This should generate a new entry. - NavigationController::LoadCommittedDetails details; - EXPECT_TRUE(controller().RendererDidNavigate(params, 0, &details)); - EXPECT_TRUE(notifications.Check1AndReset( - NotificationType::NAV_ENTRY_COMMITTED)); - EXPECT_EQ(2, controller().entry_count()); - - // Second manual subframe navigation should also make a new entry. - const GURL url3("http://foo3"); - params.page_id = 2; - params.url = url3; - EXPECT_TRUE(controller().RendererDidNavigate(params, 0, &details)); - EXPECT_TRUE(notifications.Check1AndReset( - NotificationType::NAV_ENTRY_COMMITTED)); - EXPECT_EQ(3, controller().entry_count()); - EXPECT_EQ(2, controller().GetCurrentEntryIndex()); - - // Go back one. - controller().GoBack(); - params.url = url2; - params.page_id = 1; - EXPECT_TRUE(controller().RendererDidNavigate(params, 0, &details)); - EXPECT_TRUE(notifications.Check1AndReset( - NotificationType::NAV_ENTRY_COMMITTED)); - EXPECT_EQ(3, controller().entry_count()); - EXPECT_EQ(1, controller().GetCurrentEntryIndex()); - - // Go back one more. - controller().GoBack(); - params.url = url1; - params.page_id = 0; - EXPECT_TRUE(controller().RendererDidNavigate(params, 0, &details)); - EXPECT_TRUE(notifications.Check1AndReset( - NotificationType::NAV_ENTRY_COMMITTED)); - EXPECT_EQ(3, controller().entry_count()); - EXPECT_EQ(0, controller().GetCurrentEntryIndex()); -} - -TEST_F(NavigationControllerTest, LinkClick) { - TestNotificationTracker notifications; - RegisterForAllNavNotifications(¬ifications, &controller()); - - const GURL url1("http://foo1"); - const GURL url2("http://foo2"); - - rvh()->SendNavigate(0, url1); - EXPECT_TRUE(notifications.Check1AndReset( - NotificationType::NAV_ENTRY_COMMITTED)); - - rvh()->SendNavigate(1, url2); - EXPECT_TRUE(notifications.Check1AndReset( - NotificationType::NAV_ENTRY_COMMITTED)); - - // Should not have produced a new session history entry. - EXPECT_EQ(controller().entry_count(), 2); - EXPECT_EQ(controller().last_committed_entry_index(), 1); - EXPECT_EQ(controller().pending_entry_index(), -1); - EXPECT_TRUE(controller().GetLastCommittedEntry()); - EXPECT_FALSE(controller().pending_entry()); - EXPECT_TRUE(controller().CanGoBack()); - EXPECT_FALSE(controller().CanGoForward()); -} - -TEST_F(NavigationControllerTest, InPage) { - TestNotificationTracker notifications; - RegisterForAllNavNotifications(¬ifications, &controller()); - - // Main page. - const GURL url1("http://foo"); - rvh()->SendNavigate(0, url1); - EXPECT_TRUE(notifications.Check1AndReset( - NotificationType::NAV_ENTRY_COMMITTED)); - - // First navigation. - const GURL url2("http://foo#a"); - ViewHostMsg_FrameNavigate_Params params; - params.page_id = 1; - params.url = url2; - params.transition = PageTransition::LINK; - params.should_update_history = false; - params.gesture = NavigationGestureUser; - params.is_post = false; - - // This should generate a new entry. - NavigationController::LoadCommittedDetails details; - EXPECT_TRUE(controller().RendererDidNavigate(params, 0, &details)); - EXPECT_TRUE(notifications.Check1AndReset( - NotificationType::NAV_ENTRY_COMMITTED)); - EXPECT_TRUE(details.is_in_page); - EXPECT_FALSE(details.did_replace_entry); - EXPECT_EQ(2, controller().entry_count()); - - // Go back one. - ViewHostMsg_FrameNavigate_Params back_params(params); - controller().GoBack(); - back_params.url = url1; - back_params.page_id = 0; - EXPECT_TRUE(controller().RendererDidNavigate(back_params, 0, &details)); - EXPECT_TRUE(notifications.Check1AndReset( - NotificationType::NAV_ENTRY_COMMITTED)); - // is_in_page is false in that case but should be true. - // See comment in AreURLsInPageNavigation() in navigation_controller.cc - // EXPECT_TRUE(details.is_in_page); - EXPECT_EQ(2, controller().entry_count()); - EXPECT_EQ(0, controller().GetCurrentEntryIndex()); - EXPECT_EQ(back_params.url, controller().GetActiveEntry()->url()); - - // Go forward - ViewHostMsg_FrameNavigate_Params forward_params(params); - controller().GoForward(); - forward_params.url = url2; - forward_params.page_id = 1; - EXPECT_TRUE(controller().RendererDidNavigate(forward_params, 0, &details)); - EXPECT_TRUE(notifications.Check1AndReset( - NotificationType::NAV_ENTRY_COMMITTED)); - EXPECT_TRUE(details.is_in_page); - EXPECT_EQ(2, controller().entry_count()); - EXPECT_EQ(1, controller().GetCurrentEntryIndex()); - EXPECT_EQ(forward_params.url, - controller().GetActiveEntry()->url()); - - // Now go back and forward again. This is to work around a bug where we would - // compare the incoming URL with the last committed entry rather than the - // one identified by an existing page ID. This would result in the second URL - // losing the reference fragment when you navigate away from it and then back. - controller().GoBack(); - EXPECT_TRUE(controller().RendererDidNavigate(back_params, 0, &details)); - controller().GoForward(); - EXPECT_TRUE(controller().RendererDidNavigate(forward_params, 0, &details)); - EXPECT_EQ(forward_params.url, - controller().GetActiveEntry()->url()); - - // Finally, navigate to an unrelated URL to make sure in_page is not sticky. - const GURL url3("http://bar"); - params.page_id = 2; - params.url = url3; - notifications.Reset(); - EXPECT_TRUE(controller().RendererDidNavigate(params, 0, &details)); - EXPECT_TRUE(notifications.Check1AndReset( - NotificationType::NAV_ENTRY_COMMITTED)); - EXPECT_FALSE(details.is_in_page); -} - -TEST_F(NavigationControllerTest, InPage_Replace) { - TestNotificationTracker notifications; - RegisterForAllNavNotifications(¬ifications, &controller()); - - // Main page. - const GURL url1("http://foo"); - rvh()->SendNavigate(0, url1); - EXPECT_TRUE(notifications.Check1AndReset( - NotificationType::NAV_ENTRY_COMMITTED)); - - // First navigation. - const GURL url2("http://foo#a"); - ViewHostMsg_FrameNavigate_Params params; - params.page_id = 0; // Same page_id - params.url = url2; - params.transition = PageTransition::LINK; - params.should_update_history = false; - params.gesture = NavigationGestureUser; - params.is_post = false; - - // This should NOT generate a new entry. - NavigationController::LoadCommittedDetails details; - EXPECT_TRUE(controller().RendererDidNavigate(params, 0, &details)); - EXPECT_TRUE(notifications.Check2AndReset( - NotificationType::NAV_LIST_PRUNED, - NotificationType::NAV_ENTRY_COMMITTED)); - EXPECT_TRUE(details.is_in_page); - EXPECT_TRUE(details.did_replace_entry); - EXPECT_EQ(1, controller().entry_count()); -} - -// Tests for http://crbug.com/40395 -// Simulates this: -// <script> -// window.location.replace("#a"); -// window.location='http://foo3/'; -// </script> -TEST_F(NavigationControllerTest, ClientRedirectAfterInPageNavigation) { - TestNotificationTracker notifications; - RegisterForAllNavNotifications(¬ifications, &controller()); - - // Load an initial page. - { - const GURL url("http://foo/"); - rvh()->SendNavigate(0, url); - EXPECT_TRUE(notifications.Check1AndReset( - NotificationType::NAV_ENTRY_COMMITTED)); - } - - // Navigate to a new page. - { - const GURL url("http://foo2/"); - rvh()->SendNavigate(1, url); - controller().DocumentLoadedInFrame(); - EXPECT_TRUE(notifications.Check1AndReset( - NotificationType::NAV_ENTRY_COMMITTED)); - } - - // Navigate within the page. - { - const GURL url("http://foo2/#a"); - ViewHostMsg_FrameNavigate_Params params; - params.page_id = 1; // Same page_id - params.url = url; - params.transition = PageTransition::LINK; - params.redirects.push_back(url); - params.should_update_history = true; - params.gesture = NavigationGestureUnknown; - params.is_post = false; - - // This should NOT generate a new entry. - NavigationController::LoadCommittedDetails details; - EXPECT_TRUE(controller().RendererDidNavigate(params, 0, &details)); - EXPECT_TRUE(notifications.Check2AndReset( - NotificationType::NAV_LIST_PRUNED, - NotificationType::NAV_ENTRY_COMMITTED)); - EXPECT_TRUE(details.is_in_page); - EXPECT_TRUE(details.did_replace_entry); - EXPECT_EQ(2, controller().entry_count()); - } - - // Perform a client redirect to a new page. - { - const GURL url("http://foo3/"); - ViewHostMsg_FrameNavigate_Params params; - params.page_id = 2; // New page_id - params.url = url; - params.transition = PageTransition::CLIENT_REDIRECT; - params.redirects.push_back(GURL("http://foo2/#a")); - params.redirects.push_back(url); - params.should_update_history = true; - params.gesture = NavigationGestureUnknown; - params.is_post = false; - - // This SHOULD generate a new entry. - NavigationController::LoadCommittedDetails details; - EXPECT_TRUE(controller().RendererDidNavigate(params, 0, &details)); - EXPECT_TRUE(notifications.Check1AndReset( - NotificationType::NAV_ENTRY_COMMITTED)); - EXPECT_FALSE(details.is_in_page); - EXPECT_EQ(3, controller().entry_count()); - } - - // Verify that BACK brings us back to http://foo2/. - { - const GURL url("http://foo2/"); - controller().GoBack(); - rvh()->SendNavigate(1, url); - EXPECT_TRUE(notifications.Check1AndReset( - NotificationType::NAV_ENTRY_COMMITTED)); - EXPECT_EQ(url, controller().GetActiveEntry()->url()); - } -} - -// NotificationObserver implementation used in verifying we've received the -// NotificationType::NAV_LIST_PRUNED method. -class PrunedListener : public NotificationObserver { - public: - explicit PrunedListener(NavigationController* controller) - : notification_count_(0) { - registrar_.Add(this, NotificationType::NAV_LIST_PRUNED, - Source<NavigationController>(controller)); - } - - virtual void Observe(NotificationType type, - const NotificationSource& source, - const NotificationDetails& details) { - if (type == NotificationType::NAV_LIST_PRUNED) { - notification_count_++; - details_ = *(Details<NavigationController::PrunedDetails>(details).ptr()); - } - } - - // Number of times NAV_LIST_PRUNED has been observed. - int notification_count_; - - // Details from the last NAV_LIST_PRUNED. - NavigationController::PrunedDetails details_; - - private: - NotificationRegistrar registrar_; - - DISALLOW_COPY_AND_ASSIGN(PrunedListener); -}; - -// Tests that we limit the number of navigation entries created correctly. -TEST_F(NavigationControllerTest, EnforceMaxNavigationCount) { - size_t original_count = NavigationController::max_entry_count(); - const int kMaxEntryCount = 5; - - NavigationController::set_max_entry_count(kMaxEntryCount); - - int url_index; - // Load up to the max count, all entries should be there. - for (url_index = 0; url_index < kMaxEntryCount; url_index++) { - GURL url(StringPrintf("http://www.a.com/%d", url_index)); - controller().LoadURL(url, GURL(), PageTransition::TYPED); - rvh()->SendNavigate(url_index, url); - } - - EXPECT_EQ(controller().entry_count(), kMaxEntryCount); - - // Created a PrunedListener to observe prune notifications. - PrunedListener listener(&controller()); - - // Navigate some more. - GURL url(StringPrintf("http://www.a.com/%d", url_index)); - controller().LoadURL(url, GURL(), PageTransition::TYPED); - rvh()->SendNavigate(url_index, url); - url_index++; - - // We should have got a pruned navigation. - EXPECT_EQ(1, listener.notification_count_); - EXPECT_TRUE(listener.details_.from_front); - EXPECT_EQ(1, listener.details_.count); - - // We expect http://www.a.com/0 to be gone. - EXPECT_EQ(controller().entry_count(), kMaxEntryCount); - EXPECT_EQ(controller().GetEntryAtIndex(0)->url(), - GURL("http:////www.a.com/1")); - - // More navigations. - for (int i = 0; i < 3; i++) { - url = GURL(StringPrintf("http:////www.a.com/%d", url_index)); - controller().LoadURL(url, GURL(), PageTransition::TYPED); - rvh()->SendNavigate(url_index, url); - url_index++; - } - EXPECT_EQ(controller().entry_count(), kMaxEntryCount); - EXPECT_EQ(controller().GetEntryAtIndex(0)->url(), - GURL("http:////www.a.com/4")); - - NavigationController::set_max_entry_count(original_count); -} - -// Tests that we can do a restore and navigate to the restored entries and -// everything is updated properly. This can be tricky since there is no -// SiteInstance for the entries created initially. -TEST_F(NavigationControllerTest, RestoreNavigate) { - // Create a NavigationController with a restored set of tabs. - GURL url("http://foo"); - std::vector<TabNavigation> navigations; - navigations.push_back(TabNavigation(0, url, GURL(), - ASCIIToUTF16("Title"), "state", - PageTransition::LINK)); - TabContents our_contents(profile(), NULL, MSG_ROUTING_NONE, NULL, NULL); - NavigationController& our_controller = our_contents.controller(); - our_controller.RestoreFromState(navigations, 0, true); - our_controller.GoToIndex(0); - - // We should now have one entry, and it should be "pending". - EXPECT_EQ(1, our_controller.entry_count()); - EXPECT_EQ(our_controller.GetEntryAtIndex(0), - our_controller.pending_entry()); - EXPECT_EQ(0, our_controller.GetEntryAtIndex(0)->page_id()); - EXPECT_EQ(NavigationEntry::RESTORE_LAST_SESSION, - our_controller.GetEntryAtIndex(0)->restore_type()); - - // Say we navigated to that entry. - ViewHostMsg_FrameNavigate_Params params; - params.page_id = 0; - params.url = url; - params.transition = PageTransition::LINK; - params.should_update_history = false; - params.gesture = NavigationGestureUser; - params.is_post = false; - NavigationController::LoadCommittedDetails details; - our_controller.RendererDidNavigate(params, 0, &details); - - // There should be no longer any pending entry and one committed one. This - // means that we were able to locate the entry, assign its site instance, and - // commit it properly. - EXPECT_EQ(1, our_controller.entry_count()); - EXPECT_EQ(0, our_controller.last_committed_entry_index()); - EXPECT_FALSE(our_controller.pending_entry()); - EXPECT_EQ(url, - our_controller.GetLastCommittedEntry()->site_instance()->site()); - EXPECT_EQ(NavigationEntry::RESTORE_NONE, - our_controller.GetEntryAtIndex(0)->restore_type()); -} - -// Make sure that the page type and stuff is correct after an interstitial. -TEST_F(NavigationControllerTest, Interstitial) { - // First navigate somewhere normal. - const GURL url1("http://foo"); - controller().LoadURL(url1, GURL(), PageTransition::TYPED); - rvh()->SendNavigate(0, url1); - - // Now navigate somewhere with an interstitial. - const GURL url2("http://bar"); - controller().LoadURL(url1, GURL(), PageTransition::TYPED); - controller().pending_entry()->set_page_type(INTERSTITIAL_PAGE); - - // At this point the interstitial will be displayed and the load will still - // be pending. If the user continues, the load will commit. - rvh()->SendNavigate(1, url2); - - // The page should be a normal page again. - EXPECT_EQ(url2, controller().GetLastCommittedEntry()->url()); - EXPECT_EQ(NORMAL_PAGE, controller().GetLastCommittedEntry()->page_type()); -} - -TEST_F(NavigationControllerTest, RemoveEntry) { - const GURL url1("http://foo1"); - const GURL url2("http://foo2"); - const GURL url3("http://foo3"); - const GURL url4("http://foo4"); - const GURL url5("http://foo5"); - const GURL pending_url("http://pending"); - const GURL default_url("http://default"); - - controller().LoadURL(url1, GURL(), PageTransition::TYPED); - rvh()->SendNavigate(0, url1); - controller().LoadURL(url2, GURL(), PageTransition::TYPED); - rvh()->SendNavigate(1, url2); - controller().LoadURL(url3, GURL(), PageTransition::TYPED); - rvh()->SendNavigate(2, url3); - controller().LoadURL(url4, GURL(), PageTransition::TYPED); - rvh()->SendNavigate(3, url4); - controller().LoadURL(url5, GURL(), PageTransition::TYPED); - rvh()->SendNavigate(4, url5); - - // Remove the last entry. - controller().RemoveEntryAtIndex( - controller().entry_count() - 1, default_url); - EXPECT_EQ(4, controller().entry_count()); - EXPECT_EQ(3, controller().last_committed_entry_index()); - NavigationEntry* pending_entry = controller().pending_entry(); - EXPECT_TRUE(pending_entry && pending_entry->url() == url4); - - // Add a pending entry. - controller().LoadURL(pending_url, GURL(), PageTransition::TYPED); - // Now remove the last entry. - controller().RemoveEntryAtIndex( - controller().entry_count() - 1, default_url); - // The pending entry should have been discarded and the last committed entry - // removed. - EXPECT_EQ(3, controller().entry_count()); - EXPECT_EQ(2, controller().last_committed_entry_index()); - pending_entry = controller().pending_entry(); - EXPECT_TRUE(pending_entry && pending_entry->url() == url3); - - // Remove an entry which is not the last committed one. - controller().RemoveEntryAtIndex(0, default_url); - EXPECT_EQ(2, controller().entry_count()); - EXPECT_EQ(1, controller().last_committed_entry_index()); - // No navigation should have been initiated since we did not remove the - // current entry. - EXPECT_FALSE(controller().pending_entry()); - - // Remove the 2 remaining entries. - controller().RemoveEntryAtIndex(1, default_url); - controller().RemoveEntryAtIndex(0, default_url); - - // This should have created a pending default entry. - EXPECT_EQ(0, controller().entry_count()); - EXPECT_EQ(-1, controller().last_committed_entry_index()); - pending_entry = controller().pending_entry(); - EXPECT_TRUE(pending_entry && pending_entry->url() == default_url); -} - -// Tests the transient entry, making sure it goes away with all navigations. -TEST_F(NavigationControllerTest, TransientEntry) { - TestNotificationTracker notifications; - RegisterForAllNavNotifications(¬ifications, &controller()); - - const GURL url0("http://foo0"); - const GURL url1("http://foo1"); - const GURL url2("http://foo2"); - const GURL url3("http://foo3"); - const GURL url4("http://foo4"); - const GURL transient_url("http://transient"); - - controller().LoadURL(url0, GURL(), PageTransition::TYPED); - rvh()->SendNavigate(0, url0); - controller().LoadURL(url1, GURL(), PageTransition::TYPED); - rvh()->SendNavigate(1, url1); - - notifications.Reset(); - - // Adding a transient with no pending entry. - NavigationEntry* transient_entry = new NavigationEntry; - transient_entry->set_url(transient_url); - controller().AddTransientEntry(transient_entry); - - // We should not have received any notifications. - EXPECT_EQ(0U, notifications.size()); - - // Check our state. - EXPECT_EQ(transient_url, controller().GetActiveEntry()->url()); - EXPECT_EQ(controller().entry_count(), 3); - EXPECT_EQ(controller().last_committed_entry_index(), 1); - EXPECT_EQ(controller().pending_entry_index(), -1); - EXPECT_TRUE(controller().GetLastCommittedEntry()); - EXPECT_FALSE(controller().pending_entry()); - EXPECT_TRUE(controller().CanGoBack()); - EXPECT_FALSE(controller().CanGoForward()); - EXPECT_EQ(contents()->GetMaxPageID(), 1); - - // Navigate. - controller().LoadURL(url2, GURL(), PageTransition::TYPED); - rvh()->SendNavigate(2, url2); - - // We should have navigated, transient entry should be gone. - EXPECT_EQ(url2, controller().GetActiveEntry()->url()); - EXPECT_EQ(controller().entry_count(), 3); - - // Add a transient again, then navigate with no pending entry this time. - transient_entry = new NavigationEntry; - transient_entry->set_url(transient_url); - controller().AddTransientEntry(transient_entry); - EXPECT_EQ(transient_url, controller().GetActiveEntry()->url()); - rvh()->SendNavigate(3, url3); - // Transient entry should be gone. - EXPECT_EQ(url3, controller().GetActiveEntry()->url()); - EXPECT_EQ(controller().entry_count(), 4); - - // Initiate a navigation, add a transient then commit navigation. - controller().LoadURL(url4, GURL(), PageTransition::TYPED); - transient_entry = new NavigationEntry; - transient_entry->set_url(transient_url); - controller().AddTransientEntry(transient_entry); - EXPECT_EQ(transient_url, controller().GetActiveEntry()->url()); - rvh()->SendNavigate(4, url4); - EXPECT_EQ(url4, controller().GetActiveEntry()->url()); - EXPECT_EQ(controller().entry_count(), 5); - - // Add a transient and go back. This should simply remove the transient. - transient_entry = new NavigationEntry; - transient_entry->set_url(transient_url); - controller().AddTransientEntry(transient_entry); - EXPECT_EQ(transient_url, controller().GetActiveEntry()->url()); - EXPECT_TRUE(controller().CanGoBack()); - EXPECT_FALSE(controller().CanGoForward()); - controller().GoBack(); - // Transient entry should be gone. - EXPECT_EQ(url4, controller().GetActiveEntry()->url()); - EXPECT_EQ(controller().entry_count(), 5); - rvh()->SendNavigate(3, url3); - - // Add a transient and go to an entry before the current one. - transient_entry = new NavigationEntry; - transient_entry->set_url(transient_url); - controller().AddTransientEntry(transient_entry); - EXPECT_EQ(transient_url, controller().GetActiveEntry()->url()); - controller().GoToIndex(1); - // The navigation should have been initiated, transient entry should be gone. - EXPECT_EQ(url1, controller().GetActiveEntry()->url()); - rvh()->SendNavigate(1, url1); - - // Add a transient and go to an entry after the current one. - transient_entry = new NavigationEntry; - transient_entry->set_url(transient_url); - controller().AddTransientEntry(transient_entry); - EXPECT_EQ(transient_url, controller().GetActiveEntry()->url()); - controller().GoToIndex(3); - // The navigation should have been initiated, transient entry should be gone. - // Because of the transient entry that is removed, going to index 3 makes us - // land on url2. - EXPECT_EQ(url2, controller().GetActiveEntry()->url()); - rvh()->SendNavigate(2, url2); - - // Add a transient and go forward. - transient_entry = new NavigationEntry; - transient_entry->set_url(transient_url); - controller().AddTransientEntry(transient_entry); - EXPECT_EQ(transient_url, controller().GetActiveEntry()->url()); - EXPECT_TRUE(controller().CanGoForward()); - controller().GoForward(); - // We should have navigated, transient entry should be gone. - EXPECT_EQ(url3, controller().GetActiveEntry()->url()); - rvh()->SendNavigate(3, url3); - - // Ensure the URLS are correct. - EXPECT_EQ(controller().entry_count(), 5); - EXPECT_EQ(controller().GetEntryAtIndex(0)->url(), url0); - EXPECT_EQ(controller().GetEntryAtIndex(1)->url(), url1); - EXPECT_EQ(controller().GetEntryAtIndex(2)->url(), url2); - EXPECT_EQ(controller().GetEntryAtIndex(3)->url(), url3); - EXPECT_EQ(controller().GetEntryAtIndex(4)->url(), url4); -} - -// Tests that IsInPageNavigation returns appropriate results. Prevents -// regression for bug 1126349. -TEST_F(NavigationControllerTest, IsInPageNavigation) { - // Navigate to URL with no refs. - const GURL url("http://www.google.com/home.html"); - rvh()->SendNavigate(0, url); - - // Reloading the page is not an in-page navigation. - EXPECT_FALSE(controller().IsURLInPageNavigation(url)); - const GURL other_url("http://www.google.com/add.html"); - EXPECT_FALSE(controller().IsURLInPageNavigation(other_url)); - const GURL url_with_ref("http://www.google.com/home.html#my_ref"); - EXPECT_TRUE(controller().IsURLInPageNavigation(url_with_ref)); - - // Navigate to URL with refs. - rvh()->SendNavigate(1, url_with_ref); - - // Reloading the page is not an in-page navigation. - EXPECT_FALSE(controller().IsURLInPageNavigation(url_with_ref)); - EXPECT_FALSE(controller().IsURLInPageNavigation(url)); - EXPECT_FALSE(controller().IsURLInPageNavigation(other_url)); - const GURL other_url_with_ref("http://www.google.com/home.html#my_other_ref"); - EXPECT_TRUE(controller().IsURLInPageNavigation( - other_url_with_ref)); -} - -// Some pages can have subframes with the same base URL (minus the reference) as -// the main page. Even though this is hard, it can happen, and we don't want -// these subframe navigations to affect the toplevel document. They should -// instead be ignored. http://crbug.com/5585 -TEST_F(NavigationControllerTest, SameSubframe) { - // Navigate the main frame. - const GURL url("http://www.google.com/"); - rvh()->SendNavigate(0, url); - - // We should be at the first navigation entry. - EXPECT_EQ(controller().entry_count(), 1); - EXPECT_EQ(controller().last_committed_entry_index(), 0); - - // Navigate a subframe that would normally count as in-page. - const GURL subframe("http://www.google.com/#"); - ViewHostMsg_FrameNavigate_Params params; - params.page_id = 0; - params.url = subframe; - params.transition = PageTransition::AUTO_SUBFRAME; - params.should_update_history = false; - params.gesture = NavigationGestureAuto; - params.is_post = false; - NavigationController::LoadCommittedDetails details; - EXPECT_FALSE(controller().RendererDidNavigate(params, 0, &details)); - - // Nothing should have changed. - EXPECT_EQ(controller().entry_count(), 1); - EXPECT_EQ(controller().last_committed_entry_index(), 0); -} - -// Test view source redirection is reflected in title bar. -TEST_F(NavigationControllerTest, ViewSourceRedirect) { - const char kUrl[] = "view-source:http://redirect.to/google.com"; - const char kResult[] = "http://google.com"; - const char kExpected[] = "view-source:google.com"; - const GURL url(kUrl); - const GURL result_url(kResult); - - controller().LoadURL(url, GURL(), PageTransition::TYPED); - - ViewHostMsg_FrameNavigate_Params params; - params.page_id = 0; - params.url = result_url; - params.transition = PageTransition::SERVER_REDIRECT; - params.should_update_history = false; - params.gesture = NavigationGestureAuto; - params.is_post = false; - NavigationController::LoadCommittedDetails details; - controller().RendererDidNavigate(params, 0, &details); - - EXPECT_EQ(ASCIIToUTF16(kExpected), contents()->GetTitle()); - EXPECT_TRUE(contents()->ShouldDisplayURL()); -} - -// Make sure that on cloning a tabcontents and going back needs_reload is false. -TEST_F(NavigationControllerTest, CloneAndGoBack) { - const GURL url1("http://foo1"); - const GURL url2("http://foo2"); - - NavigateAndCommit(url1); - NavigateAndCommit(url2); - - scoped_ptr<TabContents> clone(controller().tab_contents()->Clone()); - - ASSERT_EQ(2, clone->controller().entry_count()); - EXPECT_TRUE(clone->controller().needs_reload()); - clone->controller().GoBack(); - // Navigating back should have triggered needs_reload_ to go false. - EXPECT_FALSE(clone->controller().needs_reload()); -} - -// Make sure that cloning a tabcontents doesn't copy interstitials. -TEST_F(NavigationControllerTest, CloneOmitsInterstitials) { - const GURL url1("http://foo1"); - const GURL url2("http://foo2"); - - NavigateAndCommit(url1); - NavigateAndCommit(url2); - - // Add an interstitial entry. Should be deleted with controller. - NavigationEntry* interstitial_entry = new NavigationEntry(); - interstitial_entry->set_page_type(INTERSTITIAL_PAGE); - controller().AddTransientEntry(interstitial_entry); - - scoped_ptr<TabContents> clone(controller().tab_contents()->Clone()); - - ASSERT_EQ(2, clone->controller().entry_count()); -} - -// Tests a subframe navigation while a toplevel navigation is pending. -// http://crbug.com/43967 -TEST_F(NavigationControllerTest, SubframeWhilePending) { - // Load the first page. - const GURL url1("http://foo/"); - NavigateAndCommit(url1); - - // Now start a pending load to a totally different page, but don't commit it. - const GURL url2("http://bar/"); - controller().LoadURL(url2, GURL(), PageTransition::TYPED); - - // Send a subframe update from the first page, as if one had just - // automatically loaded. Auto subframes don't increment the page ID. - const GURL url1_sub("http://foo/subframe"); - ViewHostMsg_FrameNavigate_Params params; - params.page_id = controller().GetLastCommittedEntry()->page_id(); - params.url = url1_sub; - params.transition = PageTransition::AUTO_SUBFRAME; - params.should_update_history = false; - params.gesture = NavigationGestureAuto; - params.is_post = false; - NavigationController::LoadCommittedDetails details; - - // This should return false meaning that nothing was actually updated. - EXPECT_FALSE(controller().RendererDidNavigate(params, 0, &details)); - - // The notification should have updated the last committed one, and not - // the pending load. - EXPECT_EQ(url1, controller().GetLastCommittedEntry()->url()); - - // The active entry should be unchanged by the subframe load. - EXPECT_EQ(url2, controller().GetActiveEntry()->url()); -} - -// Tests CopyStateFromAndPrune with 2 urls in source, 1 in dest. -TEST_F(NavigationControllerTest, CopyStateFromAndPrune) { - SessionID id(controller().session_id()); - const GURL url1("http://foo1"); - const GURL url2("http://foo2"); - const GURL url3("http://foo3"); - - NavigateAndCommit(url1); - NavigateAndCommit(url2); - - scoped_ptr<TestTabContents> other_contents(CreateTestTabContents()); - NavigationController& other_controller = other_contents->controller(); - SessionID other_id(other_controller.session_id()); - other_contents->NavigateAndCommit(url3); - other_controller.CopyStateFromAndPrune(&controller()); - - // other_controller should now contain the 3 urls: url1, url2 and url3. - - ASSERT_EQ(3, other_controller.entry_count()); - - ASSERT_EQ(2, other_controller.GetCurrentEntryIndex()); - - EXPECT_EQ(url1, other_controller.GetEntryAtIndex(0)->url()); - EXPECT_EQ(url2, other_controller.GetEntryAtIndex(1)->url()); - EXPECT_EQ(url3, other_controller.GetEntryAtIndex(2)->url()); - - // Make sure session ids didn't change. - EXPECT_EQ(id.id(), controller().session_id().id()); - EXPECT_EQ(other_id.id(), other_controller.session_id().id()); -} - -// Test CopyStateFromAndPrune with 2 urls, the first selected and nothing in -// the target. -TEST_F(NavigationControllerTest, CopyStateFromAndPrune2) { - SessionID id(controller().session_id()); - const GURL url1("http://foo1"); - const GURL url2("http://foo2"); - const GURL url3("http://foo3"); - - NavigateAndCommit(url1); - NavigateAndCommit(url2); - controller().GoBack(); - - scoped_ptr<TestTabContents> other_contents(CreateTestTabContents()); - NavigationController& other_controller = other_contents->controller(); - SessionID other_id(other_controller.session_id()); - other_controller.CopyStateFromAndPrune(&controller()); - - // other_controller should now contain the 1 url: url1. - - ASSERT_EQ(1, other_controller.entry_count()); - - ASSERT_EQ(0, other_controller.GetCurrentEntryIndex()); - - EXPECT_EQ(url1, other_controller.GetEntryAtIndex(0)->url()); - - // Make sure session ids didn't change. - EXPECT_EQ(id.id(), controller().session_id().id()); - EXPECT_EQ(other_id.id(), other_controller.session_id().id()); -} - -// Test CopyStateFromAndPrune with 2 urls, the first selected and nothing in -// the target. -TEST_F(NavigationControllerTest, CopyStateFromAndPrune3) { - SessionID id(controller().session_id()); - const GURL url1("http://foo1"); - const GURL url2("http://foo2"); - const GURL url3("http://foo3"); - - NavigateAndCommit(url1); - NavigateAndCommit(url2); - controller().GoBack(); - - scoped_ptr<TestTabContents> other_contents(CreateTestTabContents()); - NavigationController& other_controller = other_contents->controller(); - SessionID other_id(other_controller.session_id()); - other_controller.LoadURL(url3, GURL(), PageTransition::TYPED); - other_controller.CopyStateFromAndPrune(&controller()); - - // other_controller should now contain 1 entry for url1, and a pending entry - // for url3. - - ASSERT_EQ(1, other_controller.entry_count()); - - EXPECT_EQ(0, other_controller.GetCurrentEntryIndex()); - - EXPECT_EQ(url1, other_controller.GetEntryAtIndex(0)->url()); - - // And there should be a pending entry for url3. - ASSERT_TRUE(other_controller.pending_entry()); - - EXPECT_EQ(url3, other_controller.pending_entry()->url()); - - // Make sure session ids didn't change. - EXPECT_EQ(id.id(), controller().session_id().id()); - EXPECT_EQ(other_id.id(), other_controller.session_id().id()); -} - -// Tests that navigations initiated from the page (with the history object) -// work as expected without navigation entries. -TEST_F(NavigationControllerTest, HistoryNavigate) { - const GURL url1("http://foo1"); - const GURL url2("http://foo2"); - const GURL url3("http://foo3"); - - NavigateAndCommit(url1); - NavigateAndCommit(url2); - NavigateAndCommit(url3); - controller().GoBack(); - contents()->CommitPendingNavigation(); - - // Simulate the page calling history.back(), it should not create a pending - // entry. - contents()->OnGoToEntryAtOffset(-1); - EXPECT_EQ(-1, controller().pending_entry_index()); - // The actual cross-navigation is suspended until the current RVH tells us - // it unloaded, simulate that. - contents()->ProceedWithCrossSiteNavigation(); - // Also make sure we told the page to navigate. - const IPC::Message* message = - process()->sink().GetFirstMessageMatching(ViewMsg_Navigate::ID); - ASSERT_TRUE(message != NULL); - Tuple1<ViewMsg_Navigate_Params> nav_params; - ViewMsg_Navigate::Read(message, &nav_params); - EXPECT_EQ(url1, nav_params.a.url); - process()->sink().ClearMessages(); - - // Now test history.forward() - contents()->OnGoToEntryAtOffset(1); - EXPECT_EQ(-1, controller().pending_entry_index()); - // The actual cross-navigation is suspended until the current RVH tells us - // it unloaded, simulate that. - contents()->ProceedWithCrossSiteNavigation(); - message = process()->sink().GetFirstMessageMatching(ViewMsg_Navigate::ID); - ASSERT_TRUE(message != NULL); - ViewMsg_Navigate::Read(message, &nav_params); - EXPECT_EQ(url3, nav_params.a.url); - process()->sink().ClearMessages(); - - // Make sure an extravagant history.go() doesn't break. - contents()->OnGoToEntryAtOffset(120); // Out of bounds. - EXPECT_EQ(-1, controller().pending_entry_index()); - message = process()->sink().GetFirstMessageMatching(ViewMsg_Navigate::ID); - EXPECT_TRUE(message == NULL); -} - -// Test call to PruneAllButActive for the only entry. -TEST_F(NavigationControllerTest, PruneAllButActiveForSingle) { - const GURL url1("http://foo1"); - NavigateAndCommit(url1); - controller().PruneAllButActive(); - - EXPECT_EQ(-1, controller().pending_entry_index()); - EXPECT_EQ(controller().GetEntryAtIndex(0)->url(), url1); -} - -// Test call to PruneAllButActive for last entry. -TEST_F(NavigationControllerTest, PruneAllButActiveForLast) { - const GURL url1("http://foo1"); - const GURL url2("http://foo2"); - const GURL url3("http://foo3"); - - NavigateAndCommit(url1); - NavigateAndCommit(url2); - NavigateAndCommit(url3); - controller().GoBack(); - controller().GoBack(); - contents()->CommitPendingNavigation(); - - controller().PruneAllButActive(); - - EXPECT_EQ(-1, controller().pending_entry_index()); - EXPECT_EQ(controller().GetEntryAtIndex(0)->url(), url1); -} - -// Test call to PruneAllButActive for intermediate entry. -TEST_F(NavigationControllerTest, PruneAllButActiveForIntermediate) { - const GURL url1("http://foo1"); - const GURL url2("http://foo2"); - const GURL url3("http://foo3"); - - NavigateAndCommit(url1); - NavigateAndCommit(url2); - NavigateAndCommit(url3); - controller().GoBack(); - contents()->CommitPendingNavigation(); - - controller().PruneAllButActive(); - - EXPECT_EQ(-1, controller().pending_entry_index()); - EXPECT_EQ(controller().GetEntryAtIndex(0)->url(), url2); -} - -// Test call to PruneAllButActive for intermediate entry. -TEST_F(NavigationControllerTest, PruneAllButActiveForPending) { - const GURL url1("http://foo1"); - const GURL url2("http://foo2"); - const GURL url3("http://foo3"); - - NavigateAndCommit(url1); - NavigateAndCommit(url2); - NavigateAndCommit(url3); - controller().GoBack(); - - controller().PruneAllButActive(); - - EXPECT_EQ(0, controller().pending_entry_index()); -} - -// Test call to PruneAllButActive for transient entry. -TEST_F(NavigationControllerTest, PruneAllButActiveForTransient) { - const GURL url0("http://foo0"); - const GURL url1("http://foo1"); - const GURL transient_url("http://transient"); - - controller().LoadURL(url0, GURL(), PageTransition::TYPED); - rvh()->SendNavigate(0, url0); - controller().LoadURL(url1, GURL(), PageTransition::TYPED); - rvh()->SendNavigate(1, url1); - - // Adding a transient with no pending entry. - NavigationEntry* transient_entry = new NavigationEntry; - transient_entry->set_url(transient_url); - controller().AddTransientEntry(transient_entry); - - controller().PruneAllButActive(); - - EXPECT_EQ(-1, controller().pending_entry_index()); - EXPECT_EQ(-1, controller().pending_entry_index()); - EXPECT_EQ(controller().GetTransientEntry()->url(), transient_url); -} - -/* TODO(brettw) These test pass on my local machine but fail on the XP buildbot - (but not Vista) cleaning up the directory after they run. - This should be fixed. - -// A basic test case. Navigates to a single url, and make sure the history -// db matches. -TEST_F(NavigationControllerHistoryTest, Basic) { - controller().LoadURL(url0, GURL(), PageTransition::LINK); - rvh()->SendNavigate(0, url0); - - GetLastSession(); - - session_helper_.AssertSingleWindowWithSingleTab(windows_, 1); - session_helper_.AssertTabEquals(0, 0, 1, *(windows_[0]->tabs[0])); - TabNavigation nav1(0, url0, GURL(), string16(), - webkit_glue::CreateHistoryStateForURL(url0), - PageTransition::LINK); - session_helper_.AssertNavigationEquals(nav1, - windows_[0]->tabs[0]->navigations[0]); -} - -// Navigates to three urls, then goes back and make sure the history database -// is in sync. -TEST_F(NavigationControllerHistoryTest, NavigationThenBack) { - rvh()->SendNavigate(0, url0); - rvh()->SendNavigate(1, url1); - rvh()->SendNavigate(2, url2); - - controller().GoBack(); - rvh()->SendNavigate(1, url1); - - GetLastSession(); - - session_helper_.AssertSingleWindowWithSingleTab(windows_, 3); - session_helper_.AssertTabEquals(0, 1, 3, *(windows_[0]->tabs[0])); - - TabNavigation nav(0, url0, GURL(), string16(), - webkit_glue::CreateHistoryStateForURL(url0), - PageTransition::LINK); - session_helper_.AssertNavigationEquals(nav, - windows_[0]->tabs[0]->navigations[0]); - nav.set_url(url1); - session_helper_.AssertNavigationEquals(nav, - windows_[0]->tabs[0]->navigations[1]); - nav.set_url(url2); - session_helper_.AssertNavigationEquals(nav, - windows_[0]->tabs[0]->navigations[2]); -} - -// Navigates to three urls, then goes back twice, then loads a new url. -TEST_F(NavigationControllerHistoryTest, NavigationPruning) { - rvh()->SendNavigate(0, url0); - rvh()->SendNavigate(1, url1); - rvh()->SendNavigate(2, url2); - - controller().GoBack(); - rvh()->SendNavigate(1, url1); - - controller().GoBack(); - rvh()->SendNavigate(0, url0); - - rvh()->SendNavigate(3, url2); - - // Now have url0, and url2. - - GetLastSession(); - - session_helper_.AssertSingleWindowWithSingleTab(windows_, 2); - session_helper_.AssertTabEquals(0, 1, 2, *(windows_[0]->tabs[0])); - - TabNavigation nav(0, url0, GURL(), string16(), - webkit_glue::CreateHistoryStateForURL(url0), - PageTransition::LINK); - session_helper_.AssertNavigationEquals(nav, - windows_[0]->tabs[0]->navigations[0]); - nav.set_url(url2); - session_helper_.AssertNavigationEquals(nav, - windows_[0]->tabs[0]->navigations[1]); -} -*/ diff --git a/chrome/browser/tab_contents/navigation_entry.cc b/chrome/browser/tab_contents/navigation_entry.cc deleted file mode 100644 index 25af057..0000000 --- a/chrome/browser/tab_contents/navigation_entry.cc +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/tab_contents/navigation_entry.h" - -#include "base/string_util.h" -#include "base/utf_string_conversions.h" -#include "chrome/browser/profiles/profile.h" -#include "chrome/browser/renderer_host/site_instance.h" -#include "chrome/browser/tab_contents/navigation_controller.h" -#include "chrome/common/chrome_constants.h" -#include "chrome/common/url_constants.h" -#include "grit/app_resources.h" -#include "net/base/net_util.h" -#include "ui/base/resource/resource_bundle.h" -#include "ui/base/text/text_elider.h" - -// Use this to get a new unique ID for a NavigationEntry during construction. -// The returned ID is guaranteed to be nonzero (which is the "no ID" indicator). -static int GetUniqueID() { - static int unique_id_counter = 0; - return ++unique_id_counter; -} - -NavigationEntry::SSLStatus::SSLStatus() - : security_style_(SECURITY_STYLE_UNKNOWN), - cert_id_(0), - cert_status_(0), - security_bits_(-1), - connection_status_(0), - content_status_(NORMAL_CONTENT) { -} - -NavigationEntry::FaviconStatus::FaviconStatus() : valid_(false) { - ResourceBundle &rb = ResourceBundle::GetSharedInstance(); - bitmap_ = *rb.GetBitmapNamed(IDR_DEFAULT_FAVICON); -} - - -NavigationEntry::NavigationEntry() - : unique_id_(GetUniqueID()), - site_instance_(NULL), - page_type_(NORMAL_PAGE), - update_virtual_url_with_url_(false), - page_id_(-1), - transition_type_(PageTransition::LINK), - has_post_data_(false), - restore_type_(RESTORE_NONE) { -} - -NavigationEntry::NavigationEntry(SiteInstance* instance, - int page_id, - const GURL& url, - const GURL& referrer, - const string16& title, - PageTransition::Type transition_type) - : unique_id_(GetUniqueID()), - site_instance_(instance), - page_type_(NORMAL_PAGE), - url_(url), - referrer_(referrer), - update_virtual_url_with_url_(false), - title_(title), - page_id_(page_id), - transition_type_(transition_type), - has_post_data_(false), - restore_type_(RESTORE_NONE) { -} - -NavigationEntry::~NavigationEntry() { -} - -void NavigationEntry::set_site_instance(SiteInstance* site_instance) { - site_instance_ = site_instance; -} - -const string16& NavigationEntry::GetTitleForDisplay( - const std::string& languages) { - // Most pages have real titles. Don't even bother caching anything if this is - // the case. - if (!title_.empty()) - return title_; - - // More complicated cases will use the URLs as the title. This result we will - // cache since it's more complicated to compute. - if (!cached_display_title_.empty()) - return cached_display_title_; - - // Use the virtual URL first if any, and fall back on using the real URL. - string16 title; - std::wstring elided_title; - if (!virtual_url_.is_empty()) { - title = net::FormatUrl(virtual_url_, languages); - } else if (!url_.is_empty()) { - title = net::FormatUrl(url_, languages); - } - ui::ElideString(UTF16ToWideHack(title), chrome::kMaxTitleChars, - &elided_title); - cached_display_title_ = WideToUTF16Hack(elided_title); - return cached_display_title_; -} - -bool NavigationEntry::IsViewSourceMode() const { - return virtual_url_.SchemeIs(chrome::kViewSourceScheme); -} diff --git a/chrome/browser/tab_contents/navigation_entry.h b/chrome/browser/tab_contents/navigation_entry.h index 57d93c4..a9f0cc0 100644 --- a/chrome/browser/tab_contents/navigation_entry.h +++ b/chrome/browser/tab_contents/navigation_entry.h @@ -6,424 +6,7 @@ #define CHROME_BROWSER_TAB_CONTENTS_NAVIGATION_ENTRY_H_ #pragma once -#include <string> - -#include "base/basictypes.h" -#include "base/ref_counted.h" -#include "chrome/common/page_type.h" -#include "chrome/common/page_transition_types.h" -#include "chrome/common/security_style.h" -#include "googleurl/src/gurl.h" -#include "third_party/skia/include/core/SkBitmap.h" - -class SiteInstance; - -//////////////////////////////////////////////////////////////////////////////// -// -// NavigationEntry class -// -// A NavigationEntry is a data structure that captures all the information -// required to recreate a browsing state. This includes some opaque binary -// state as provided by the TabContents as well as some clear text title and -// URL which is used for our user interface. -// -//////////////////////////////////////////////////////////////////////////////// -class NavigationEntry { - public: - // SSL ----------------------------------------------------------------------- - - // Collects the SSL information for this NavigationEntry. - class SSLStatus { - public: - // Flags used for the page security content status. - enum ContentStatusFlags { - // HTTP page, or HTTPS page with no insecure content. - NORMAL_CONTENT = 0, - - // HTTPS page containing "displayed" HTTP resources (e.g. images, CSS). - DISPLAYED_INSECURE_CONTENT = 1 << 0, - - // HTTPS page containing "executed" HTTP resources (i.e. script). - // Also currently used for HTTPS page containing broken-HTTPS resources; - // this is wrong and should be fixed (see comments in - // SSLPolicy::OnRequestStarted()). - RAN_INSECURE_CONTENT = 1 << 1, - }; - - SSLStatus(); - - bool Equals(const SSLStatus& status) const { - return security_style_ == status.security_style_ && - cert_id_ == status.cert_id_ && - cert_status_ == status.cert_status_ && - security_bits_ == status.security_bits_ && - content_status_ == status.content_status_; - } - - void set_security_style(SecurityStyle security_style) { - security_style_ = security_style; - } - SecurityStyle security_style() const { - return security_style_; - } - - void set_cert_id(int ssl_cert_id) { - cert_id_ = ssl_cert_id; - } - int cert_id() const { - return cert_id_; - } - - void set_cert_status(int ssl_cert_status) { - cert_status_ = ssl_cert_status; - } - int cert_status() const { - return cert_status_; - } - - void set_security_bits(int security_bits) { - security_bits_ = security_bits; - } - int security_bits() const { - return security_bits_; - } - - void set_displayed_insecure_content() { - content_status_ |= DISPLAYED_INSECURE_CONTENT; - } - bool displayed_insecure_content() const { - return (content_status_ & DISPLAYED_INSECURE_CONTENT) != 0; - } - - void set_ran_insecure_content() { - content_status_ |= RAN_INSECURE_CONTENT; - } - bool ran_insecure_content() const { - return (content_status_ & RAN_INSECURE_CONTENT) != 0; - } - - void set_connection_status(int connection_status) { - connection_status_ = connection_status; - } - int connection_status() const { - return connection_status_; - } - - // Raw accessors for all the content status flags. This contains a - // combination of any of the ContentStatusFlags defined above. It is used - // by some tests for checking and for certain copying. Use the per-status - // functions for normal usage. - void set_content_status(int content_status) { - content_status_ = content_status; - } - int content_status() const { - return content_status_; - } - - private: - // See the accessors above for descriptions. - SecurityStyle security_style_; - int cert_id_; - int cert_status_; - int security_bits_; - int connection_status_; - int content_status_; - - // Copy and assignment is explicitly allowed for this class. - }; - - // Favicon ------------------------------------------------------------------- - - // Collects the favicon related information for a NavigationEntry. - class FaviconStatus { - public: - FaviconStatus(); - - // Indicates whether we've gotten an official favicon for the page, or are - // just using the default favicon. - void set_is_valid(bool is_valid) { - valid_ = is_valid; - } - bool is_valid() const { - return valid_; - } - - // The URL of the favicon which was used to load it off the web. - void set_url(const GURL& favicon_url) { - url_ = favicon_url; - } - const GURL& url() const { - return url_; - } - - // The favicon bitmap for the page. If the favicon has not been explicitly - // set or it empty, it will return the default favicon. Note that this is - // loaded asynchronously, so even if the favicon URL is valid we may return - // the default favicon if we haven't gotten the data yet. - void set_bitmap(const SkBitmap& bitmap) { - bitmap_ = bitmap; - } - const SkBitmap& bitmap() const { - return bitmap_; - } - - private: - // See the accessors above for descriptions. - bool valid_; - GURL url_; - SkBitmap bitmap_; - - // Copy and assignment is explicitly allowed for this class. - }; - - // --------------------------------------------------------------------------- - - NavigationEntry(); - NavigationEntry(SiteInstance* instance, - int page_id, - const GURL& url, - const GURL& referrer, - const string16& title, - PageTransition::Type transition_type); - ~NavigationEntry(); - - // Page-related stuff -------------------------------------------------------- - - // A unique ID is preserved across commits and redirects, which means that - // sometimes a NavigationEntry's unique ID needs to be set (e.g. when - // creating a committed entry to correspond to a to-be-deleted pending entry, - // the pending entry's ID must be copied). - void set_unique_id(int unique_id) { - unique_id_ = unique_id; - } - int unique_id() const { - return unique_id_; - } - - // The SiteInstance tells us how to share sub-processes when the tab type is - // TAB_CONTENTS_WEB. This will be NULL otherwise. This is a reference counted - // pointer to a shared site instance. - // - // Note that the SiteInstance should usually not be changed after it is set, - // but this may happen if the NavigationEntry was cloned and needs to use a - // different SiteInstance. - void set_site_instance(SiteInstance* site_instance); - SiteInstance* site_instance() const { - return site_instance_; - } - - // The page type tells us if this entry is for an interstitial or error page. - // See the PageType enum above. - void set_page_type(PageType page_type) { - page_type_ = page_type; - } - PageType page_type() const { - return page_type_; - } - - // The actual URL of the page. For some about pages, this may be a scary - // data: URL or something like that. Use virtual_url() below for showing to - // the user. - void set_url(const GURL& url) { - url_ = url; - cached_display_title_.clear(); - } - const GURL& url() const { - return url_; - } - - // The referring URL. Can be empty. - void set_referrer(const GURL& referrer) { - referrer_ = referrer; - } - const GURL& referrer() const { - return referrer_; - } - - // The virtual URL, when nonempty, will override the actual URL of the page - // when we display it to the user. This allows us to have nice and friendly - // URLs that the user sees for things like about: URLs, but actually feed - // the renderer a data URL that results in the content loading. - // - // virtual_url() will return the URL to display to the user in all cases, so - // if there is no overridden display URL, it will return the actual one. - void set_virtual_url(const GURL& url) { - virtual_url_ = (url == url_) ? GURL() : url; - cached_display_title_.clear(); - } - bool has_virtual_url() const { - return !virtual_url_.is_empty(); - } - const GURL& virtual_url() const { - return virtual_url_.is_empty() ? url_ : virtual_url_; - } - - bool update_virtual_url_with_url() const { - return update_virtual_url_with_url_; - } - void set_update_virtual_url_with_url(bool update) { - update_virtual_url_with_url_ = update; - } - - // The title as set by the page. This will be empty if there is no title set. - // The caller is responsible for detecting when there is no title and - // displaying the appropriate "Untitled" label if this is being displayed to - // the user. - void set_title(const string16& title) { - title_ = title; - cached_display_title_.clear(); - } - const string16& title() const { - return title_; - } - - // The favicon data and tracking information. See FaviconStatus above. - const FaviconStatus& favicon() const { - return favicon_; - } - FaviconStatus& favicon() { - return favicon_; - } - - // Content state is an opaque blob created by WebKit that represents the - // state of the page. This includes form entries and scroll position for each - // frame. We store it so that we can supply it back to WebKit to restore form - // state properly when the user goes back and forward. - // - // WARNING: This state is saved to the file and used to restore previous - // states. If the format is modified in the future, we should still be able to - // deal with older versions. - void set_content_state(const std::string& state) { - content_state_ = state; - } - const std::string& content_state() const { - return content_state_; - } - - // Describes the current page that the tab represents. For web pages - // (TAB_CONTENTS_WEB) this is the ID that the renderer generated for the page - // and is how we can tell new versus renavigations. - void set_page_id(int page_id) { - page_id_ = page_id; - } - int32 page_id() const { - return page_id_; - } - - // All the SSL flags and state. See SSLStatus above. - const SSLStatus& ssl() const { - return ssl_; - } - SSLStatus& ssl() { - return ssl_; - } - - // Page-related helpers ------------------------------------------------------ - - // Returns the title to be displayed on the tab. This could be the title of - // the page if it is available or the URL. |languages| is the list of - // accpeted languages (e.g., prefs::kAcceptLanguages) or empty if proper - // URL formatting isn't needed (e.g., unit tests). - const string16& GetTitleForDisplay(const std::string& languages); - - // Returns true if the current tab is in view source mode. This will be false - // if there is no navigation. - bool IsViewSourceMode() const; - - // Tracking stuff ------------------------------------------------------------ - - // The transition type indicates what the user did to move to this page from - // the previous page. - void set_transition_type(PageTransition::Type transition_type) { - transition_type_ = transition_type; - } - PageTransition::Type transition_type() const { - return transition_type_; - } - - // The user typed URL was the URL that the user initiated the navigation - // with, regardless of any redirects. This is used to generate keywords, for - // example, based on "what the user thinks the site is called" rather than - // what it's actually called. For example, if the user types "foo.com", that - // may redirect somewhere arbitrary like "bar.com/foo", and we want to use - // the name that the user things of the site as having. - // - // This URL will be is_empty() if the URL was navigated to some other way. - // Callers should fall back on using the regular or display URL in this case. - void set_user_typed_url(const GURL& user_typed_url) { - user_typed_url_ = user_typed_url; - } - const GURL& user_typed_url() const { - return user_typed_url_; - } - - // Post data is form data that was posted to get to this page. The data will - // have to be reposted to reload the page properly. This flag indicates - // whether the page had post data. - // - // The actual post data is stored in the content_state and is extracted by - // WebKit to actually make the request. - void set_has_post_data(bool has_post_data) { - has_post_data_ = has_post_data; - } - bool has_post_data() const { - return has_post_data_; - } - - // Enumerations of the possible restore types. - enum RestoreType { - // The entry has been restored is from the last session. - RESTORE_LAST_SESSION, - - // The entry has been restored from the current session. This is used when - // the user issues 'reopen closed tab'. - RESTORE_CURRENT_SESSION, - - // The entry was not restored. - RESTORE_NONE - }; - - // The RestoreType for this entry. This is set if the entry was retored. This - // is set to RESTORE_NONE once the entry is loaded. - void set_restore_type(RestoreType type) { - restore_type_ = type; - } - RestoreType restore_type() const { - return restore_type_; - } - - private: - // WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING - // Session/Tab restore save portions of this class so that it can be recreated - // later. If you add a new field that needs to be persisted you'll have to - // update SessionService/TabRestoreService appropriately. - // WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING - - // See the accessors above for descriptions. - int unique_id_; - scoped_refptr<SiteInstance> site_instance_; - PageType page_type_; - GURL url_; - GURL referrer_; - GURL virtual_url_; - bool update_virtual_url_with_url_; - string16 title_; - FaviconStatus favicon_; - std::string content_state_; - int32 page_id_; - SSLStatus ssl_; - PageTransition::Type transition_type_; - GURL user_typed_url_; - bool has_post_data_; - RestoreType restore_type_; - - // This is a cached version of the result of GetTitleForDisplay. It prevents - // us from having to do URL formatting on the URL evey time the title is - // displayed. When the URL, virtual URL, or title is set, this should be - // cleared to force a refresh. - string16 cached_display_title_; - - // Copy and assignment is explicitly allowed for this class. -}; +// TODO(jam): remove this file when all files have been converted. +#include "content/browser/tab_contents/navigation_entry.h" #endif // CHROME_BROWSER_TAB_CONTENTS_NAVIGATION_ENTRY_H_ diff --git a/chrome/browser/tab_contents/navigation_entry_unittest.cc b/chrome/browser/tab_contents/navigation_entry_unittest.cc deleted file mode 100644 index 014817c..0000000 --- a/chrome/browser/tab_contents/navigation_entry_unittest.cc +++ /dev/null @@ -1,183 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/string16.h" -#include "base/string_util.h" -#include "base/utf_string_conversions.h" -#include "chrome/browser/renderer_host/site_instance.h" -#include "chrome/browser/tab_contents/navigation_entry.h" -#include "testing/gtest/include/gtest/gtest.h" - -class NavigationEntryTest : public testing::Test { - public: - NavigationEntryTest() : instance_(NULL) { - } - - virtual void SetUp() { - entry1_.reset(new NavigationEntry); - - instance_ = SiteInstance::CreateSiteInstance(NULL); - entry2_.reset(new NavigationEntry(instance_, 3, - GURL("test:url"), - GURL("from"), - ASCIIToUTF16("title"), - PageTransition::TYPED)); - } - - virtual void TearDown() { - } - - protected: - scoped_ptr<NavigationEntry> entry1_; - scoped_ptr<NavigationEntry> entry2_; - // SiteInstances are deleted when their NavigationEntries are gone. - SiteInstance* instance_; -}; - -// Test unique ID accessors -TEST_F(NavigationEntryTest, NavigationEntryUniqueIDs) { - // Two entries should have different IDs by default - EXPECT_NE(entry1_.get()->unique_id(), entry2_.get()->unique_id()); - - // Can set an entry to have the same ID as another - entry2_.get()->set_unique_id(entry1_.get()->unique_id()); - EXPECT_EQ(entry1_.get()->unique_id(), entry2_.get()->unique_id()); -} - -// Test URL accessors -TEST_F(NavigationEntryTest, NavigationEntryURLs) { - // Start with no virtual_url (even if a url is set) - EXPECT_FALSE(entry1_.get()->has_virtual_url()); - EXPECT_FALSE(entry2_.get()->has_virtual_url()); - - EXPECT_EQ(GURL(), entry1_.get()->url()); - EXPECT_EQ(GURL(), entry1_.get()->virtual_url()); - EXPECT_TRUE(entry1_.get()->GetTitleForDisplay("").empty()); - - // Setting URL affects virtual_url and GetTitleForDisplay - entry1_.get()->set_url(GURL("http://www.google.com")); - EXPECT_EQ(GURL("http://www.google.com"), entry1_.get()->url()); - EXPECT_EQ(GURL("http://www.google.com"), entry1_.get()->virtual_url()); - EXPECT_EQ(ASCIIToUTF16("www.google.com"), - entry1_.get()->GetTitleForDisplay("")); - - // Title affects GetTitleForDisplay - entry1_.get()->set_title(ASCIIToUTF16("Google")); - EXPECT_EQ(ASCIIToUTF16("Google"), entry1_.get()->GetTitleForDisplay("")); - - // Setting virtual_url doesn't affect URL - entry2_.get()->set_virtual_url(GURL("display:url")); - EXPECT_TRUE(entry2_.get()->has_virtual_url()); - EXPECT_EQ(GURL("test:url"), entry2_.get()->url()); - EXPECT_EQ(GURL("display:url"), entry2_.get()->virtual_url()); - - // Having a title set in constructor overrides virtual URL - EXPECT_EQ(ASCIIToUTF16("title"), entry2_.get()->GetTitleForDisplay("")); - - // User typed URL is independent of the others - EXPECT_EQ(GURL(), entry1_.get()->user_typed_url()); - EXPECT_EQ(GURL(), entry2_.get()->user_typed_url()); - entry2_.get()->set_user_typed_url(GURL("typedurl")); - EXPECT_EQ(GURL("typedurl"), entry2_.get()->user_typed_url()); -} - -// Test Favicon inner class -TEST_F(NavigationEntryTest, NavigationEntryFavicons) { - EXPECT_EQ(GURL(), entry1_.get()->favicon().url()); - entry1_.get()->favicon().set_url(GURL("icon")); - EXPECT_EQ(GURL("icon"), entry1_.get()->favicon().url()); - - // Validity not affected by setting URL - EXPECT_FALSE(entry1_.get()->favicon().is_valid()); - entry1_.get()->favicon().set_is_valid(true); - EXPECT_TRUE(entry1_.get()->favicon().is_valid()); -} - -// Test SSLStatus inner class -TEST_F(NavigationEntryTest, NavigationEntrySSLStatus) { - // Default (unknown) - EXPECT_EQ(SECURITY_STYLE_UNKNOWN, entry1_.get()->ssl().security_style()); - EXPECT_EQ(SECURITY_STYLE_UNKNOWN, entry2_.get()->ssl().security_style()); - EXPECT_EQ(0, entry1_.get()->ssl().cert_id()); - EXPECT_EQ(0, entry1_.get()->ssl().cert_status()); - EXPECT_EQ(-1, entry1_.get()->ssl().security_bits()); - EXPECT_FALSE(entry1_.get()->ssl().displayed_insecure_content()); - EXPECT_FALSE(entry1_.get()->ssl().ran_insecure_content()); - - // Change from the defaults - entry2_.get()->ssl().set_security_style(SECURITY_STYLE_AUTHENTICATED); - entry2_.get()->ssl().set_cert_id(4); - entry2_.get()->ssl().set_cert_status(1); - entry2_.get()->ssl().set_security_bits(0); - entry2_.get()->ssl().set_displayed_insecure_content(); - EXPECT_EQ(SECURITY_STYLE_AUTHENTICATED, - entry2_.get()->ssl().security_style()); - EXPECT_EQ(4, entry2_.get()->ssl().cert_id()); - EXPECT_EQ(1, entry2_.get()->ssl().cert_status()); - EXPECT_EQ(0, entry2_.get()->ssl().security_bits()); - EXPECT_TRUE(entry2_.get()->ssl().displayed_insecure_content()); - - entry2_.get()->ssl().set_security_style(SECURITY_STYLE_AUTHENTICATION_BROKEN); - entry2_.get()->ssl().set_ran_insecure_content(); - EXPECT_EQ(SECURITY_STYLE_AUTHENTICATION_BROKEN, - entry2_.get()->ssl().security_style()); - EXPECT_TRUE(entry2_.get()->ssl().ran_insecure_content()); -} - -// Test other basic accessors -TEST_F(NavigationEntryTest, NavigationEntryAccessors) { - // SiteInstance - EXPECT_TRUE(entry1_.get()->site_instance() == NULL); - EXPECT_EQ(instance_, entry2_.get()->site_instance()); - entry1_.get()->set_site_instance(instance_); - EXPECT_EQ(instance_, entry1_.get()->site_instance()); - - // Page type - EXPECT_EQ(NORMAL_PAGE, entry1_.get()->page_type()); - EXPECT_EQ(NORMAL_PAGE, entry2_.get()->page_type()); - entry2_.get()->set_page_type(INTERSTITIAL_PAGE); - EXPECT_EQ(INTERSTITIAL_PAGE, entry2_.get()->page_type()); - - // Referrer - EXPECT_EQ(GURL(), entry1_.get()->referrer()); - EXPECT_EQ(GURL("from"), entry2_.get()->referrer()); - entry2_.get()->set_referrer(GURL("from2")); - EXPECT_EQ(GURL("from2"), entry2_.get()->referrer()); - - // Title - EXPECT_EQ(string16(), entry1_.get()->title()); - EXPECT_EQ(ASCIIToUTF16("title"), entry2_.get()->title()); - entry2_.get()->set_title(ASCIIToUTF16("title2")); - EXPECT_EQ(ASCIIToUTF16("title2"), entry2_.get()->title()); - - // State - EXPECT_EQ(std::string(), entry1_.get()->content_state()); - EXPECT_EQ(std::string(), entry2_.get()->content_state()); - entry2_.get()->set_content_state("state"); - EXPECT_EQ("state", entry2_.get()->content_state()); - - // Page ID - EXPECT_EQ(-1, entry1_.get()->page_id()); - EXPECT_EQ(3, entry2_.get()->page_id()); - entry2_.get()->set_page_id(2); - EXPECT_EQ(2, entry2_.get()->page_id()); - - // Transition type - EXPECT_EQ(PageTransition::LINK, entry1_.get()->transition_type()); - EXPECT_EQ(PageTransition::TYPED, entry2_.get()->transition_type()); - entry2_.get()->set_transition_type(PageTransition::RELOAD); - EXPECT_EQ(PageTransition::RELOAD, entry2_.get()->transition_type()); - - // Post Data - EXPECT_FALSE(entry1_.get()->has_post_data()); - EXPECT_FALSE(entry2_.get()->has_post_data()); - entry2_.get()->set_has_post_data(true); - EXPECT_TRUE(entry2_.get()->has_post_data()); - - // Restored - EXPECT_EQ(NavigationEntry::RESTORE_NONE, entry1_->restore_type()); - EXPECT_EQ(NavigationEntry::RESTORE_NONE, entry2_->restore_type()); - entry2_->set_restore_type(NavigationEntry::RESTORE_LAST_SESSION); - EXPECT_EQ(NavigationEntry::RESTORE_LAST_SESSION, entry2_->restore_type()); -} diff --git a/chrome/browser/tab_contents/page_navigator.h b/chrome/browser/tab_contents/page_navigator.h index 8773146..62c0333 100644 --- a/chrome/browser/tab_contents/page_navigator.h +++ b/chrome/browser/tab_contents/page_navigator.h @@ -2,29 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// PageNavigator defines an interface that can be used to express the user's -// intention to navigate to a particular URL. The implementing class should -// perform the navigation. - #ifndef CHROME_BROWSER_TAB_CONTENTS_PAGE_NAVIGATOR_H_ #define CHROME_BROWSER_TAB_CONTENTS_PAGE_NAVIGATOR_H_ #pragma once -#include "chrome/common/page_transition_types.h" -#include "webkit/glue/window_open_disposition.h" - -class GURL; - -class PageNavigator { - public: - // Opens a URL with the given disposition. The transition specifies how this - // navigation should be recorded in the history system (for example, typed). - virtual void OpenURL(const GURL& url, const GURL& referrer, - WindowOpenDisposition disposition, - PageTransition::Type transition) = 0; - - protected: - virtual ~PageNavigator() {} -}; +// TODO(jam): remove this file when all files have been converted. +#include "content/browser/tab_contents/page_navigator.h" #endif // CHROME_BROWSER_TAB_CONTENTS_PAGE_NAVIGATOR_H_ diff --git a/chrome/browser/tab_contents/provisional_load_details.cc b/chrome/browser/tab_contents/provisional_load_details.cc deleted file mode 100644 index 3cd59a7e..0000000 --- a/chrome/browser/tab_contents/provisional_load_details.cc +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - - -#include "chrome/browser/tab_contents/provisional_load_details.h" - -#include "chrome/browser/ssl/ssl_manager.h" - -ProvisionalLoadDetails::ProvisionalLoadDetails(bool is_main_frame, - bool is_in_page_navigation, - const GURL& url, - const std::string& security_info, - bool is_content_filtered, - bool is_error_page, - int64 frame_id) - : error_code_(net::OK), - transition_type_(PageTransition::LINK), - url_(url), - is_main_frame_(is_main_frame), - is_in_page_navigation_(is_in_page_navigation), - ssl_cert_id_(0), - ssl_cert_status_(0), - ssl_security_bits_(-1), - ssl_connection_status_(0), - is_content_filtered_(is_content_filtered), - is_error_page_(is_error_page), - frame_id_(frame_id) { - SSLManager::DeserializeSecurityInfo(security_info, - &ssl_cert_id_, - &ssl_cert_status_, - &ssl_security_bits_, - &ssl_connection_status_); -} diff --git a/chrome/browser/tab_contents/provisional_load_details.h b/chrome/browser/tab_contents/provisional_load_details.h index 732d52c..1ee04248 100644 --- a/chrome/browser/tab_contents/provisional_load_details.h +++ b/chrome/browser/tab_contents/provisional_load_details.h @@ -6,77 +6,7 @@ #define CHROME_BROWSER_TAB_CONTENTS_PROVISIONAL_LOAD_DETAILS_H_ #pragma once -#include <string> - -#include "base/basictypes.h" -#include "chrome/common/page_transition_types.h" -#include "googleurl/src/gurl.h" - -// This class captures some of the information associated to the provisional -// load of a frame. It is provided as Details with the -// NOTIFY_FRAME_PROVISIONAL_LOAD_START, NOTIFY_FRAME_PROVISIONAL_LOAD_COMMITTED -// and NOTIFY_FAIL_PROVISIONAL_LOAD_WITH_ERROR notifications -// (see notification_types.h). - -// TODO(brettw) this mostly duplicates -// NavigationController::LoadCommittedDetails, it would be nice to unify these -// somehow. -class ProvisionalLoadDetails { - public: - ProvisionalLoadDetails(bool main_frame, - bool in_page_navigation, - const GURL& url, - const std::string& security_info, - bool is_filtered, - bool is_error_page, - int64 frame_id); - virtual ~ProvisionalLoadDetails() { } - - void set_error_code(int error_code) { error_code_ = error_code; } - int error_code() const { return error_code_; } - - void set_transition_type(PageTransition::Type transition_type) { - transition_type_ = transition_type; - } - PageTransition::Type transition_type() const { - return transition_type_; - } - - const GURL& url() const { return url_; } - - bool main_frame() const { return is_main_frame_; } - - bool in_page_navigation() const { return is_in_page_navigation_; } - - int ssl_cert_id() const { return ssl_cert_id_; } - - int ssl_cert_status() const { return ssl_cert_status_; } - - int ssl_security_bits() const { return ssl_security_bits_; } - - int ssl_connection_status() const { return ssl_connection_status_; } - - bool is_content_filtered() const { return is_content_filtered_; } - - bool is_error_page() const { return is_error_page_; } - - int64 frame_id() const { return frame_id_; } - - private: - int error_code_; - PageTransition::Type transition_type_; - GURL url_; - bool is_main_frame_; - bool is_in_page_navigation_; - int ssl_cert_id_; - int ssl_cert_status_; - int ssl_security_bits_; - int ssl_connection_status_; - bool is_content_filtered_; - bool is_error_page_; - int64 frame_id_; - - DISALLOW_COPY_AND_ASSIGN(ProvisionalLoadDetails); -}; +// TODO(jam): remove this file when all files have been converted. +#include "content/browser/tab_contents/provisional_load_details.h" #endif // CHROME_BROWSER_TAB_CONTENTS_PROVISIONAL_LOAD_DETAILS_H_ diff --git a/chrome/browser/tab_contents/render_view_host_manager.cc b/chrome/browser/tab_contents/render_view_host_manager.cc deleted file mode 100644 index 55902d8..0000000 --- a/chrome/browser/tab_contents/render_view_host_manager.cc +++ /dev/null @@ -1,729 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/tab_contents/render_view_host_manager.h" - -#include "base/command_line.h" -#include "base/logging.h" -#include "chrome/browser/extensions/extension_service.h" -#include "chrome/browser/profiles/profile.h" -#include "chrome/browser/renderer_host/render_view_host.h" -#include "chrome/browser/renderer_host/render_view_host_delegate.h" -#include "chrome/browser/renderer_host/render_view_host_factory.h" -#include "chrome/browser/renderer_host/render_widget_host_view.h" -#include "chrome/browser/renderer_host/site_instance.h" -#include "chrome/browser/tab_contents/navigation_controller.h" -#include "chrome/browser/tab_contents/navigation_entry.h" -#include "chrome/browser/tab_contents/tab_contents_view.h" -#include "chrome/browser/webui/web_ui.h" -#include "chrome/browser/webui/web_ui_factory.h" -#include "chrome/common/chrome_switches.h" -#include "chrome/common/notification_service.h" -#include "chrome/common/notification_type.h" -#include "chrome/common/render_messages.h" -#include "chrome/common/render_messages_params.h" -#include "chrome/common/url_constants.h" - -namespace base { -class WaitableEvent; -} - -RenderViewHostManager::RenderViewHostManager( - RenderViewHostDelegate* render_view_delegate, - Delegate* delegate) - : delegate_(delegate), - cross_navigation_pending_(false), - render_view_delegate_(render_view_delegate), - render_view_host_(NULL), - pending_render_view_host_(NULL), - interstitial_page_(NULL) { -} - -RenderViewHostManager::~RenderViewHostManager() { - if (pending_render_view_host_) - CancelPending(); - - // We should always have a main RenderViewHost. - RenderViewHost* render_view_host = render_view_host_; - render_view_host_ = NULL; - render_view_host->Shutdown(); -} - -void RenderViewHostManager::Init(Profile* profile, - SiteInstance* site_instance, - int routing_id) { - // Create a RenderViewHost, once we have an instance. It is important to - // immediately give this SiteInstance to a RenderViewHost so that it is - // ref counted. - if (!site_instance) - site_instance = SiteInstance::CreateSiteInstance(profile); - render_view_host_ = RenderViewHostFactory::Create( - site_instance, render_view_delegate_, routing_id, delegate_-> - GetControllerForRenderManager().session_storage_namespace()); - NotificationService::current()->Notify( - NotificationType::RENDER_VIEW_HOST_CREATED_FOR_TAB, - Source<RenderViewHostManager>(this), - Details<RenderViewHost>(render_view_host_)); -} - -RenderWidgetHostView* RenderViewHostManager::GetRenderWidgetHostView() const { - if (!render_view_host_) - return NULL; - return render_view_host_->view(); -} - -RenderViewHost* RenderViewHostManager::Navigate(const NavigationEntry& entry) { - // Create a pending RenderViewHost. It will give us the one we should use - RenderViewHost* dest_render_view_host = UpdateRendererStateForNavigate(entry); - if (!dest_render_view_host) - return NULL; // We weren't able to create a pending render view host. - - // If the current render_view_host_ isn't live, we should create it so - // that we don't show a sad tab while the dest_render_view_host fetches - // its first page. (Bug 1145340) - if (dest_render_view_host != render_view_host_ && - !render_view_host_->IsRenderViewLive()) { - // Note: we don't call InitRenderView here because we are navigating away - // soon anyway, and we don't have the NavigationEntry for this host. - delegate_->CreateRenderViewForRenderManager(render_view_host_); - } - - // If the renderer crashed, then try to create a new one to satisfy this - // navigation request. - if (!dest_render_view_host->IsRenderViewLive()) { - if (!InitRenderView(dest_render_view_host, entry)) - return NULL; - - // Now that we've created a new renderer, be sure to hide it if it isn't - // our primary one. Otherwise, we might crash if we try to call Show() - // on it later. - if (dest_render_view_host != render_view_host_ && - dest_render_view_host->view()) { - dest_render_view_host->view()->Hide(); - } else { - // This is our primary renderer, notify here as we won't be calling - // CommitPending (which does the notify). - RenderViewHostSwitchedDetails details; - details.new_host = render_view_host_; - details.old_host = NULL; - NotificationService::current()->Notify( - NotificationType::RENDER_VIEW_HOST_CHANGED, - Source<NavigationController>( - &delegate_->GetControllerForRenderManager()), - Details<RenderViewHostSwitchedDetails>(&details)); - } - } - - return dest_render_view_host; -} - -void RenderViewHostManager::Stop() { - render_view_host_->Stop(); - - // If we are cross-navigating, we should stop the pending renderers. This - // will lead to a DidFailProvisionalLoad, which will properly destroy them. - if (cross_navigation_pending_) - pending_render_view_host_->Stop(); -} - -void RenderViewHostManager::SetIsLoading(bool is_loading) { - render_view_host_->SetIsLoading(is_loading); - if (pending_render_view_host_) - pending_render_view_host_->SetIsLoading(is_loading); -} - -bool RenderViewHostManager::ShouldCloseTabOnUnresponsiveRenderer() { - if (!cross_navigation_pending_) - return true; - - // If the tab becomes unresponsive during unload while doing a - // cross-site navigation, proceed with the navigation. (This assumes that - // the pending RenderViewHost is still responsive.) - int pending_request_id = pending_render_view_host_->GetPendingRequestId(); - if (pending_request_id == -1) { - // Haven't gotten around to starting the request, because we're still - // waiting for the beforeunload handler to finish. We'll pretend that it - // did finish, to let the navigation proceed. Note that there's a danger - // that the beforeunload handler will later finish and possibly return - // false (meaning the navigation should not proceed), but we'll ignore it - // in this case because it took too long. - if (pending_render_view_host_->are_navigations_suspended()) - pending_render_view_host_->SetNavigationsSuspended(false); - } else { - // The request has been started and paused, while we're waiting for the - // unload handler to finish. We'll pretend that it did, by notifying the - // IO thread to let the response continue. The pending renderer will then - // be swapped in as part of the usual DidNavigate logic. (If the unload - // handler later finishes, this call will be ignored because the state in - // CrossSiteResourceHandler will already be cleaned up.) - ViewMsg_ClosePage_Params params; - params.closing_process_id = - render_view_host_->process()->id(); - params.closing_route_id = render_view_host_->routing_id(); - params.for_cross_site_transition = true; - params.new_render_process_host_id = - pending_render_view_host_->process()->id(); - params.new_request_id = pending_request_id; - current_host()->process()->CrossSiteClosePageACK(params); - } - return false; -} - -void RenderViewHostManager::DidNavigateMainFrame( - RenderViewHost* render_view_host) { - if (!cross_navigation_pending_) { - DCHECK(!pending_render_view_host_); - - // We should only hear this from our current renderer. - DCHECK(render_view_host == render_view_host_); - - // Even when there is no pending RVH, there may be a pending Web UI. - if (pending_web_ui_.get()) - CommitPending(); - return; - } - - if (render_view_host == pending_render_view_host_) { - // The pending cross-site navigation completed, so show the renderer. - CommitPending(); - cross_navigation_pending_ = false; - } else if (render_view_host == render_view_host_) { - // A navigation in the original page has taken place. Cancel the pending - // one. - CancelPending(); - cross_navigation_pending_ = false; - } else { - // No one else should be sending us DidNavigate in this state. - DCHECK(false); - } -} - -void RenderViewHostManager::SetWebUIPostCommit(WebUI* web_ui) { - DCHECK(!web_ui_.get()); - web_ui_.reset(web_ui); -} - -void RenderViewHostManager::RendererAbortedProvisionalLoad( - RenderViewHost* render_view_host) { - // We used to cancel the pending renderer here for cross-site downloads. - // However, it's not safe to do that because the download logic repeatedly - // looks for this TabContents based on a render view ID. Instead, we just - // leave the pending renderer around until the next navigation event - // (Navigate, DidNavigate, etc), which will clean it up properly. - // TODO(creis): All of this will go away when we move the cross-site logic - // to ResourceDispatcherHost, so that we intercept responses rather than - // navigation events. (That's necessary to support onunload anyway.) Once - // we've made that change, we won't create a pending renderer until we know - // the response is not a download. -} - -void RenderViewHostManager::ShouldClosePage(bool for_cross_site_transition, - bool proceed) { - if (for_cross_site_transition) { - // Ignore if we're not in a cross-site navigation. - if (!cross_navigation_pending_) - return; - - if (proceed) { - // Ok to unload the current page, so proceed with the cross-site - // navigation. Note that if navigations are not currently suspended, it - // might be because the renderer was deemed unresponsive and this call was - // already made by ShouldCloseTabOnUnresponsiveRenderer. In that case, it - // is ok to do nothing here. - if (pending_render_view_host_ && - pending_render_view_host_->are_navigations_suspended()) - pending_render_view_host_->SetNavigationsSuspended(false); - } else { - // Current page says to cancel. - CancelPending(); - cross_navigation_pending_ = false; - } - } else { - // Non-cross site transition means closing the entire tab. - bool proceed_to_fire_unload; - delegate_->BeforeUnloadFiredFromRenderManager(proceed, - &proceed_to_fire_unload); - - if (proceed_to_fire_unload) { - // This is not a cross-site navigation, the tab is being closed. - render_view_host_->ClosePage(false, -1, -1); - } - } -} - -void RenderViewHostManager::OnCrossSiteResponse(int new_render_process_host_id, - int new_request_id) { - // Should only see this while we have a pending renderer. - if (!cross_navigation_pending_) - return; - DCHECK(pending_render_view_host_); - - // Tell the old renderer to run its onunload handler. When it finishes, it - // will send a ClosePage_ACK to the ResourceDispatcherHost with the given - // IDs (of the pending RVH's request), allowing the pending RVH's response to - // resume. - render_view_host_->ClosePage(true, - new_render_process_host_id, new_request_id); - - // ResourceDispatcherHost has told us to run the onunload handler, which - // means it is not a download or unsafe page, and we are going to perform the - // navigation. Thus, we no longer need to remember that the RenderViewHost - // is part of a pending cross-site request. - pending_render_view_host_->SetHasPendingCrossSiteRequest(false, - new_request_id); -} - -void RenderViewHostManager::OnCrossSiteNavigationCanceled() { - DCHECK(cross_navigation_pending_); - cross_navigation_pending_ = false; - if (pending_render_view_host_) - CancelPending(); -} - -bool RenderViewHostManager::ShouldTransitionCrossSite() { - // True if we are using process-per-site-instance (default) or - // process-per-site (kProcessPerSite). - return !CommandLine::ForCurrentProcess()->HasSwitch(switches::kProcessPerTab); -} - -bool RenderViewHostManager::ShouldSwapProcessesForNavigation( - const NavigationEntry* cur_entry, - const NavigationEntry* new_entry) const { - DCHECK(new_entry); - - // Check for reasons to swap processes even if we are in a process model that - // doesn't usually swap (e.g., process-per-tab). - - // For security, we should transition between processes when one is a Web UI - // page and one isn't. If there's no cur_entry, check the current RVH's - // site, which might already be committed to a Web UI URL (such as the NTP). - const GURL& current_url = (cur_entry) ? cur_entry->url() : - render_view_host_->site_instance()->site(); - Profile* profile = delegate_->GetControllerForRenderManager().profile(); - if (WebUIFactory::UseWebUIForURL(profile, current_url)) { - // Force swap if it's not an acceptable URL for Web UI. - if (!WebUIFactory::IsURLAcceptableForWebUI(profile, new_entry->url())) - return true; - } else { - // Force swap if it's a Web UI URL. - if (WebUIFactory::UseWebUIForURL(profile, new_entry->url())) - return true; - } - - if (!cur_entry) { - // Always choose a new process when navigating to extension URLs. The - // process grouping logic will combine all of a given extension's pages - // into the same process. - if (new_entry->url().SchemeIs(chrome::kExtensionScheme)) - return true; - - return false; - } - - // We can't switch a RenderView between view source and non-view source mode - // without screwing up the session history sometimes (when navigating between - // "view-source:http://foo.com/" and "http://foo.com/", WebKit doesn't treat - // it as a new navigation). So require a view switch. - if (cur_entry->IsViewSourceMode() != new_entry->IsViewSourceMode()) - return true; - - // Also, we must switch if one is an extension and the other is not the exact - // same extension. - if (cur_entry->url().SchemeIs(chrome::kExtensionScheme) || - new_entry->url().SchemeIs(chrome::kExtensionScheme)) { - if (cur_entry->url().GetOrigin() != new_entry->url().GetOrigin()) - return true; - } - - return false; -} - -SiteInstance* RenderViewHostManager::GetSiteInstanceForEntry( - const NavigationEntry& entry, - SiteInstance* curr_instance) { - // NOTE: This is only called when ShouldTransitionCrossSite is true. - - // If the entry has an instance already, we should use it. - if (entry.site_instance()) - return entry.site_instance(); - - // (UGLY) HEURISTIC, process-per-site only: - // - // If this navigation is generated, then it probably corresponds to a search - // query. Given that search results typically lead to users navigating to - // other sites, we don't really want to use the search engine hostname to - // determine the site instance for this navigation. - // - // NOTE: This can be removed once we have a way to transition between - // RenderViews in response to a link click. - // - if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kProcessPerSite) && - entry.transition_type() == PageTransition::GENERATED) - return curr_instance; - - const GURL& dest_url = entry.url(); - - // If we haven't used our SiteInstance (and thus RVH) yet, then we can use it - // for this entry. We won't commit the SiteInstance to this site until the - // navigation commits (in DidNavigate), unless the navigation entry was - // restored or it's a Web UI as described below. - if (!curr_instance->has_site()) { - // If we've already created a SiteInstance for our destination, we don't - // want to use this unused SiteInstance; use the existing one. (We don't - // do this check if the curr_instance has a site, because for now, we want - // to compare against the current URL and not the SiteInstance's site. In - // this case, there is no current URL, so comparing against the site is ok. - // See additional comments below.) - if (curr_instance->HasRelatedSiteInstance(dest_url)) { - return curr_instance->GetRelatedSiteInstance(dest_url); - } else { - // Normally the "site" on the SiteInstance is set lazily when the load - // actually commits. This is to support better process sharing in case - // the site redirects to some other site: we want to use the destination - // site in the site instance. - // - // In the case of session restore, as it loads all the pages immediately - // we need to set the site first, otherwise after a restore none of the - // pages would share renderers. - // - // For Web UI (this mostly comes up for the new tab page), the - // SiteInstance has special meaning: we never want to reassign the - // process. If you navigate to another site before the Web UI commits, - // we still want to create a new process rather than re-using the - // existing Web UI process. - if (entry.restore_type() != NavigationEntry::RESTORE_NONE || - WebUIFactory::HasWebUIScheme(dest_url)) - curr_instance->SetSite(dest_url); - return curr_instance; - } - } - - // Otherwise, only create a new SiteInstance for cross-site navigation. - - // TODO(creis): Once we intercept links and script-based navigations, we - // will be able to enforce that all entries in a SiteInstance actually have - // the same site, and it will be safe to compare the URL against the - // SiteInstance's site, as follows: - // const GURL& current_url = curr_instance->site(); - // For now, though, we're in a hybrid model where you only switch - // SiteInstances if you type in a cross-site URL. This means we have to - // compare the entry's URL to the last committed entry's URL. - NavigationController& controller = delegate_->GetControllerForRenderManager(); - NavigationEntry* curr_entry = controller.GetLastCommittedEntry(); - if (interstitial_page_) { - // The interstitial is currently the last committed entry, but we want to - // compare against the last non-interstitial entry. - curr_entry = controller.GetEntryAtOffset(-1); - } - // If there is no last non-interstitial entry (and curr_instance already - // has a site), then we must have been opened from another tab. We want - // to compare against the URL of the page that opened us, but we can't - // get to it directly. The best we can do is check against the site of - // the SiteInstance. This will be correct when we intercept links and - // script-based navigations, but for now, it could place some pages in a - // new process unnecessarily. We should only hit this case if a page tries - // to open a new tab to an interstitial-inducing URL, and then navigates - // the page to a different same-site URL. (This seems very unlikely in - // practice.) - const GURL& current_url = (curr_entry) ? curr_entry->url() : - curr_instance->site(); - Profile* profile = controller.profile(); - - if (SiteInstance::IsSameWebSite(profile, current_url, dest_url)) { - return curr_instance; - } else if (ShouldSwapProcessesForNavigation(curr_entry, &entry)) { - // When we're swapping, we need to force the site instance AND browsing - // instance to be different ones. This addresses special cases where we use - // a single BrowsingInstance for all pages of a certain type (e.g., New Tab - // Pages), keeping them in the same process. When you navigate away from - // that page, we want to explicity ignore that BrowsingInstance and group - // this page into the appropriate SiteInstance for its URL. - return SiteInstance::CreateSiteInstanceForURL(profile, dest_url); - } else { - // Start the new renderer in a new SiteInstance, but in the current - // BrowsingInstance. It is important to immediately give this new - // SiteInstance to a RenderViewHost (if it is different than our current - // SiteInstance), so that it is ref counted. This will happen in - // CreatePendingRenderView. - return curr_instance->GetRelatedSiteInstance(dest_url); - } -} - -bool RenderViewHostManager::CreatePendingRenderView( - const NavigationEntry& entry, SiteInstance* instance) { - NavigationEntry* curr_entry = - delegate_->GetControllerForRenderManager().GetLastCommittedEntry(); - if (curr_entry) { - DCHECK(!curr_entry->content_state().empty()); - // TODO(creis): Should send a message to the RenderView to let it know - // we're about to switch away, so that it sends an UpdateState message. - } - - pending_render_view_host_ = RenderViewHostFactory::Create( - instance, render_view_delegate_, MSG_ROUTING_NONE, delegate_-> - GetControllerForRenderManager().session_storage_namespace()); - NotificationService::current()->Notify( - NotificationType::RENDER_VIEW_HOST_CREATED_FOR_TAB, - Source<RenderViewHostManager>(this), - Details<RenderViewHost>(pending_render_view_host_)); - - bool success = InitRenderView(pending_render_view_host_, entry); - if (success) { - // Don't show the view until we get a DidNavigate from it. - pending_render_view_host_->view()->Hide(); - } else { - CancelPending(); - } - return success; -} - -bool RenderViewHostManager::InitRenderView(RenderViewHost* render_view_host, - const NavigationEntry& entry) { - // If the pending navigation is to a WebUI, tell the RenderView about any - // bindings it will need enabled. - if (pending_web_ui_.get()) - render_view_host->AllowBindings(pending_web_ui_->bindings()); - - // Tell the RenderView whether it will be used for an extension process. - Profile* profile = delegate_->GetControllerForRenderManager().profile(); - bool is_extension_process = profile->GetExtensionService() && - profile->GetExtensionService()->ExtensionBindingsAllowed(entry.url()); - render_view_host->set_is_extension_process(is_extension_process); - - return delegate_->CreateRenderViewForRenderManager(render_view_host); -} - -void RenderViewHostManager::CommitPending() { - // First check whether we're going to want to focus the location bar after - // this commit. We do this now because the navigation hasn't formally - // committed yet, so if we've already cleared |pending_web_ui_| the call chain - // this triggers won't be able to figure out what's going on. - bool will_focus_location_bar = delegate_->FocusLocationBarByDefault(); - - // Next commit the Web UI, if any. - web_ui_.swap(pending_web_ui_); - if (web_ui_.get() && pending_web_ui_.get() && !pending_render_view_host_) - web_ui_->DidBecomeActiveForReusedRenderView(); - pending_web_ui_.reset(); - - // It's possible for the pending_render_view_host_ to be NULL when we aren't - // crossing process boundaries. If so, we just needed to handle the Web UI - // committing above and we're done. - if (!pending_render_view_host_) { - if (will_focus_location_bar) - delegate_->SetFocusToLocationBar(false); - return; - } - - // Remember if the page was focused so we can focus the new renderer in - // that case. - bool focus_render_view = !will_focus_location_bar && - render_view_host_->view() && render_view_host_->view()->HasFocus(); - - // Hide the current view and prepare to destroy it. - // TODO(creis): Get the old RenderViewHost to send us an UpdateState message - // before we destroy it. - if (render_view_host_->view()) - render_view_host_->view()->Hide(); - RenderViewHost* old_render_view_host = render_view_host_; - - // Swap in the pending view and make it active. - render_view_host_ = pending_render_view_host_; - pending_render_view_host_ = NULL; - - // If the view is gone, then this RenderViewHost died while it was hidden. - // We ignored the RenderViewGone call at the time, so we should send it now - // to make sure the sad tab shows up, etc. - if (render_view_host_->view()) - render_view_host_->view()->Show(); - else - delegate_->RenderViewGoneFromRenderManager(render_view_host_); - - // Make sure the size is up to date. (Fix for bug 1079768.) - delegate_->UpdateRenderViewSizeForRenderManager(); - - if (will_focus_location_bar) - delegate_->SetFocusToLocationBar(false); - else if (focus_render_view && render_view_host_->view()) - render_view_host_->view()->Focus(); - - RenderViewHostSwitchedDetails details; - details.new_host = render_view_host_; - details.old_host = old_render_view_host; - NotificationService::current()->Notify( - NotificationType::RENDER_VIEW_HOST_CHANGED, - Source<NavigationController>(&delegate_->GetControllerForRenderManager()), - Details<RenderViewHostSwitchedDetails>(&details)); - - old_render_view_host->Shutdown(); - - // Let the task manager know that we've swapped RenderViewHosts, since it - // might need to update its process groupings. - delegate_->NotifySwappedFromRenderManager(); -} - -RenderViewHost* RenderViewHostManager::UpdateRendererStateForNavigate( - const NavigationEntry& entry) { - // If we are cross-navigating, then we want to get back to normal and navigate - // as usual. - if (cross_navigation_pending_) { - if (pending_render_view_host_) - CancelPending(); - cross_navigation_pending_ = false; - } - - // This will possibly create (set to NULL) a Web UI object for the pending - // page. We'll use this later to give the page special access. This must - // happen before the new renderer is created below so it will get bindings. - // It must also happen after the above conditional call to CancelPending(), - // otherwise CancelPending may clear the pending_web_ui_ and the page will - // not have it's bindings set appropriately. - pending_web_ui_.reset(delegate_->CreateWebUIForRenderManager(entry.url())); - - // render_view_host_ will not be deleted before the end of this method, so we - // don't have to worry about this SiteInstance's ref count dropping to zero. - SiteInstance* curr_instance = render_view_host_->site_instance(); - - // Determine if we need a new SiteInstance for this entry. - // Again, new_instance won't be deleted before the end of this method, so it - // is safe to use a normal pointer here. - SiteInstance* new_instance = curr_instance; - bool force_swap = ShouldSwapProcessesForNavigation( - delegate_->GetLastCommittedNavigationEntryForRenderManager(), - &entry); - if (ShouldTransitionCrossSite() || force_swap) - new_instance = GetSiteInstanceForEntry(entry, curr_instance); - - if (new_instance != curr_instance || force_swap) { - // New SiteInstance. - DCHECK(!cross_navigation_pending_); - - // Create a pending RVH and navigate it. - bool success = CreatePendingRenderView(entry, new_instance); - if (!success) - return NULL; - - // Check if our current RVH is live before we set up a transition. - if (!render_view_host_->IsRenderViewLive()) { - if (!cross_navigation_pending_) { - // The current RVH is not live. There's no reason to sit around with a - // sad tab or a newly created RVH while we wait for the pending RVH to - // navigate. Just switch to the pending RVH now and go back to non - // cross-navigating (Note that we don't care about on{before}unload - // handlers if the current RVH isn't live.) - CommitPending(); - return render_view_host_; - } else { - NOTREACHED(); - return render_view_host_; - } - } - // Otherwise, it's safe to treat this as a pending cross-site transition. - - // Make sure the old render view stops, in case a load is in progress. - render_view_host_->Stop(); - - // Suspend the new render view (i.e., don't let it send the cross-site - // Navigate message) until we hear back from the old renderer's - // onbeforeunload handler. If the handler returns false, we'll have to - // cancel the request. - DCHECK(!pending_render_view_host_->are_navigations_suspended()); - pending_render_view_host_->SetNavigationsSuspended(true); - - // Tell the CrossSiteRequestManager that this RVH has a pending cross-site - // request, so that ResourceDispatcherHost will know to tell us to run the - // old page's onunload handler before it sends the response. - pending_render_view_host_->SetHasPendingCrossSiteRequest(true, -1); - - // We now have a pending RVH. - DCHECK(!cross_navigation_pending_); - cross_navigation_pending_ = true; - - // Tell the old render view to run its onbeforeunload handler, since it - // doesn't otherwise know that the cross-site request is happening. This - // will trigger a call to ShouldClosePage with the reply. - render_view_host_->FirePageBeforeUnload(true); - - return pending_render_view_host_; - } else { - if (pending_web_ui_.get() && render_view_host_->IsRenderViewLive()) - pending_web_ui_->RenderViewReused(render_view_host_); - - // The renderer can exit view source mode when any error or cancellation - // happen. We must overwrite to recover the mode. - if (entry.IsViewSourceMode()) { - render_view_host_->Send( - new ViewMsg_EnableViewSourceMode(render_view_host_->routing_id())); - } - } - - // Same SiteInstance can be used. Navigate render_view_host_ if we are not - // cross navigating. - DCHECK(!cross_navigation_pending_); - return render_view_host_; -} - -void RenderViewHostManager::CancelPending() { - RenderViewHost* pending_render_view_host = pending_render_view_host_; - pending_render_view_host_ = NULL; - pending_render_view_host->Shutdown(); - - pending_web_ui_.reset(); -} - -void RenderViewHostManager::RenderViewDeleted(RenderViewHost* rvh) { - // We are doing this in order to work around and to track a crasher - // (http://crbug.com/23411) where it seems that pending_render_view_host_ is - // deleted (not sure from where) but not NULLed. - if (rvh == pending_render_view_host_) { - // If you hit this NOTREACHED, please report it in the following bug - // http://crbug.com/23411 Make sure to include what you were doing when it - // happened (navigating to a new page, closing a tab...) and if you can - // reproduce. - NOTREACHED(); - pending_render_view_host_ = NULL; - } -} - -void RenderViewHostManager::SwapInRenderViewHost(RenderViewHost* rvh) { - web_ui_.reset(); - - // Hide the current view and prepare to destroy it. - if (render_view_host_->view()) - render_view_host_->view()->Hide(); - RenderViewHost* old_render_view_host = render_view_host_; - - // Swap in the new view and make it active. - render_view_host_ = rvh; - render_view_host_->set_delegate(render_view_delegate_); - delegate_->CreateViewAndSetSizeForRVH(render_view_host_); - render_view_host_->ActivateDeferredPluginHandles(); - // If the view is gone, then this RenderViewHost died while it was hidden. - // We ignored the RenderViewGone call at the time, so we should send it now - // to make sure the sad tab shows up, etc. - if (render_view_host_->view()) { - // TODO(tburkard,cbentzel): Figure out why this hack is needed and/or - // if it can be removed. On Windows, prerendering will not work without - // doing a Hide before the Show. - render_view_host_->view()->Hide(); - render_view_host_->view()->Show(); - } - - delegate_->UpdateRenderViewSizeForRenderManager(); - - RenderViewHostSwitchedDetails details; - details.new_host = render_view_host_; - details.old_host = old_render_view_host; - NotificationService::current()->Notify( - NotificationType::RENDER_VIEW_HOST_CHANGED, - Source<NavigationController>(&delegate_->GetControllerForRenderManager()), - Details<RenderViewHostSwitchedDetails>(&details)); - - // This will cause the old RenderViewHost to delete itself. - old_render_view_host->Shutdown(); - - // Let the task manager know that we've swapped RenderViewHosts, since it - // might need to update its process groupings. - delegate_->NotifySwappedFromRenderManager(); -} diff --git a/chrome/browser/tab_contents/render_view_host_manager.h b/chrome/browser/tab_contents/render_view_host_manager.h index 23fb866..7f1be04 100644 --- a/chrome/browser/tab_contents/render_view_host_manager.h +++ b/chrome/browser/tab_contents/render_view_host_manager.h @@ -6,268 +6,7 @@ #define CHROME_BROWSER_TAB_CONTENTS_RENDER_VIEW_HOST_MANAGER_H_ #pragma once -#include "base/basictypes.h" -#include "base/logging.h" -#include "base/scoped_ptr.h" -#include "chrome/browser/renderer_host/render_view_host_delegate.h" -#include "chrome/common/notification_registrar.h" - -class WebUI; -class InterstitialPage; -class NavigationController; -class NavigationEntry; -class Profile; -class RenderWidgetHostView; -class RenderViewHost; -class SiteInstance; - -// Manages RenderViewHosts for a TabContents. Normally there is only one and -// it is easy to do. But we can also have transitions of processes (and hence -// RenderViewHosts) that can get complex. -class RenderViewHostManager - : public RenderViewHostDelegate::RendererManagement { - public: - // Functions implemented by our owner that we need. - // - // TODO(brettw) Clean this up! These are all the functions in TabContents that - // are required to run this class. The design should probably be better such - // that these are more clear. - // - // There is additional complexity that some of the functions we need in - // TabContents are inherited and non-virtual. These are named with - // "RenderManager" so that the duplicate implementation of them will be clear. - class Delegate { - public: - // See tab_contents.h's implementation for more. - virtual bool CreateRenderViewForRenderManager( - RenderViewHost* render_view_host) = 0; - virtual void BeforeUnloadFiredFromRenderManager( - bool proceed, bool* proceed_to_fire_unload) = 0; - virtual void DidStartLoadingFromRenderManager( - RenderViewHost* render_view_host) = 0; - virtual void RenderViewGoneFromRenderManager( - RenderViewHost* render_view_host) = 0; - virtual void UpdateRenderViewSizeForRenderManager() = 0; - virtual void NotifySwappedFromRenderManager() = 0; - virtual NavigationController& GetControllerForRenderManager() = 0; - - // Creates a WebUI object for the given URL if one applies. Ownership of the - // returned pointer will be passed to the caller. If no WebUI applies, - // returns NULL. - virtual WebUI* CreateWebUIForRenderManager(const GURL& url) = 0; - - // Returns the navigation entry of the current navigation, or NULL if there - // is none. - virtual NavigationEntry* - GetLastCommittedNavigationEntryForRenderManager() = 0; - - // Returns true if the location bar should be focused by default rather than - // the page contents. - virtual bool FocusLocationBarByDefault() = 0; - - // Focuses the location bar. - virtual void SetFocusToLocationBar(bool select_all) = 0; - - // Creates a view and sets the size for the specified RVH. - virtual void CreateViewAndSetSizeForRVH(RenderViewHost* rvh) = 0; - - protected: - virtual ~Delegate() {} - }; - - // Both delegate pointers must be non-NULL and are not owned by this class. - // They must outlive this class. The RenderViewHostDelegate is what will be - // installed into all RenderViewHosts that are created. - // - // You must call Init() before using this class. - RenderViewHostManager(RenderViewHostDelegate* render_view_delegate, - Delegate* delegate); - virtual ~RenderViewHostManager(); - - // For arguments, see TabContents constructor. - void Init(Profile* profile, - SiteInstance* site_instance, - int routing_id); - - // Returns the currently actuive RenderViewHost. - // - // This will be non-NULL between Init() and Shutdown(). You may want to NULL - // check it in many cases, however. Windows can send us messages during the - // destruction process after it has been shut down. - RenderViewHost* current_host() const { - return render_view_host_; - } - - // Returns the view associated with the current RenderViewHost, or NULL if - // there is no current one. - RenderWidgetHostView* GetRenderWidgetHostView() const; - - // Returns the pending render view host, or NULL if there is no pending one. - RenderViewHost* pending_render_view_host() const { - return pending_render_view_host_; - } - - // Returns the current committed Web UI or NULL if none applies. - WebUI* web_ui() const { return web_ui_.get(); } - - // Returns the Web UI for the pending navigation, or NULL of none applies. - WebUI* pending_web_ui() const { return pending_web_ui_.get(); } - - // Called when we want to instruct the renderer to navigate to the given - // navigation entry. It may create a new RenderViewHost or re-use an existing - // one. The RenderViewHost to navigate will be returned. Returns NULL if one - // could not be created. - RenderViewHost* Navigate(const NavigationEntry& entry); - - // Instructs the various live views to stop. Called when the user directed the - // page to stop loading. - void Stop(); - - // Notifies the regular and pending RenderViewHosts that a load is or is not - // happening. Even though the message is only for one of them, we don't know - // which one so we tell both. - void SetIsLoading(bool is_loading); - - // Whether to close the tab or not when there is a hang during an unload - // handler. If we are mid-crosssite navigation, then we should proceed - // with the navigation instead of closing the tab. - bool ShouldCloseTabOnUnresponsiveRenderer(); - - // Called when a renderer's main frame navigates. - void DidNavigateMainFrame(RenderViewHost* render_view_host); - - // Set the WebUI after committing a page load. This is useful for navigations - // initiated from a renderer, where we want to give the new renderer WebUI - // privileges from the originating renderer. - void SetWebUIPostCommit(WebUI* web_ui); - - // Called when a provisional load on the given renderer is aborted. - void RendererAbortedProvisionalLoad(RenderViewHost* render_view_host); - - // Sets the passed passed interstitial as the currently showing interstitial. - // |interstitial_page| should be non NULL (use the remove_interstitial_page - // method to unset the interstitial) and no interstitial page should be set - // when there is already a non NULL interstitial page set. - void set_interstitial_page(InterstitialPage* interstitial_page) { - DCHECK(!interstitial_page_ && interstitial_page); - interstitial_page_ = interstitial_page; - } - - // Unsets the currently showing interstitial. - void remove_interstitial_page() { - DCHECK(interstitial_page_); - interstitial_page_ = NULL; - } - - // Returns the currently showing interstitial, NULL if no interstitial is - // showing. - InterstitialPage* interstitial_page() const { - return interstitial_page_; - } - - // RenderViewHostDelegate::RendererManagement implementation. - virtual void ShouldClosePage(bool for_cross_site_transition, bool proceed); - virtual void OnCrossSiteResponse(int new_render_process_host_id, - int new_request_id); - virtual void OnCrossSiteNavigationCanceled(); - - // Called when a RenderViewHost is about to be deleted. - void RenderViewDeleted(RenderViewHost* rvh); - - // Allows a caller to swap in a provided RenderViewHost to replace the - // current RenderViewHost. The current RVH will be shutdown and ultimately - // deleted. - void SwapInRenderViewHost(RenderViewHost* rvh); - - private: - friend class TestTabContents; - friend class RenderViewHostManagerTest; - - // Returns whether this tab should transition to a new renderer for - // cross-site URLs. Enabled unless we see the --process-per-tab command line - // switch. Can be overridden in unit tests. - bool ShouldTransitionCrossSite(); - - // Returns true if the two navigation entries are incompatible in some way - // other than site instances. Cases where this can happen include Web UI - // to regular web pages. It will cause us to swap RenderViewHosts (and hence - // RenderProcessHosts) even if the site instance would otherwise be the same. - // As part of this, we'll also force new SiteInstances and BrowsingInstances. - // Either of the entries may be NULL. - bool ShouldSwapProcessesForNavigation( - const NavigationEntry* cur_entry, - const NavigationEntry* new_entry) const; - - // Returns an appropriate SiteInstance object for the given NavigationEntry, - // possibly reusing the current SiteInstance. - // Never called if --process-per-tab is used. - SiteInstance* GetSiteInstanceForEntry(const NavigationEntry& entry, - SiteInstance* curr_instance); - - // Helper method to create a pending RenderViewHost for a cross-site - // navigation. - bool CreatePendingRenderView(const NavigationEntry& entry, - SiteInstance* instance); - - // Sets up the necessary state for a new RenderViewHost navigating to the - // given entry. - bool InitRenderView(RenderViewHost* render_view_host, - const NavigationEntry& entry); - - // Sets the pending RenderViewHost/WebUI to be the active one. Note that this - // doesn't require the pending render_view_host_ pointer to be non-NULL, since - // there could be Web UI switching as well. Call this for every commit. - void CommitPending(); - - // Helper method to terminate the pending RenderViewHost. - void CancelPending(); - - RenderViewHost* UpdateRendererStateForNavigate(const NavigationEntry& entry); - - // Our delegate, not owned by us. Guaranteed non-NULL. - Delegate* delegate_; - - // Whether a navigation requiring different RenderView's is pending. This is - // either cross-site request is (in the new process model), or when required - // for the view type (like view source versus not). - bool cross_navigation_pending_; - - // Implemented by the owner of this class, this delegate is installed into all - // the RenderViewHosts that we create. - RenderViewHostDelegate* render_view_delegate_; - - // Our RenderView host and its associated Web UI (if any, will be NULL for - // non-DOM-UI pages). This object is responsible for all communication with - // a child RenderView instance. - RenderViewHost* render_view_host_; - scoped_ptr<WebUI> web_ui_; - - // A RenderViewHost used to load a cross-site page. This remains hidden - // while a cross-site request is pending until it calls DidNavigate. It may - // have an associated Web UI, in which case the Web UI pointer will be non- - // NULL. - // - // The pending_web_ui may be non-NULL even when the pending_render_view_host_ - // is. This will happen when we're transitioning between two Web UI pages: - // the RVH won't be swapped, so the pending pointer will be unused, but there - // will be a pending Web UI associated with the navigation. - RenderViewHost* pending_render_view_host_; - scoped_ptr<WebUI> pending_web_ui_; - - // The intersitial page currently shown if any, not own by this class - // (the InterstitialPage is self-owned, it deletes itself when hidden). - InterstitialPage* interstitial_page_; - - NotificationRegistrar registrar_; - - DISALLOW_COPY_AND_ASSIGN(RenderViewHostManager); -}; - -// The "details" for a NOTIFY_RENDER_VIEW_HOST_CHANGED notification. The old -// host can be NULL when the first RenderViewHost is set. -struct RenderViewHostSwitchedDetails { - RenderViewHost* old_host; - RenderViewHost* new_host; -}; +// TODO(jam): remove this file when all files have been converted. +#include "content/browser/tab_contents/render_view_host_manager.h" #endif // CHROME_BROWSER_TAB_CONTENTS_RENDER_VIEW_HOST_MANAGER_H_ diff --git a/chrome/browser/tab_contents/render_view_host_manager_unittest.cc b/chrome/browser/tab_contents/render_view_host_manager_unittest.cc deleted file mode 100644 index a4b82d8..0000000 --- a/chrome/browser/tab_contents/render_view_host_manager_unittest.cc +++ /dev/null @@ -1,345 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/browser_thread.h" -#include "chrome/browser/browser_url_handler.h" -#include "chrome/browser/renderer_host/site_instance.h" -#include "chrome/browser/renderer_host/test/test_render_view_host.h" -#include "chrome/browser/tab_contents/navigation_controller.h" -#include "chrome/browser/tab_contents/navigation_entry.h" -#include "chrome/browser/tab_contents/render_view_host_manager.h" -#include "chrome/browser/tab_contents/test_tab_contents.h" -#include "chrome/common/notification_details.h" -#include "chrome/common/notification_source.h" -#include "chrome/common/page_transition_types.h" -#include "chrome/common/render_messages.h" -#include "chrome/common/render_messages_params.h" -#include "chrome/common/url_constants.h" -#include "chrome/test/test_notification_tracker.h" -#include "chrome/test/testing_profile.h" -#include "ipc/ipc_message.h" -#include "testing/gtest/include/gtest/gtest.h" - -class RenderViewHostManagerTest : public RenderViewHostTestHarness { - public: - void NavigateActiveAndCommit(const GURL& url) { - // Note: we navigate the active RenderViewHost because previous navigations - // won't have committed yet, so NavigateAndCommit does the wrong thing - // for us. - controller().LoadURL(url, GURL(), PageTransition::LINK); - active_rvh()->SendNavigate( - static_cast<MockRenderProcessHost*>(active_rvh()->process())-> - max_page_id() + 1, - url); - } - - bool ShouldSwapProcesses(RenderViewHostManager* manager, - const NavigationEntry* cur_entry, - const NavigationEntry* new_entry) const { - return manager->ShouldSwapProcessesForNavigation(cur_entry, new_entry); - } -}; - -// Tests that when you navigate from the New TabPage to another page, and -// then do that same thing in another tab, that the two resulting pages have -// different SiteInstances, BrowsingInstances, and RenderProcessHosts. This is -// a regression test for bug 9364. -TEST_F(RenderViewHostManagerTest, NewTabPageProcesses) { - BrowserThread ui_thread(BrowserThread::UI, MessageLoop::current()); - GURL ntp(chrome::kChromeUINewTabURL); - GURL dest("http://www.google.com/"); - - // Navigate our first tab to the new tab page and then to the destination. - NavigateActiveAndCommit(ntp); - NavigateActiveAndCommit(dest); - - // Make a second tab. - TestTabContents contents2(profile_.get(), NULL); - - // Load the two URLs in the second tab. Note that the first navigation creates - // a RVH that's not pending (since there is no cross-site transition), so - // we use the committed one, but the second one is the opposite. - contents2.controller().LoadURL(ntp, GURL(), PageTransition::LINK); - static_cast<TestRenderViewHost*>(contents2.render_manager()-> - current_host())->SendNavigate(100, ntp); - contents2.controller().LoadURL(dest, GURL(), PageTransition::LINK); - static_cast<TestRenderViewHost*>(contents2.render_manager()-> - pending_render_view_host())->SendNavigate(101, dest); - - // The two RVH's should be different in every way. - EXPECT_NE(active_rvh()->process(), contents2.render_view_host()->process()); - EXPECT_NE(active_rvh()->site_instance(), - contents2.render_view_host()->site_instance()); - EXPECT_NE(active_rvh()->site_instance()->browsing_instance(), - contents2.render_view_host()->site_instance()->browsing_instance()); - - // Navigate both to the new tab page, and verify that they share a - // SiteInstance. - NavigateActiveAndCommit(ntp); - - contents2.controller().LoadURL(ntp, GURL(), PageTransition::LINK); - static_cast<TestRenderViewHost*>(contents2.render_manager()-> - pending_render_view_host())->SendNavigate(102, ntp); - - EXPECT_EQ(active_rvh()->site_instance(), - contents2.render_view_host()->site_instance()); -} - -// When there is an error with the specified page, renderer exits view-source -// mode. See WebFrameImpl::DidFail(). We check by this test that -// EnableViewSourceMode message is sent on every navigation regardless -// RenderView is being newly created or reused. -TEST_F(RenderViewHostManagerTest, AlwaysSendEnableViewSourceMode) { - BrowserThread ui_thread(BrowserThread::UI, MessageLoop::current()); - const GURL kNtpUrl(chrome::kChromeUINewTabURL); - const GURL kUrl("view-source:http://foo"); - - // We have to navigate to some page at first since without this, the first - // navigation will reuse the SiteInstance created by Init(), and the second - // one will create a new SiteInstance. Because current_instance and - // new_instance will be different, a new RenderViewHost will be created for - // the second navigation. We have to avoid this in order to exercise the - // target code patch. - NavigateActiveAndCommit(kNtpUrl); - - // Navigate. - controller().LoadURL(kUrl, GURL() /* referer */, PageTransition::TYPED); - // Simulate response from RenderView for FirePageBeforeUnload. - rvh()->TestOnMessageReceived( - ViewHostMsg_ShouldClose_ACK(rvh()->routing_id(), true)); - ASSERT_TRUE(pending_rvh()); // New pending RenderViewHost will be created. - RenderViewHost* last_rvh = pending_rvh(); - int new_id = static_cast<MockRenderProcessHost*>(pending_rvh()->process())-> - max_page_id() + 1; - pending_rvh()->SendNavigate(new_id, kUrl); - EXPECT_EQ(controller().last_committed_entry_index(), 1); - ASSERT_TRUE(controller().GetLastCommittedEntry()); - EXPECT_TRUE(kUrl == controller().GetLastCommittedEntry()->url()); - EXPECT_FALSE(controller().pending_entry()); - // Because we're using TestTabContents and TestRenderViewHost in this - // unittest, no one calls TabContents::RenderViewCreated(). So, we see no - // EnableViewSourceMode message, here. - - // Clear queued messages before load. - process()->sink().ClearMessages(); - // Navigate, again. - controller().LoadURL(kUrl, GURL() /* referer */, PageTransition::TYPED); - // The same RenderViewHost should be reused. - EXPECT_FALSE(pending_rvh()); - EXPECT_TRUE(last_rvh == rvh()); - rvh()->SendNavigate(new_id, kUrl); // The same page_id returned. - EXPECT_EQ(controller().last_committed_entry_index(), 1); - EXPECT_FALSE(controller().pending_entry()); - // New message should be sent out to make sure to enter view-source mode. - EXPECT_TRUE(process()->sink().GetUniqueMessageMatching( - ViewMsg_EnableViewSourceMode::ID)); -} - -// Tests the Init function by checking the initial RenderViewHost. -TEST_F(RenderViewHostManagerTest, Init) { - // Using TestingProfile. - SiteInstance* instance = SiteInstance::CreateSiteInstance(profile_.get()); - EXPECT_FALSE(instance->has_site()); - - TestTabContents tab_contents(profile_.get(), instance); - RenderViewHostManager manager(&tab_contents, &tab_contents); - - manager.Init(profile_.get(), instance, MSG_ROUTING_NONE); - - RenderViewHost* host = manager.current_host(); - ASSERT_TRUE(host); - EXPECT_TRUE(instance == host->site_instance()); - EXPECT_TRUE(&tab_contents == host->delegate()); - EXPECT_TRUE(manager.GetRenderWidgetHostView()); - EXPECT_FALSE(manager.pending_render_view_host()); -} - -// Tests the Navigate function. We navigate three sites consecutively and check -// how the pending/committed RenderViewHost are modified. -TEST_F(RenderViewHostManagerTest, Navigate) { - TestNotificationTracker notifications; - - SiteInstance* instance = SiteInstance::CreateSiteInstance(profile_.get()); - - TestTabContents tab_contents(profile_.get(), instance); - notifications.ListenFor(NotificationType::RENDER_VIEW_HOST_CHANGED, - Source<NavigationController>(&tab_contents.controller())); - - // Create. - RenderViewHostManager manager(&tab_contents, &tab_contents); - - manager.Init(profile_.get(), instance, MSG_ROUTING_NONE); - - RenderViewHost* host; - - // 1) The first navigation. -------------------------- - GURL url1("http://www.google.com/"); - NavigationEntry entry1(NULL /* instance */, -1 /* page_id */, url1, - GURL() /* referrer */, string16() /* title */, - PageTransition::TYPED); - host = manager.Navigate(entry1); - - // The RenderViewHost created in Init will be reused. - EXPECT_TRUE(host == manager.current_host()); - EXPECT_FALSE(manager.pending_render_view_host()); - - // Commit. - manager.DidNavigateMainFrame(host); - // Commit to SiteInstance should be delayed until RenderView commit. - EXPECT_TRUE(host == manager.current_host()); - ASSERT_TRUE(host); - EXPECT_FALSE(host->site_instance()->has_site()); - host->site_instance()->SetSite(url1); - - // 2) Navigate to next site. ------------------------- - GURL url2("http://www.google.com/foo"); - NavigationEntry entry2(NULL /* instance */, -1 /* page_id */, url2, - url1 /* referrer */, string16() /* title */, - PageTransition::LINK); - host = manager.Navigate(entry2); - - // The RenderViewHost created in Init will be reused. - EXPECT_TRUE(host == manager.current_host()); - EXPECT_FALSE(manager.pending_render_view_host()); - - // Commit. - manager.DidNavigateMainFrame(host); - EXPECT_TRUE(host == manager.current_host()); - ASSERT_TRUE(host); - EXPECT_TRUE(host->site_instance()->has_site()); - - // 3) Cross-site navigate to next site. -------------- - GURL url3("http://webkit.org/"); - NavigationEntry entry3(NULL /* instance */, -1 /* page_id */, url3, - url2 /* referrer */, string16() /* title */, - PageTransition::LINK); - host = manager.Navigate(entry3); - - // A new RenderViewHost should be created. - EXPECT_TRUE(manager.pending_render_view_host()); - EXPECT_TRUE(host == manager.pending_render_view_host()); - - notifications.Reset(); - - // Commit. - manager.DidNavigateMainFrame(manager.pending_render_view_host()); - EXPECT_TRUE(host == manager.current_host()); - ASSERT_TRUE(host); - EXPECT_TRUE(host->site_instance()->has_site()); - // Check the pending RenderViewHost has been committed. - EXPECT_FALSE(manager.pending_render_view_host()); - - // We should observe a notification. - EXPECT_TRUE(notifications.Check1AndReset( - NotificationType::RENDER_VIEW_HOST_CHANGED)); -} - -// Tests WebUI creation. -TEST_F(RenderViewHostManagerTest, WebUI) { - BrowserThread ui_thread(BrowserThread::UI, MessageLoop::current()); - SiteInstance* instance = SiteInstance::CreateSiteInstance(profile_.get()); - - TestTabContents tab_contents(profile_.get(), instance); - RenderViewHostManager manager(&tab_contents, &tab_contents); - - manager.Init(profile_.get(), instance, MSG_ROUTING_NONE); - - GURL url(chrome::kChromeUINewTabURL); - NavigationEntry entry(NULL /* instance */, -1 /* page_id */, url, - GURL() /* referrer */, string16() /* title */, - PageTransition::TYPED); - RenderViewHost* host = manager.Navigate(entry); - - EXPECT_TRUE(host); - EXPECT_TRUE(host == manager.current_host()); - EXPECT_FALSE(manager.pending_render_view_host()); - - // It's important that the site instance get set on the Web UI page as soon - // as the navigation starts, rather than lazily after it commits, so we don't - // try to re-use the SiteInstance/process for non DOM-UI things that may - // get loaded in between. - EXPECT_TRUE(host->site_instance()->has_site()); - EXPECT_EQ(url, host->site_instance()->site()); - - // The Web UI is committed immediately because the RenderViewHost has not been - // used yet. UpdateRendererStateForNavigate() took the short cut path. - EXPECT_FALSE(manager.pending_web_ui()); - EXPECT_TRUE(manager.web_ui()); - - // Commit. - manager.DidNavigateMainFrame(host); -} - -// Tests that chrome: URLs that are not Web UI pages do not get grouped into -// Web UI renderers, even if --process-per-tab is enabled. In that mode, we -// still swap processes if ShouldSwapProcessesForNavigation is true. -// Regression test for bug 46290. -TEST_F(RenderViewHostManagerTest, NonWebUIChromeURLs) { - BrowserThread thread(BrowserThread::UI, &message_loop_); - SiteInstance* instance = SiteInstance::CreateSiteInstance(profile_.get()); - TestTabContents tab_contents(profile_.get(), instance); - RenderViewHostManager manager(&tab_contents, &tab_contents); - manager.Init(profile_.get(), instance, MSG_ROUTING_NONE); - - // NTP is a Web UI page. - GURL ntp_url(chrome::kChromeUINewTabURL); - NavigationEntry ntp_entry(NULL /* instance */, -1 /* page_id */, ntp_url, - GURL() /* referrer */, string16() /* title */, - PageTransition::TYPED); - - // about: URLs are not Web UI pages. - GURL about_url(chrome::kAboutMemoryURL); - // Rewrite so it looks like chrome://about/memory - bool reverse_on_redirect = false; - BrowserURLHandler::RewriteURLIfNecessary( - &about_url, profile_.get(), &reverse_on_redirect); - NavigationEntry about_entry(NULL /* instance */, -1 /* page_id */, about_url, - GURL() /* referrer */, string16() /* title */, - PageTransition::TYPED); - - EXPECT_TRUE(ShouldSwapProcesses(&manager, &ntp_entry, &about_entry)); -} - -// Tests that we don't end up in an inconsistent state if a page does a back and -// then reload. http://crbug.com/51680 -TEST_F(RenderViewHostManagerTest, PageDoesBackAndReload) { - GURL url1("http://www.google.com/"); - GURL url2("http://www.evil-site.com/"); - - // Navigate to a safe site, then an evil site. - // This will switch RenderViewHosts. We cannot assert that the first and - // second RVHs are different, though, because the first one may be promptly - // deleted. - contents()->NavigateAndCommit(url1); - contents()->NavigateAndCommit(url2); - RenderViewHost* evil_rvh = contents()->render_view_host(); - - // Now let's simulate the evil page calling history.back(). - contents()->OnGoToEntryAtOffset(-1); - // We should have a new pending RVH. - // Note that in this case, the navigation has not committed, so evil_rvh will - // not be deleted yet. - EXPECT_NE(evil_rvh, contents()->render_manager()->pending_render_view_host()); - - // Before that RVH has committed, the evil page reloads itself. - ViewHostMsg_FrameNavigate_Params params; - params.page_id = 1; - params.url = url2; - params.transition = PageTransition::CLIENT_REDIRECT; - params.should_update_history = false; - params.gesture = NavigationGestureAuto; - params.was_within_same_page = false; - params.is_post = false; - contents()->TestDidNavigate(evil_rvh, params); - - // That should have cancelled the pending RVH, and the evil RVH should be the - // current one. - EXPECT_TRUE(contents()->render_manager()->pending_render_view_host() == NULL); - EXPECT_EQ(evil_rvh, contents()->render_manager()->current_host()); - - // Also we should not have a pending navigation entry. - NavigationEntry* entry = contents()->controller().GetActiveEntry(); - ASSERT_TRUE(entry != NULL); - EXPECT_EQ(url2, entry->url()); -} diff --git a/chrome/browser/tab_contents/tab_contents.cc b/chrome/browser/tab_contents/tab_contents.cc deleted file mode 100644 index 62666c9..0000000 --- a/chrome/browser/tab_contents/tab_contents.cc +++ /dev/null @@ -1,2962 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/tab_contents/tab_contents.h" - -#include <cmath> - -#include "base/auto_reset.h" -#include "base/metrics/histogram.h" -#include "base/metrics/stats_counters.h" -#include "base/string16.h" -#include "base/string_util.h" -#include "base/time.h" -#include "base/utf_string_conversions.h" -#include "chrome/browser/autocomplete_history_manager.h" -#include "chrome/browser/autofill/autofill_manager.h" -#include "chrome/browser/blocked_content_container.h" -#include "chrome/browser/browser_process.h" -#include "chrome/browser/browser_shutdown.h" -#include "chrome/browser/character_encoding.h" -#include "chrome/browser/child_process_security_policy.h" -#include "chrome/browser/content_settings/content_settings_details.h" -#include "chrome/browser/content_settings/host_content_settings_map.h" -#include "chrome/browser/debugger/devtools_manager.h" -#include "chrome/browser/defaults.h" -#include "chrome/browser/desktop_notification_handler.h" -#include "chrome/browser/dom_operation_notification_details.h" -#include "chrome/browser/download/download_item_model.h" -#include "chrome/browser/download/download_manager.h" -#include "chrome/browser/download/download_request_limiter.h" -#include "chrome/browser/extensions/extension_service.h" -#include "chrome/browser/external_protocol_handler.h" -#include "chrome/browser/favicon_service.h" -#include "chrome/browser/file_select_helper.h" -#include "chrome/browser/google/google_util.h" -#include "chrome/browser/history/history.h" -#include "chrome/browser/history/history_types.h" -#include "chrome/browser/history/top_sites.h" -#include "chrome/browser/host_zoom_map.h" -#include "chrome/browser/hung_renderer_dialog.h" -#include "chrome/browser/in_process_webkit/session_storage_namespace.h" -#include "chrome/browser/load_from_memory_cache_details.h" -#include "chrome/browser/load_notification_details.h" -#include "chrome/browser/metrics/metric_event_duration_details.h" -#include "chrome/browser/metrics/user_metrics.h" -#include "chrome/browser/modal_html_dialog_delegate.h" -#include "chrome/browser/omnibox_search_hint.h" -#include "chrome/browser/pdf_unsupported_feature.h" -#include "chrome/browser/platform_util.h" -#include "chrome/browser/plugin_observer.h" -#include "chrome/browser/prefs/pref_service.h" -#include "chrome/browser/prerender/prerender_manager.h" -#include "chrome/browser/prerender/prerender_plt_recorder.h" -#include "chrome/browser/printing/print_preview_message_handler.h" -#include "chrome/browser/printing/print_preview_tab_controller.h" -#include "chrome/browser/printing/print_view_manager.h" -#include "chrome/browser/profiles/profile.h" -#include "chrome/browser/renderer_host/render_process_host.h" -#include "chrome/browser/renderer_host/render_view_host.h" -#include "chrome/browser/renderer_host/render_widget_host_view.h" -#include "chrome/browser/renderer_host/resource_request_details.h" -#include "chrome/browser/renderer_host/site_instance.h" -#include "chrome/browser/renderer_host/web_cache_manager.h" -#include "chrome/browser/renderer_preferences_util.h" -#include "chrome/browser/safe_browsing/client_side_detection_host.h" -#include "chrome/browser/sessions/session_types.h" -#include "chrome/browser/tab_contents/infobar_delegate.h" -#include "chrome/browser/tab_contents/interstitial_page.h" -#include "chrome/browser/tab_contents/navigation_entry.h" -#include "chrome/browser/tab_contents/provisional_load_details.h" -#include "chrome/browser/tab_contents/tab_contents_delegate.h" -#include "chrome/browser/tab_contents/tab_contents_observer.h" -#include "chrome/browser/tab_contents/tab_contents_ssl_helper.h" -#include "chrome/browser/tab_contents/tab_contents_view.h" -#include "chrome/browser/tab_contents/thumbnail_generator.h" -#include "chrome/browser/translate/page_translated_details.h" -#include "chrome/browser/ui/app_modal_dialogs/message_box_handler.h" -#include "chrome/browser/webui/web_ui.h" -#include "chrome/common/bindings_policy.h" -#include "chrome/common/chrome_switches.h" -#include "chrome/common/content_restriction.h" -#include "chrome/common/extensions/extension.h" -#include "chrome/common/extensions/extension_action.h" -#include "chrome/common/extensions/extension_icon_set.h" -#include "chrome/common/extensions/extension_resource.h" -#include "chrome/common/extensions/url_pattern.h" -#include "chrome/common/navigation_types.h" -#include "chrome/common/net/url_request_context_getter.h" -#include "chrome/common/notification_service.h" -#include "chrome/common/pref_names.h" -#include "chrome/common/render_messages.h" -#include "chrome/common/render_messages_params.h" -#include "chrome/common/url_constants.h" -#include "grit/chromium_strings.h" -#include "grit/generated_resources.h" -#include "grit/locale_settings.h" -#include "grit/platform_locale_settings.h" -#include "grit/theme_resources.h" -#include "net/base/net_util.h" -#include "net/base/registry_controlled_domain.h" -#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h" -#include "ui/base/l10n/l10n_util.h" -#include "ui/base/resource/resource_bundle.h" -#include "ui/gfx/codec/png_codec.h" -#include "webkit/glue/password_form.h" -#include "webkit/glue/webpreferences.h" - -#if defined(OS_MACOSX) -#include "app/surface/io_surface_support_mac.h" -#endif // defined(OS_MACOSX) - -#if defined(OS_CHROMEOS) -#include "chrome/browser/chromeos/locale_change_guard.h" -#endif // defined(OS_CHROMEOS) - -// Cross-Site Navigations -// -// If a TabContents is told to navigate to a different web site (as determined -// by SiteInstance), it will replace its current RenderViewHost with a new -// RenderViewHost dedicated to the new SiteInstance. This works as follows: -// -// - Navigate determines whether the destination is cross-site, and if so, -// it creates a pending_render_view_host_ and moves into the PENDING -// RendererState. -// - The pending RVH is "suspended," so that no navigation messages are sent to -// its renderer until the onbeforeunload JavaScript handler has a chance to -// run in the current RVH. -// - The pending RVH tells CrossSiteRequestManager (a thread-safe singleton) -// that it has a pending cross-site request. ResourceDispatcherHost will -// check for this when the response arrives. -// - The current RVH runs its onbeforeunload handler. If it returns false, we -// cancel all the pending logic and go back to NORMAL. Otherwise we allow -// the pending RVH to send the navigation request to its renderer. -// - ResourceDispatcherHost receives a ResourceRequest on the IO thread. It -// checks CrossSiteRequestManager to see that the RVH responsible has a -// pending cross-site request, and then installs a CrossSiteEventHandler. -// - When RDH receives a response, the BufferedEventHandler determines whether -// it is a download. If so, it sends a message to the new renderer causing -// it to cancel the request, and the download proceeds in the download -// thread. For now, we stay in a PENDING state (with a pending RVH) until -// the next DidNavigate event for this TabContents. This isn't ideal, but it -// doesn't affect any functionality. -// - After RDH receives a response and determines that it is safe and not a -// download, it pauses the response to first run the old page's onunload -// handler. It does this by asynchronously calling the OnCrossSiteResponse -// method of TabContents on the UI thread, which sends a ClosePage message -// to the current RVH. -// - Once the onunload handler is finished, a ClosePage_ACK message is sent to -// the ResourceDispatcherHost, who unpauses the response. Data is then sent -// to the pending RVH. -// - The pending renderer sends a FrameNavigate message that invokes the -// DidNavigate method. This replaces the current RVH with the -// pending RVH and goes back to the NORMAL RendererState. - -namespace { - -// Amount of time we wait between when a key event is received and the renderer -// is queried for its state and pushed to the NavigationEntry. -const int kQueryStateDelay = 5000; - -const int kSyncWaitDelay = 40; - -// If another javascript message box is displayed within -// kJavascriptMessageExpectedDelay of a previous javascript message box being -// dismissed, display an option to suppress future message boxes from this -// contents. -const int kJavascriptMessageExpectedDelay = 1000; - -// The list of prefs we want to observe. -const char* kPrefsToObserve[] = { - prefs::kAlternateErrorPagesEnabled, - prefs::kDefaultZoomLevel, - prefs::kWebKitJavaEnabled, - prefs::kWebKitJavascriptEnabled, - prefs::kWebKitLoadsImagesAutomatically, - prefs::kWebKitPluginsEnabled, - prefs::kWebKitUsesUniversalDetector, - prefs::kWebKitSerifFontFamily, - prefs::kWebKitSansSerifFontFamily, - prefs::kWebKitFixedFontFamily, - prefs::kWebKitDefaultFontSize, - prefs::kWebKitDefaultFixedFontSize, - prefs::kWebKitMinimumFontSize, - prefs::kWebKitMinimumLogicalFontSize, - prefs::kWebkitTabsToLinks, - prefs::kDefaultCharset - // kWebKitStandardFontIsSerif needs to be added - // if we let users pick which font to use, serif or sans-serif when - // no font is specified or a CSS generic family (serif or sans-serif) - // is not specified. -}; - -const int kPrefsToObserveLength = arraysize(kPrefsToObserve); - -#if defined(OS_WIN) - -BOOL CALLBACK InvalidateWindow(HWND hwnd, LPARAM lparam) { - // Note: erase is required to properly paint some widgets borders. This can - // be seen with textfields. - InvalidateRect(hwnd, NULL, TRUE); - return TRUE; -} -#endif - -ViewMsg_Navigate_Params::NavigationType GetNavigationType( - Profile* profile, const NavigationEntry& entry, - NavigationController::ReloadType reload_type) { - switch (reload_type) { - case NavigationController::RELOAD: - return ViewMsg_Navigate_Params::RELOAD; - case NavigationController::RELOAD_IGNORING_CACHE: - return ViewMsg_Navigate_Params::RELOAD_IGNORING_CACHE; - case NavigationController::NO_RELOAD: - break; // Fall through to rest of function. - } - - if (entry.restore_type() == NavigationEntry::RESTORE_LAST_SESSION && - profile->DidLastSessionExitCleanly()) - return ViewMsg_Navigate_Params::RESTORE; - - return ViewMsg_Navigate_Params::NORMAL; -} - -void MakeNavigateParams(const NavigationEntry& entry, - const NavigationController& controller, - NavigationController::ReloadType reload_type, - ViewMsg_Navigate_Params* params) { - params->page_id = entry.page_id(); - params->pending_history_list_offset = controller.GetIndexOfEntry(&entry); - params->current_history_list_offset = controller.last_committed_entry_index(); - params->current_history_list_length = controller.entry_count(); - params->url = entry.url(); - params->referrer = entry.referrer(); - params->transition = entry.transition_type(); - params->state = entry.content_state(); - params->navigation_type = - GetNavigationType(controller.profile(), entry, reload_type); - params->request_time = base::Time::Now(); -} - -} // namespace - - -// TabContents ---------------------------------------------------------------- - -TabContents::TabContents(Profile* profile, - SiteInstance* site_instance, - int routing_id, - const TabContents* base_tab_contents, - SessionStorageNamespace* session_storage_namespace) - : delegate_(NULL), - ALLOW_THIS_IN_INITIALIZER_LIST(controller_( - this, profile, session_storage_namespace)), - ALLOW_THIS_IN_INITIALIZER_LIST(view_( - TabContentsView::Create(this))), - ALLOW_THIS_IN_INITIALIZER_LIST(render_manager_(this, this)), - bookmark_drag_(NULL), - is_loading_(false), - crashed_status_(base::TERMINATION_STATUS_STILL_RUNNING), - crashed_error_code_(0), - waiting_for_response_(false), - max_page_id_(-1), - load_state_(net::LOAD_STATE_IDLE), - upload_size_(0), - upload_position_(0), - received_page_title_(false), - blocked_contents_(NULL), - all_contents_blocked_(false), - dont_notify_render_view_(false), - displayed_insecure_content_(false), - extension_app_(NULL), - capturing_contents_(false), - is_being_destroyed_(false), - notify_disconnection_(false), -#if defined(OS_WIN) - message_box_active_(CreateEvent(NULL, TRUE, FALSE, NULL)), -#endif - suppress_javascript_messages_(false), - is_showing_before_unload_dialog_(false), - opener_web_ui_type_(WebUIFactory::kNoWebUI), - language_state_(&controller_), - closed_by_user_gesture_(false), - minimum_zoom_percent_( - static_cast<int>(WebKit::WebView::minTextSizeMultiplier * 100)), - maximum_zoom_percent_( - static_cast<int>(WebKit::WebView::maxTextSizeMultiplier * 100)), - temporary_zoom_settings_(false), - content_restrictions_(0) { - renderer_preferences_util::UpdateFromSystemSettings( - &renderer_preferences_, profile); - - content_settings_delegate_.reset( - new TabSpecificContentSettings(this, profile)); - - render_manager_.Init(profile, site_instance, routing_id); - - // We have the initial size of the view be based on the size of the passed in - // tab contents (normally a tab from the same window). - view_->CreateView(base_tab_contents ? - base_tab_contents->view()->GetContainerSize() : gfx::Size()); - - // Register for notifications about all interested prefs change. - PrefService* prefs = profile->GetPrefs(); - pref_change_registrar_.Init(prefs); - if (prefs) { - for (int i = 0; i < kPrefsToObserveLength; ++i) - pref_change_registrar_.Add(kPrefsToObserve[i], this); - } - - registrar_.Add(this, NotificationType::RENDER_WIDGET_HOST_DESTROYED, - NotificationService::AllSources()); -#if defined(OS_LINUX) - registrar_.Add(this, NotificationType::BROWSER_THEME_CHANGED, - NotificationService::AllSources()); -#endif - - registrar_.Add(this, NotificationType::USER_STYLE_SHEET_UPDATED, - NotificationService::AllSources()); - - // Register for notifications about content setting changes. - registrar_.Add(this, NotificationType::CONTENT_SETTINGS_CHANGED, - NotificationService::AllSources()); - - // Listen for extension changes so we can update extension_for_current_page_. - registrar_.Add(this, NotificationType::EXTENSION_LOADED, - NotificationService::AllSources()); - registrar_.Add(this, NotificationType::EXTENSION_UNLOADED, - NotificationService::AllSources()); - - // Listen for Google URL changes - registrar_.Add(this, NotificationType::GOOGLE_URL_UPDATED, - NotificationService::AllSources()); - - // Set-up the showing of the omnibox search infobar if applicable. - if (OmniboxSearchHint::IsEnabled(profile)) - omnibox_search_hint_.reset(new OmniboxSearchHint(this)); - - // Can only add observers after render_manager_.Init() is called, since that's - // what sets up the render_view_host which TabContentObserver's constructor - // uses to get the routing_id. - AddObservers(); -} - -TabContents::~TabContents() { - is_being_destroyed_ = true; - - // We don't want any notifications while we're running our destructor. - registrar_.RemoveAll(); - pref_change_registrar_.RemoveAll(); - - NotifyDisconnected(); - hung_renderer_dialog::HideForTabContents(this); - - // First cleanly close all child windows. - // TODO(mpcomplete): handle case if MaybeCloseChildWindows() already asked - // some of these to close. CloseWindows is async, so it might get called - // twice before it runs. - CloseConstrainedWindows(); - - // Close all blocked contents. - if (blocked_contents_) - blocked_contents_->Destroy(); - - // Notify any observer that have a reference on this tab contents. - NotificationService::current()->Notify( - NotificationType::TAB_CONTENTS_DESTROYED, - Source<TabContents>(this), - NotificationService::NoDetails()); - - // Notify any lasting InfobarDelegates that have not yet been removed that - // whatever infobar they were handling in this TabContents has closed, - // because the TabContents is going away entirely. - // This must happen after the TAB_CONTENTS_DESTROYED notification as the - // notification may trigger infobars calls that access their delegate. (and - // some implementations of InfoBarDelegate do delete themselves on - // InfoBarClosed()). - for (size_t i = 0; i < infobar_count(); ++i) { - InfoBarDelegate* delegate = GetInfoBarDelegateAt(i); - delegate->InfoBarClosed(); - } - infobar_delegates_.clear(); - - // TODO(brettw) this should be moved to the view. -#if defined(OS_WIN) - // If we still have a window handle, destroy it. GetNativeView can return - // NULL if this contents was part of a window that closed. - if (GetNativeView()) { - RenderViewHost* host = render_view_host(); - if (host && host->view()) { - host->view()->WillWmDestroy(); - } - ::DestroyWindow(GetNativeView()); - } -#endif - - // OnCloseStarted isn't called in unit tests. - if (!tab_close_start_time_.is_null()) { - UMA_HISTOGRAM_TIMES("Tab.Close", - base::TimeTicks::Now() - tab_close_start_time_); - } - - FOR_EACH_OBSERVER(TabContentsObserver, observers_, set_tab_contents(NULL)); -} - -void TabContents::AddObservers() { - printing_.reset(new printing::PrintViewManager(this)); - print_preview_.reset(new printing::PrintPreviewMessageHandler(this)); - fav_icon_helper_.reset(new FavIconHelper(this)); - autofill_manager_.reset(new AutoFillManager(this)); - autocomplete_history_manager_.reset(new AutocompleteHistoryManager(this)); - prerender_plt_recorder_.reset(new prerender::PrerenderPLTRecorder(this)); - desktop_notification_handler_.reset( - new DesktopNotificationHandlerForTC(this, GetRenderProcessHost())); - plugin_observer_.reset(new PluginObserver(this)); - safebrowsing_detection_host_.reset(new safe_browsing::ClientSideDetectionHost( - this)); -} - -// static -void TabContents::RegisterUserPrefs(PrefService* prefs) { - prefs->RegisterBooleanPref(prefs::kAlternateErrorPagesEnabled, true); - - WebPreferences pref_defaults; - prefs->RegisterBooleanPref(prefs::kWebKitJavascriptEnabled, - pref_defaults.javascript_enabled); - prefs->RegisterBooleanPref(prefs::kWebKitWebSecurityEnabled, - pref_defaults.web_security_enabled); - prefs->RegisterBooleanPref( - prefs::kWebKitJavascriptCanOpenWindowsAutomatically, true); - prefs->RegisterBooleanPref(prefs::kWebKitLoadsImagesAutomatically, - pref_defaults.loads_images_automatically); - prefs->RegisterBooleanPref(prefs::kWebKitPluginsEnabled, - pref_defaults.plugins_enabled); - prefs->RegisterBooleanPref(prefs::kWebKitDomPasteEnabled, - pref_defaults.dom_paste_enabled); - prefs->RegisterBooleanPref(prefs::kWebKitShrinksStandaloneImagesToFit, - pref_defaults.shrinks_standalone_images_to_fit); - prefs->RegisterDictionaryPref(prefs::kWebKitInspectorSettings); - prefs->RegisterBooleanPref(prefs::kWebKitTextAreasAreResizable, - pref_defaults.text_areas_are_resizable); - prefs->RegisterBooleanPref(prefs::kWebKitJavaEnabled, - pref_defaults.java_enabled); - prefs->RegisterBooleanPref(prefs::kWebkitTabsToLinks, - pref_defaults.tabs_to_links); - - prefs->RegisterLocalizedStringPref(prefs::kAcceptLanguages, - IDS_ACCEPT_LANGUAGES); - prefs->RegisterLocalizedStringPref(prefs::kDefaultCharset, - IDS_DEFAULT_ENCODING); - prefs->RegisterLocalizedBooleanPref(prefs::kWebKitStandardFontIsSerif, - IDS_STANDARD_FONT_IS_SERIF); - prefs->RegisterLocalizedStringPref(prefs::kWebKitFixedFontFamily, - IDS_FIXED_FONT_FAMILY); - prefs->RegisterLocalizedStringPref(prefs::kWebKitSerifFontFamily, - IDS_SERIF_FONT_FAMILY); - prefs->RegisterLocalizedStringPref(prefs::kWebKitSansSerifFontFamily, - IDS_SANS_SERIF_FONT_FAMILY); - prefs->RegisterLocalizedStringPref(prefs::kWebKitCursiveFontFamily, - IDS_CURSIVE_FONT_FAMILY); - prefs->RegisterLocalizedStringPref(prefs::kWebKitFantasyFontFamily, - IDS_FANTASY_FONT_FAMILY); - prefs->RegisterLocalizedIntegerPref(prefs::kWebKitDefaultFontSize, - IDS_DEFAULT_FONT_SIZE); - prefs->RegisterLocalizedIntegerPref(prefs::kWebKitDefaultFixedFontSize, - IDS_DEFAULT_FIXED_FONT_SIZE); - prefs->RegisterLocalizedIntegerPref(prefs::kWebKitMinimumFontSize, - IDS_MINIMUM_FONT_SIZE); - prefs->RegisterLocalizedIntegerPref(prefs::kWebKitMinimumLogicalFontSize, - IDS_MINIMUM_LOGICAL_FONT_SIZE); - prefs->RegisterLocalizedBooleanPref(prefs::kWebKitUsesUniversalDetector, - IDS_USES_UNIVERSAL_DETECTOR); - prefs->RegisterLocalizedStringPref(prefs::kStaticEncodings, - IDS_STATIC_ENCODING_LIST); -} - -bool TabContents::OnMessageReceived(const IPC::Message& message) { - ObserverListBase<TabContentsObserver>::Iterator it(observers_); - TabContentsObserver* observer; - while ((observer = it.GetNext()) != NULL) - if (observer->OnMessageReceived(message)) - return true; - - bool handled = true; - bool message_is_ok = true; - IPC_BEGIN_MESSAGE_MAP_EX(TabContents, message, message_is_ok) - IPC_MESSAGE_HANDLER(ViewHostMsg_DidStartProvisionalLoadForFrame, - OnDidStartProvisionalLoadForFrame) - IPC_MESSAGE_HANDLER(ViewHostMsg_DidRedirectProvisionalLoad, - OnDidRedirectProvisionalLoad) - IPC_MESSAGE_HANDLER(ViewHostMsg_DidFailProvisionalLoadWithError, - OnDidFailProvisionalLoadWithError) - IPC_MESSAGE_HANDLER(ViewHostMsg_DidLoadResourceFromMemoryCache, - OnDidLoadResourceFromMemoryCache) - IPC_MESSAGE_HANDLER(ViewHostMsg_DidDisplayInsecureContent, - OnDidDisplayInsecureContent) - IPC_MESSAGE_HANDLER(ViewHostMsg_DidRunInsecureContent, - OnDidRunInsecureContent) - IPC_MESSAGE_HANDLER(ViewHostMsg_DocumentLoadedInFrame, - OnDocumentLoadedInFrame) - IPC_MESSAGE_HANDLER(ViewHostMsg_DidFinishLoad, OnDidFinishLoad) - IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateContentRestrictions, - OnUpdateContentRestrictions) - IPC_MESSAGE_HANDLER(ViewHostMsg_PDFHasUnsupportedFeature, - OnPDFHasUnsupportedFeature) - IPC_MESSAGE_HANDLER(ViewHostMsg_GoToEntryAtOffset, OnGoToEntryAtOffset) - IPC_MESSAGE_HANDLER(ViewHostMsg_DidGetApplicationInfo, - OnDidGetApplicationInfo) - IPC_MESSAGE_HANDLER(ViewHostMsg_InstallApplication, - OnInstallApplication) - IPC_MESSAGE_HANDLER(ViewHostMsg_PageContents, OnPageContents) - IPC_MESSAGE_HANDLER(ViewHostMsg_PageTranslated, OnPageTranslated) - IPC_MESSAGE_HANDLER(ViewHostMsg_SetSuggestions, OnSetSuggestions) - IPC_MESSAGE_HANDLER(ViewHostMsg_InstantSupportDetermined, - OnInstantSupportDetermined) - IPC_MESSAGE_HANDLER(ViewHostMsg_RunFileChooser, OnRunFileChooser) - IPC_MESSAGE_UNHANDLED(handled = false) - IPC_END_MESSAGE_MAP_EX() - - if (!message_is_ok) { - UserMetrics::RecordAction(UserMetricsAction("BadMessageTerminate_RVD")); - GetRenderProcessHost()->ReceivedBadMessage(); - } - - return handled; -} - -// Returns true if contains content rendered by an extension. -bool TabContents::HostsExtension() const { - return GetURL().SchemeIs(chrome::kExtensionScheme); -} - -TabContentsSSLHelper* TabContents::GetSSLHelper() { - if (ssl_helper_.get() == NULL) - ssl_helper_.reset(new TabContentsSSLHelper(this)); - return ssl_helper_.get(); -} - -RenderProcessHost* TabContents::GetRenderProcessHost() const { - return render_manager_.current_host()->process(); -} - -void TabContents::SetExtensionApp(const Extension* extension) { - DCHECK(!extension || extension->GetFullLaunchURL().is_valid()); - extension_app_ = extension; - - UpdateExtensionAppIcon(extension_app_); - - NotificationService::current()->Notify( - NotificationType::TAB_CONTENTS_APPLICATION_EXTENSION_CHANGED, - Source<TabContents>(this), - NotificationService::NoDetails()); -} - -void TabContents::SetExtensionAppById(const std::string& extension_app_id) { - if (extension_app_id.empty()) - return; - - ExtensionService* extension_service = profile()->GetExtensionService(); - if (!extension_service || !extension_service->is_ready()) - return; - - const Extension* extension = - extension_service->GetExtensionById(extension_app_id, false); - if (extension) - SetExtensionApp(extension); -} - -SkBitmap* TabContents::GetExtensionAppIcon() { - if (extension_app_icon_.empty()) - return NULL; - - return &extension_app_icon_; -} - -const GURL& TabContents::GetURL() const { - // We may not have a navigation entry yet - NavigationEntry* entry = controller_.GetActiveEntry(); - return entry ? entry->virtual_url() : GURL::EmptyGURL(); -} - -const string16& TabContents::GetTitle() const { - // Transient entries take precedence. They are used for interstitial pages - // that are shown on top of existing pages. - NavigationEntry* entry = controller_.GetTransientEntry(); - if (entry) { - return entry->GetTitleForDisplay(profile()->GetPrefs()-> - GetString(prefs::kAcceptLanguages)); - } - WebUI* our_web_ui = render_manager_.pending_web_ui() ? - render_manager_.pending_web_ui() : render_manager_.web_ui(); - if (our_web_ui) { - // Don't override the title in view source mode. - entry = controller_.GetActiveEntry(); - if (!(entry && entry->IsViewSourceMode())) { - // Give the Web UI the chance to override our title. - const string16& title = our_web_ui->overridden_title(); - if (!title.empty()) - return title; - } - } - - // We use the title for the last committed entry rather than a pending - // navigation entry. For example, when the user types in a URL, we want to - // keep the old page's title until the new load has committed and we get a new - // title. - entry = controller_.GetLastCommittedEntry(); - if (entry) { - return entry->GetTitleForDisplay(profile()->GetPrefs()-> - GetString(prefs::kAcceptLanguages)); - } - return EmptyString16(); -} - -// static -string16 TabContents::GetDefaultTitle() { - return l10n_util::GetStringUTF16(IDS_DEFAULT_TAB_TITLE); -} - -int32 TabContents::GetMaxPageID() { - if (GetSiteInstance()) - return GetSiteInstance()->max_page_id(); - else - return max_page_id_; -} - -void TabContents::UpdateMaxPageID(int32 page_id) { - // Ensure both the SiteInstance and RenderProcessHost update their max page - // IDs in sync. Only TabContents will also have site instances, except during - // testing. - if (GetSiteInstance()) - GetSiteInstance()->UpdateMaxPageID(page_id); - GetRenderProcessHost()->UpdateMaxPageID(page_id); -} - -SiteInstance* TabContents::GetSiteInstance() const { - return render_manager_.current_host()->site_instance(); -} - -bool TabContents::ShouldDisplayURL() { - // Don't hide the url in view source mode and with interstitials. - NavigationEntry* entry = controller_.GetActiveEntry(); - if (entry && (entry->IsViewSourceMode() || - entry->page_type() == INTERSTITIAL_PAGE)) { - return true; - } - - // We always display the URL for non-WebUI URLs to prevent spoofing. - if (entry && !WebUIFactory::HasWebUIScheme(entry->url())) - return true; - - WebUI* web_ui = GetWebUIForCurrentState(); - if (web_ui) - return !web_ui->should_hide_url(); - return true; -} - -SkBitmap TabContents::GetFavIcon() const { - // Like GetTitle(), we also want to use the favicon for the last committed - // entry rather than a pending navigation entry. - NavigationEntry* entry = controller_.GetTransientEntry(); - if (entry) - return entry->favicon().bitmap(); - - entry = controller_.GetLastCommittedEntry(); - if (entry) - return entry->favicon().bitmap(); - return SkBitmap(); -} - -bool TabContents::FavIconIsValid() const { - NavigationEntry* entry = controller_.GetTransientEntry(); - if (entry) - return entry->favicon().is_valid(); - - entry = controller_.GetLastCommittedEntry(); - if (entry) - return entry->favicon().is_valid(); - - return false; -} - -bool TabContents::ShouldDisplayFavIcon() { - // Always display a throbber during pending loads. - if (controller_.GetLastCommittedEntry() && controller_.pending_entry()) - return true; - - WebUI* web_ui = GetWebUIForCurrentState(); - if (web_ui) - return !web_ui->hide_favicon(); - return true; -} - -string16 TabContents::GetStatusText() const { - if (!is_loading() || load_state_ == net::LOAD_STATE_IDLE) - return string16(); - - switch (load_state_) { - case net::LOAD_STATE_WAITING_FOR_CACHE: - return l10n_util::GetStringUTF16(IDS_LOAD_STATE_WAITING_FOR_CACHE); - case net::LOAD_STATE_ESTABLISHING_PROXY_TUNNEL: - return - l10n_util::GetStringUTF16(IDS_LOAD_STATE_ESTABLISHING_PROXY_TUNNEL); - case net::LOAD_STATE_RESOLVING_PROXY_FOR_URL: - return l10n_util::GetStringUTF16(IDS_LOAD_STATE_RESOLVING_PROXY_FOR_URL); - case net::LOAD_STATE_RESOLVING_HOST: - return l10n_util::GetStringUTF16(IDS_LOAD_STATE_RESOLVING_HOST); - case net::LOAD_STATE_CONNECTING: - return l10n_util::GetStringUTF16(IDS_LOAD_STATE_CONNECTING); - case net::LOAD_STATE_SSL_HANDSHAKE: - return l10n_util::GetStringUTF16(IDS_LOAD_STATE_SSL_HANDSHAKE); - case net::LOAD_STATE_SENDING_REQUEST: - if (upload_size_) - return l10n_util::GetStringFUTF16Int( - IDS_LOAD_STATE_SENDING_REQUEST_WITH_PROGRESS, - static_cast<int>((100 * upload_position_) / upload_size_)); - else - return l10n_util::GetStringUTF16(IDS_LOAD_STATE_SENDING_REQUEST); - case net::LOAD_STATE_WAITING_FOR_RESPONSE: - return l10n_util::GetStringFUTF16(IDS_LOAD_STATE_WAITING_FOR_RESPONSE, - load_state_host_); - // Ignore net::LOAD_STATE_READING_RESPONSE and net::LOAD_STATE_IDLE - case net::LOAD_STATE_IDLE: - case net::LOAD_STATE_READING_RESPONSE: - break; - } - - return string16(); -} - -void TabContents::AddObserver(TabContentsObserver* observer) { - observers_.AddObserver(observer); -} - -void TabContents::RemoveObserver(TabContentsObserver* observer) { - observers_.RemoveObserver(observer); -} - -void TabContents::SetIsCrashed(base::TerminationStatus status, int error_code) { - if (status == crashed_status_) - return; - - crashed_status_ = status; - crashed_error_code_ = error_code; - NotifyNavigationStateChanged(INVALIDATE_TAB); -} - -void TabContents::PageActionStateChanged() { - NotifyNavigationStateChanged(TabContents::INVALIDATE_PAGE_ACTIONS); -} - -void TabContents::NotifyNavigationStateChanged(unsigned changed_flags) { - if (delegate_) - delegate_->NavigationStateChanged(this, changed_flags); -} - -void TabContents::DidBecomeSelected() { - controller_.SetActive(true); - RenderWidgetHostView* rwhv = GetRenderWidgetHostView(); - if (rwhv) { - rwhv->DidBecomeSelected(); -#if defined(OS_MACOSX) - rwhv->SetActive(true); -#endif - } - - WebCacheManager::GetInstance()->ObserveActivity(GetRenderProcessHost()->id()); - last_selected_time_ = base::TimeTicks::Now(); -#if defined(OS_CHROMEOS) - chromeos::LocaleChangeGuard::Check(this); -#endif -} - -void TabContents::FadeForInstant(bool animate) { - RenderWidgetHostView* rwhv = GetRenderWidgetHostView(); - SkColor whitish = SkColorSetARGB(192, 255, 255, 255); - if (rwhv) - rwhv->SetVisuallyDeemphasized(&whitish, animate); -} - -void TabContents::CancelInstantFade() { - RenderWidgetHostView* rwhv = GetRenderWidgetHostView(); - if (rwhv) - rwhv->SetVisuallyDeemphasized(NULL, false); -} - -void TabContents::WasHidden() { - if (!capturing_contents()) { - // |render_view_host()| can be NULL if the user middle clicks a link to open - // a tab in then background, then closes the tab before selecting it. This - // is because closing the tab calls TabContents::Destroy(), which removes - // the |render_view_host()|; then when we actually destroy the window, - // OnWindowPosChanged() notices and calls HideContents() (which calls us). - RenderWidgetHostView* rwhv = GetRenderWidgetHostView(); - if (rwhv) - rwhv->WasHidden(); - } - - NotificationService::current()->Notify( - NotificationType::TAB_CONTENTS_HIDDEN, - Source<TabContents>(this), - NotificationService::NoDetails()); -} - -void TabContents::Activate() { - if (delegate_) - delegate_->ActivateContents(this); -} - -void TabContents::Deactivate() { - if (delegate_) - delegate_->DeactivateContents(this); -} - -void TabContents::ShowContents() { - RenderWidgetHostView* rwhv = GetRenderWidgetHostView(); - if (rwhv) - rwhv->DidBecomeSelected(); -} - -void TabContents::HideContents() { - // TODO(pkasting): http://b/1239839 Right now we purposefully don't call - // our superclass HideContents(), because some callers want to be very picky - // about the order in which these get called. In addition to making the code - // here practically impossible to understand, this also means we end up - // calling TabContents::WasHidden() twice if callers call both versions of - // HideContents() on a TabContents. - WasHidden(); -} - -bool TabContents::NeedToFireBeforeUnload() { - // TODO(creis): Should we fire even for interstitial pages? - return notify_disconnection() && - !showing_interstitial_page() && - !render_view_host()->SuddenTerminationAllowed(); -} - -void TabContents::OpenURL(const GURL& url, const GURL& referrer, - WindowOpenDisposition disposition, - PageTransition::Type transition) { - if (delegate_) - delegate_->OpenURLFromTab(this, url, referrer, disposition, transition); -} - -bool TabContents::NavigateToPendingEntry( - NavigationController::ReloadType reload_type) { - return NavigateToEntry(*controller_.pending_entry(), reload_type); -} - -bool TabContents::NavigateToEntry( - const NavigationEntry& entry, - NavigationController::ReloadType reload_type) { - RenderViewHost* dest_render_view_host = render_manager_.Navigate(entry); - if (!dest_render_view_host) - return false; // Unable to create the desired render view host. - - if (delegate_ && delegate_->ShouldEnablePreferredSizeNotifications()) { - dest_render_view_host->EnablePreferredSizeChangedMode( - kPreferredSizeWidth | kPreferredSizeHeightThisIsSlow); - } - - // For security, we should never send non-Web-UI URLs to a Web UI renderer. - // Double check that here. - int enabled_bindings = dest_render_view_host->enabled_bindings(); - bool is_allowed_in_web_ui_renderer = - WebUIFactory::IsURLAcceptableForWebUI(profile(), entry.url()); - CHECK(!BindingsPolicy::is_web_ui_enabled(enabled_bindings) || - is_allowed_in_web_ui_renderer); - - // Tell DevTools agent that it is attached prior to the navigation. - DevToolsManager* devtools_manager = DevToolsManager::GetInstance(); - if (devtools_manager) { // NULL in unit tests. - devtools_manager->OnNavigatingToPendingEntry(render_view_host(), - dest_render_view_host, - entry.url()); - } - - // Used for page load time metrics. - current_load_start_ = base::TimeTicks::Now(); - - // Navigate in the desired RenderViewHost. - ViewMsg_Navigate_Params navigate_params; - MakeNavigateParams(entry, controller_, reload_type, &navigate_params); - if (delegate_) { - navigate_params.extra_headers = - delegate_->GetNavigationHeaders(navigate_params.url); - } - dest_render_view_host->Navigate(navigate_params); - - if (entry.page_id() == -1) { - // HACK!! This code suppresses javascript: URLs from being added to - // session history, which is what we want to do for javascript: URLs that - // do not generate content. What we really need is a message from the - // renderer telling us that a new page was not created. The same message - // could be used for mailto: URLs and the like. - if (entry.url().SchemeIs(chrome::kJavaScriptScheme)) - return false; - } - - // Notify observers about navigation. - FOR_EACH_OBSERVER(TabContentsObserver, observers_, NavigateToPendingEntry()); - - if (reload_type != NavigationController::NO_RELOAD && - !profile()->IsOffTheRecord()) { - FaviconService* favicon_service = - profile()->GetFaviconService(Profile::IMPLICIT_ACCESS); - if (favicon_service) - favicon_service->SetFaviconOutOfDateForPage(entry.url()); - } - - return true; -} - -void TabContents::Stop() { - render_manager_.Stop(); - printing_->Stop(); -} - -void TabContents::DisassociateFromPopupCount() { - render_view_host()->DisassociateFromPopupCount(); -} - -TabContents* TabContents::Clone() { - // We create a new SiteInstance so that the new tab won't share processes - // with the old one. This can be changed in the future if we need it to share - // processes for some reason. - TabContents* tc = new TabContents(profile(), - SiteInstance::CreateSiteInstance(profile()), - MSG_ROUTING_NONE, this, NULL); - tc->controller().CopyStateFrom(controller_); - tc->extension_app_ = extension_app_; - tc->extension_app_icon_ = extension_app_icon_; - return tc; -} - -void TabContents::ShowPageInfo(const GURL& url, - const NavigationEntry::SSLStatus& ssl, - bool show_history) { - if (!delegate_) - return; - - delegate_->ShowPageInfo(profile(), url, ssl, show_history); -} - -void TabContents::SaveFavicon() { - NavigationEntry* entry = controller_.GetActiveEntry(); - if (!entry || entry->url().is_empty()) - return; - - // Make sure the page is in history, otherwise adding the favicon does - // nothing. - HistoryService* history = profile()->GetOriginalProfile()->GetHistoryService( - Profile::IMPLICIT_ACCESS); - if (!history) - return; - history->AddPageNoVisitForBookmark(entry->url()); - - FaviconService* service = profile()->GetOriginalProfile()->GetFaviconService( - Profile::IMPLICIT_ACCESS); - if (!service) - return; - const NavigationEntry::FaviconStatus& favicon(entry->favicon()); - if (!favicon.is_valid() || favicon.url().is_empty() || - favicon.bitmap().empty()) { - return; - } - std::vector<unsigned char> image_data; - gfx::PNGCodec::EncodeBGRASkBitmap(favicon.bitmap(), false, &image_data); - service->SetFavicon(entry->url(), favicon.url(), image_data); -} - -ConstrainedWindow* TabContents::CreateConstrainedDialog( - ConstrainedWindowDelegate* delegate) { - ConstrainedWindow* window = - ConstrainedWindow::CreateConstrainedDialog(this, delegate); - child_windows_.push_back(window); - - if (child_windows_.size() == 1) { - window->ShowConstrainedWindow(); - BlockTabContent(true); - } - - return window; -} - -void TabContents::BlockTabContent(bool blocked) { - RenderWidgetHostView* rwhv = GetRenderWidgetHostView(); - // 70% opaque grey. - SkColor greyish = SkColorSetARGB(178, 0, 0, 0); - if (rwhv) - rwhv->SetVisuallyDeemphasized(blocked ? &greyish : NULL, false); - render_view_host()->set_ignore_input_events(blocked); - if (delegate_) - delegate_->SetTabContentBlocked(this, blocked); -} - -void TabContents::AddNewContents(TabContents* new_contents, - WindowOpenDisposition disposition, - const gfx::Rect& initial_pos, - bool user_gesture) { - if (all_contents_blocked_) { - if (!blocked_contents_) - blocked_contents_ = new BlockedContentContainer(this); - blocked_contents_->AddTabContents( - new_contents, disposition, initial_pos, user_gesture); - return; - } - - if (!delegate_) - return; - - if ((disposition == NEW_POPUP) && !user_gesture && - !CommandLine::ForCurrentProcess()->HasSwitch( - switches::kDisablePopupBlocking)) { - // Unrequested popups from normal pages are constrained unless they're in - // the whitelist. The popup owner will handle checking this. - delegate_->GetConstrainingContents(this)->AddPopup( - new_contents, initial_pos); - } else { - new_contents->DisassociateFromPopupCount(); - delegate_->AddNewContents(this, new_contents, disposition, initial_pos, - user_gesture); - NotificationService::current()->Notify( - NotificationType::TAB_ADDED, - Source<TabContentsDelegate>(delegate_), - Details<TabContents>(this)); - } - - // TODO(pkasting): Why is this necessary? - PopupNotificationVisibilityChanged(blocked_contents_ != NULL); -} - -bool TabContents::ExecuteCode(int request_id, const std::string& extension_id, - bool is_js_code, const std::string& code_string, - bool all_frames) { - RenderViewHost* host = render_view_host(); - if (!host) - return false; - - return host->Send(new ViewMsg_ExecuteCode(host->routing_id(), - ViewMsg_ExecuteCode_Params(request_id, extension_id, - is_js_code, code_string, all_frames))); -} - -void TabContents::PopupNotificationVisibilityChanged(bool visible) { - if (is_being_destroyed_) - return; - content_settings_delegate_->SetPopupsBlocked(visible); - if (!dont_notify_render_view_) - render_view_host()->AllowScriptToClose(!visible); -} - -gfx::NativeView TabContents::GetContentNativeView() const { - return view_->GetContentNativeView(); -} - -gfx::NativeView TabContents::GetNativeView() const { - return view_->GetNativeView(); -} - -void TabContents::GetContainerBounds(gfx::Rect *out) const { - view_->GetContainerBounds(out); -} - -void TabContents::Focus() { - view_->Focus(); -} - -void TabContents::FocusThroughTabTraversal(bool reverse) { - if (showing_interstitial_page()) { - render_manager_.interstitial_page()->FocusThroughTabTraversal(reverse); - return; - } - render_view_host()->SetInitialFocus(reverse); -} - -bool TabContents::FocusLocationBarByDefault() { - WebUI* web_ui = GetWebUIForCurrentState(); - if (web_ui) - return web_ui->focus_location_bar_by_default(); - NavigationEntry* entry = controller_.GetActiveEntry(); - if (entry && entry->url() == GURL(chrome::kAboutBlankURL)) - return true; - return false; -} - -void TabContents::SetFocusToLocationBar(bool select_all) { - if (delegate()) - delegate()->SetFocusToLocationBar(select_all); -} - -void TabContents::AddInfoBar(InfoBarDelegate* delegate) { - if (delegate_ && !delegate_->infobars_enabled()) { - delegate->InfoBarClosed(); - return; - } - - // Look through the existing InfoBarDelegates we have for a match. If we've - // already got one that matches, then we don't add the new one. - for (size_t i = 0; i < infobar_count(); ++i) { - if (GetInfoBarDelegateAt(i)->EqualsDelegate(delegate)) { - // Tell the new infobar to close so that it can clean itself up. - delegate->InfoBarClosed(); - return; - } - } - - infobar_delegates_.push_back(delegate); - NotificationService::current()->Notify( - NotificationType::TAB_CONTENTS_INFOBAR_ADDED, Source<TabContents>(this), - Details<InfoBarDelegate>(delegate)); - - // Add ourselves as an observer for navigations the first time a delegate is - // added. We use this notification to expire InfoBars that need to expire on - // page transitions. - if (infobar_delegates_.size() == 1) { - registrar_.Add(this, NotificationType::NAV_ENTRY_COMMITTED, - Source<NavigationController>(&controller_)); - } -} - -void TabContents::RemoveInfoBar(InfoBarDelegate* delegate) { - if (delegate_ && !delegate_->infobars_enabled()) { - return; - } - - std::vector<InfoBarDelegate*>::iterator it = - find(infobar_delegates_.begin(), infobar_delegates_.end(), delegate); - if (it != infobar_delegates_.end()) { - InfoBarDelegate* delegate = *it; - NotificationService::current()->Notify( - NotificationType::TAB_CONTENTS_INFOBAR_REMOVED, - Source<TabContents>(this), - Details<InfoBarDelegate>(delegate)); - - infobar_delegates_.erase(it); - // Remove ourselves as an observer if we are tracking no more InfoBars. - if (infobar_delegates_.empty()) { - registrar_.Remove(this, NotificationType::NAV_ENTRY_COMMITTED, - Source<NavigationController>(&controller_)); - } - } -} - -void TabContents::ReplaceInfoBar(InfoBarDelegate* old_delegate, - InfoBarDelegate* new_delegate) { - if (delegate_ && !delegate_->infobars_enabled()) { - new_delegate->InfoBarClosed(); - return; - } - - std::vector<InfoBarDelegate*>::iterator it = - find(infobar_delegates_.begin(), infobar_delegates_.end(), old_delegate); - DCHECK(it != infobar_delegates_.end()); - - // Notify the container about the change of plans. - scoped_ptr<std::pair<InfoBarDelegate*, InfoBarDelegate*> > details( - new std::pair<InfoBarDelegate*, InfoBarDelegate*>( - old_delegate, new_delegate)); - NotificationService::current()->Notify( - NotificationType::TAB_CONTENTS_INFOBAR_REPLACED, - Source<TabContents>(this), - Details<std::pair<InfoBarDelegate*, InfoBarDelegate*> >(details.get())); - - // Remove the old one. - infobar_delegates_.erase(it); - - // Add the new one. - DCHECK(find(infobar_delegates_.begin(), - infobar_delegates_.end(), new_delegate) == - infobar_delegates_.end()); - infobar_delegates_.push_back(new_delegate); -} - -bool TabContents::ShouldShowBookmarkBar() { - if (showing_interstitial_page()) - return false; - - // Do not show bookmarks bar if bookmarks aren't enabled. - if (!browser_defaults::bookmarks_enabled) - return false; - - // See GetWebUIForCurrentState() comment for more info. This case is very - // similar, but for non-first loads, we want to use the committed entry. This - // is so the bookmarks bar disappears at the same time the page does. - if (controller_.GetLastCommittedEntry()) { - // Not the first load, always use the committed Web UI. - return (render_manager_.web_ui() == NULL) ? - false : render_manager_.web_ui()->force_bookmark_bar_visible(); - } - - // When it's the first load, we know either the pending one or the committed - // one will have the Web UI in it (see GetWebUIForCurrentState), and only one - // of them will be valid, so we can just check both. - if (render_manager_.pending_web_ui()) - return render_manager_.pending_web_ui()->force_bookmark_bar_visible(); - return (render_manager_.web_ui() == NULL) ? - false : render_manager_.web_ui()->force_bookmark_bar_visible(); -} - -void TabContents::ToolbarSizeChanged(bool is_animating) { - TabContentsDelegate* d = delegate(); - if (d) - d->ToolbarSizeChanged(this, is_animating); -} - -bool TabContents::CanDownload(int request_id) { - TabContentsDelegate* d = delegate(); - if (d) - return d->CanDownload(request_id); - return true; -} - -void TabContents::OnStartDownload(DownloadItem* download) { - DCHECK(download); - - // Download in a constrained popup is shown in the tab that opened it. - TabContents* tab_contents = delegate()->GetConstrainingContents(this); - - if (tab_contents && tab_contents->delegate()) - tab_contents->delegate()->OnStartDownload(download, this); -} - -void TabContents::WillClose(ConstrainedWindow* window) { - ConstrainedWindowList::iterator i( - std::find(child_windows_.begin(), child_windows_.end(), window)); - bool removed_topmost_window = i == child_windows_.begin(); - if (i != child_windows_.end()) - child_windows_.erase(i); - if (child_windows_.empty()) { - BlockTabContent(false); - } else { - if (removed_topmost_window) - child_windows_[0]->ShowConstrainedWindow(); - BlockTabContent(true); - } -} - -void TabContents::WillCloseBlockedContentContainer( - BlockedContentContainer* container) { - DCHECK(blocked_contents_ == container); - blocked_contents_ = NULL; - PopupNotificationVisibilityChanged(false); -} - -void TabContents::DidMoveOrResize(ConstrainedWindow* window) { -#if defined(OS_WIN) - UpdateWindow(GetNativeView()); -#endif -} - -void TabContents::OnSavePage() { - // If we can not save the page, try to download it. - if (!SavePackage::IsSavableContents(contents_mime_type())) { - DownloadManager* dlm = profile()->GetDownloadManager(); - const GURL& current_page_url = GetURL(); - if (dlm && current_page_url.is_valid()) - dlm->DownloadUrl(current_page_url, GURL(), "", this); - return; - } - - Stop(); - - // Create the save package and possibly prompt the user for the name to save - // the page as. The user prompt is an asynchronous operation that runs on - // another thread. - save_package_ = new SavePackage(this); - save_package_->GetSaveInfo(); -} - -// Used in automated testing to bypass prompting the user for file names. -// Instead, the names and paths are hard coded rather than running them through -// file name sanitation and extension / mime checking. -bool TabContents::SavePage(const FilePath& main_file, const FilePath& dir_path, - SavePackage::SavePackageType save_type) { - // Stop the page from navigating. - Stop(); - - save_package_ = new SavePackage(this, save_type, main_file, dir_path); - return save_package_->Init(); -} - -void TabContents::EmailPageLocation() { - std::string title = EscapeQueryParamValue(UTF16ToUTF8(GetTitle()), false); - std::string page_url = EscapeQueryParamValue(GetURL().spec(), false); - std::string mailto = std::string("mailto:?subject=Fwd:%20") + - title + "&body=%0A%0A" + page_url; - platform_util::OpenExternal(GURL(mailto)); -} - -void TabContents::PrintPreview() { - if (CommandLine::ForCurrentProcess()->HasSwitch( - switches::kEnablePrintPreview)) { - if (showing_interstitial_page()) - return; - - printing::PrintPreviewTabController* tab_controller = - printing::PrintPreviewTabController::GetInstance(); - if (!tab_controller) - return; - tab_controller->GetOrCreatePreviewTab(this, controller().window_id().id()); - - render_view_host()->PrintPreview(); - } else { - PrintNow(); - } -} - -bool TabContents::PrintNow() { - // We can't print interstitial page for now. - if (showing_interstitial_page()) - return false; - - return render_view_host()->PrintPages(); -} - -void TabContents::PrintingDone(int document_cookie, bool success) { - render_view_host()->PrintingDone(document_cookie, success); -} - -bool TabContents::IsActiveEntry(int32 page_id) { - NavigationEntry* active_entry = controller_.GetActiveEntry(); - return (active_entry != NULL && - active_entry->site_instance() == GetSiteInstance() && - active_entry->page_id() == page_id); -} - -void TabContents::SetOverrideEncoding(const std::string& encoding) { - set_encoding(encoding); - render_view_host()->SetPageEncoding(encoding); -} - -void TabContents::ResetOverrideEncoding() { - reset_encoding(); - render_view_host()->ResetPageEncodingToDefault(); -} - -void TabContents::WindowMoveOrResizeStarted() { - render_view_host()->WindowMoveOrResizeStarted(); -} - -void TabContents::SetAllContentsBlocked(bool value) { - if (all_contents_blocked_ == value) - return; - - all_contents_blocked_ = value; - if (!all_contents_blocked_ && blocked_contents_) { - std::vector<TabContents*> blocked; - blocked_contents_->GetBlockedContents(&blocked); - for (size_t i = 0; i < blocked.size(); ++i) - blocked_contents_->LaunchForContents(blocked[i]); - } -} - -void TabContents::LogNewTabTime(const std::string& event_name) { - // Not all new tab pages get timed. In those cases, we don't have a - // new_tab_start_time_. - if (new_tab_start_time_.is_null()) - return; - - base::TimeDelta duration = base::TimeTicks::Now() - new_tab_start_time_; - MetricEventDurationDetails details(event_name, - static_cast<int>(duration.InMilliseconds())); - - if (event_name == "Tab.NewTabScriptStart") { - UMA_HISTOGRAM_TIMES("Tab.NewTabScriptStart", duration); - } else if (event_name == "Tab.NewTabDOMContentLoaded") { - UMA_HISTOGRAM_TIMES("Tab.NewTabDOMContentLoaded", duration); - } else if (event_name == "Tab.NewTabOnload") { - UMA_HISTOGRAM_TIMES("Tab.NewTabOnload", duration); - // The new tab page has finished loading; reset it. - new_tab_start_time_ = base::TimeTicks(); - } else { - NOTREACHED(); - } - NotificationService::current()->Notify( - NotificationType::METRIC_EVENT_DURATION, - Source<TabContents>(this), - Details<MetricEventDurationDetails>(&details)); -} - -void TabContents::OnCloseStarted() { - if (tab_close_start_time_.is_null()) - tab_close_start_time_ = base::TimeTicks::Now(); -} - -bool TabContents::ShouldAcceptDragAndDrop() const { -#if defined(OS_CHROMEOS) - // ChromeOS panels (pop-ups) do not take drag-n-drop. - // See http://crosbug.com/2413 - if (delegate() && delegate()->IsPopup(this)) - return false; - return true; -#else - return true; -#endif -} - -void TabContents::SystemDragEnded() { - if (render_view_host()) - render_view_host()->DragSourceSystemDragEnded(); - if (delegate()) - delegate()->DragEnded(); -} - -void TabContents::UpdateHistoryForNavigation( - scoped_refptr<history::HistoryAddPageArgs> add_page_args) { - if (profile()->IsOffTheRecord()) - return; - - // Add to history service. - HistoryService* hs = profile()->GetHistoryService(Profile::IMPLICIT_ACCESS); - if (hs) - hs->AddPage(*add_page_args); -} - -void TabContents::UpdateHistoryPageTitle(const NavigationEntry& entry) { - if (profile()->IsOffTheRecord()) - return; - - HistoryService* hs = profile()->GetHistoryService(Profile::IMPLICIT_ACCESS); - if (hs) - hs->SetPageTitle(entry.virtual_url(), entry.title()); -} - -double TabContents::GetZoomLevel() const { - HostZoomMap* zoom_map = profile()->GetHostZoomMap(); - if (!zoom_map) - return 0; - - double zoom_level; - if (temporary_zoom_settings_) { - zoom_level = zoom_map->GetTemporaryZoomLevel( - GetRenderProcessHost()->id(), render_view_host()->routing_id()); - } else { - zoom_level = zoom_map->GetZoomLevel(GetURL()); - } - return zoom_level; -} - -int TabContents::GetZoomPercent(bool* enable_increment, - bool* enable_decrement) { - *enable_decrement = *enable_increment = false; - int percent = static_cast<int>( - WebKit::WebView::zoomLevelToZoomFactor(GetZoomLevel()) * 100); - *enable_decrement = percent > minimum_zoom_percent_; - *enable_increment = percent < maximum_zoom_percent_; - return percent; -} - -void TabContents::ViewSource() { - if (!delegate_) - return; - - NavigationEntry* active_entry = controller().GetActiveEntry(); - if (!active_entry) - return; - - delegate_->ViewSourceForTab(this, active_entry->url()); -} - -void TabContents::OnDidStartProvisionalLoadForFrame(int64 frame_id, - bool is_main_frame, - const GURL& url) { - bool is_error_page = (url.spec() == chrome::kUnreachableWebDataURL); - GURL validated_url(url); - render_view_host()->FilterURL(ChildProcessSecurityPolicy::GetInstance(), - GetRenderProcessHost()->id(), &validated_url); - - ProvisionalLoadDetails details( - is_main_frame, - controller_.IsURLInPageNavigation(validated_url), - validated_url, std::string(), false, is_error_page, frame_id); - NotificationService::current()->Notify( - NotificationType::FRAME_PROVISIONAL_LOAD_START, - Source<NavigationController>(&controller_), - Details<ProvisionalLoadDetails>(&details)); - if (is_main_frame) { - // If we're displaying a network error page do not reset the content - // settings delegate's cookies so the user has a chance to modify cookie - // settings. - if (!is_error_page) - content_settings_delegate_->ClearCookieSpecificContentSettings(); - content_settings_delegate_->ClearGeolocationContentSettings(); - - // Check if the URL we are about to load has been prerendered by any chance, - // and use it if possible. - MaybeUsePreloadedPage(url); - } -} - -void TabContents::OnDidRedirectProvisionalLoad(int32 page_id, - const GURL& source_url, - const GURL& target_url) { - NavigationEntry* entry; - if (page_id == -1) - entry = controller_.pending_entry(); - else - entry = controller_.GetEntryWithPageID(GetSiteInstance(), page_id); - if (!entry || entry->url() != source_url) - return; - entry->set_url(target_url); - - // Check if the URL we are about to load has been prerendered by any chance, - // and use it if possible. - MaybeUsePreloadedPage(target_url); -} - -void TabContents::OnDidFailProvisionalLoadWithError( - int64 frame_id, - bool is_main_frame, - int error_code, - const GURL& url, - bool showing_repost_interstitial) { - VLOG(1) << "Failed Provisional Load: " << url.possibly_invalid_spec() - << ", error_code: " << error_code - << " is_main_frame: " << is_main_frame - << " showing_repost_interstitial: " << showing_repost_interstitial - << " frame_id: " << frame_id; - GURL validated_url(url); - render_view_host()->FilterURL(ChildProcessSecurityPolicy::GetInstance(), - GetRenderProcessHost()->id(), &validated_url); - - if (net::ERR_ABORTED == error_code) { - // EVIL HACK ALERT! Ignore failed loads when we're showing interstitials. - // This means that the interstitial won't be torn down properly, which is - // bad. But if we have an interstitial, go back to another tab type, and - // then load the same interstitial again, we could end up getting the first - // interstitial's "failed" message (as a result of the cancel) when we're on - // the second one. - // - // We can't tell this apart, so we think we're tearing down the current page - // which will cause a crash later one. There is also some code in - // RenderViewHostManager::RendererAbortedProvisionalLoad that is commented - // out because of this problem. - // - // http://code.google.com/p/chromium/issues/detail?id=2855 - // Because this will not tear down the interstitial properly, if "back" is - // back to another tab type, the interstitial will still be somewhat alive - // in the previous tab type. If you navigate somewhere that activates the - // tab with the interstitial again, you'll see a flash before the new load - // commits of the interstitial page. - if (showing_interstitial_page()) { - LOG(WARNING) << "Discarding message during interstitial."; - return; - } - - // This will discard our pending entry if we cancelled the load (e.g., if we - // decided to download the file instead of load it). Only discard the - // pending entry if the URLs match, otherwise the user initiated a navigate - // before the page loaded so that the discard would discard the wrong entry. - NavigationEntry* pending_entry = controller_.pending_entry(); - if (pending_entry && pending_entry->url() == validated_url) { - controller_.DiscardNonCommittedEntries(); - // Update the URL display. - NotifyNavigationStateChanged(TabContents::INVALIDATE_URL); - } - - render_manager_.RendererAbortedProvisionalLoad(render_view_host()); - } - - // Send out a notification that we failed a provisional load with an error. - ProvisionalLoadDetails details( - is_main_frame, controller_.IsURLInPageNavigation(validated_url), - validated_url, std::string(), false, false, frame_id); - details.set_error_code(error_code); - - NotificationService::current()->Notify( - NotificationType::FAIL_PROVISIONAL_LOAD_WITH_ERROR, - Source<NavigationController>(&controller_), - Details<ProvisionalLoadDetails>(&details)); -} - -void TabContents::OnDidLoadResourceFromMemoryCache( - const GURL& url, - const std::string& security_info) { - static base::StatsCounter cache("WebKit.CacheHit"); - cache.Increment(); - - // Send out a notification that we loaded a resource from our memory cache. - int cert_id = 0, cert_status = 0, security_bits = -1, connection_status = 0; - SSLManager::DeserializeSecurityInfo(security_info, - &cert_id, &cert_status, - &security_bits, - &connection_status); - LoadFromMemoryCacheDetails details(url, GetRenderProcessHost()->id(), - cert_id, cert_status); - - NotificationService::current()->Notify( - NotificationType::LOAD_FROM_MEMORY_CACHE, - Source<NavigationController>(&controller_), - Details<LoadFromMemoryCacheDetails>(&details)); -} - -void TabContents::OnDidDisplayInsecureContent() { - displayed_insecure_content_ = true; - SSLManager::NotifySSLInternalStateChanged(); -} - -void TabContents::OnDidRunInsecureContent( - const std::string& security_origin, const GURL& target_url) { - LOG(INFO) << security_origin << " ran insecure content from " - << target_url.possibly_invalid_spec(); - controller_.ssl_manager()->DidRunInsecureContent(security_origin); -} - -void TabContents::OnDocumentLoadedInFrame(int64 frame_id) { - controller_.DocumentLoadedInFrame(); - NotificationService::current()->Notify( - NotificationType::FRAME_DOM_CONTENT_LOADED, - Source<NavigationController>(&controller_), - Details<int64>(&frame_id)); -} - -void TabContents::OnDidFinishLoad(int64 frame_id) { - NotificationService::current()->Notify( - NotificationType::FRAME_DID_FINISH_LOAD, - Source<NavigationController>(&controller_), - Details<int64>(&frame_id)); -} - -void TabContents::OnUpdateContentRestrictions(int restrictions) { - content_restrictions_ = restrictions; - delegate()->ContentRestrictionsChanged(this); -} - -void TabContents::OnPDFHasUnsupportedFeature() { - PDFHasUnsupportedFeature(this); -} - -// Notifies the RenderWidgetHost instance about the fact that the page is -// loading, or done loading and calls the base implementation. -void TabContents::SetIsLoading(bool is_loading, - LoadNotificationDetails* details) { - if (is_loading == is_loading_) - return; - - if (!is_loading) { - load_state_ = net::LOAD_STATE_IDLE; - load_state_host_.clear(); - upload_size_ = 0; - upload_position_ = 0; - } - - render_manager_.SetIsLoading(is_loading); - - is_loading_ = is_loading; - waiting_for_response_ = is_loading; - - if (delegate_) - delegate_->LoadingStateChanged(this); - NotifyNavigationStateChanged(INVALIDATE_LOAD); - - NotificationType type = is_loading ? NotificationType::LOAD_START : - NotificationType::LOAD_STOP; - NotificationDetails det = NotificationService::NoDetails(); - if (details) - det = Details<LoadNotificationDetails>(details); - NotificationService::current()->Notify(type, - Source<NavigationController>(&controller_), - det); -} - -void TabContents::AddPopup(TabContents* new_contents, - const gfx::Rect& initial_pos) { - // A page can't spawn popups (or do anything else, either) until its load - // commits, so when we reach here, the popup was spawned by the - // NavigationController's last committed entry, not the active entry. For - // example, if a page opens a popup in an onunload() handler, then the active - // entry is the page to be loaded as we navigate away from the unloading - // page. For this reason, we can't use GetURL() to get the opener URL, - // because it returns the active entry. - NavigationEntry* entry = controller_.GetLastCommittedEntry(); - GURL creator = entry ? entry->virtual_url() : GURL::EmptyGURL(); - - if (creator.is_valid() && - profile()->GetHostContentSettingsMap()->GetContentSetting( - creator, CONTENT_SETTINGS_TYPE_POPUPS, "") == CONTENT_SETTING_ALLOW) { - AddNewContents(new_contents, NEW_POPUP, initial_pos, true); - } else { - if (!blocked_contents_) - blocked_contents_ = new BlockedContentContainer(this); - blocked_contents_->AddTabContents(new_contents, NEW_POPUP, initial_pos, - true); - content_settings_delegate_->OnContentBlocked(CONTENT_SETTINGS_TYPE_POPUPS, - std::string()); - } -} - -void TabContents::ExpireInfoBars( - const NavigationController::LoadCommittedDetails& details) { - // Only hide InfoBars when the user has done something that makes the main - // frame load. We don't want various automatic or subframe navigations making - // it disappear. - if (!details.is_user_initiated_main_frame_load()) - return; - - // NOTE: It is not safe to change the following code to count upwards or use - // iterators, as the RemoveInfoBar() call synchronously modifies our delegate - // list. - for (size_t i = infobar_count(); i > 0; --i) { - InfoBarDelegate* delegate = GetInfoBarDelegateAt(i - 1); - if (delegate->ShouldExpire(details)) - RemoveInfoBar(delegate); - } -} - -WebUI* TabContents::GetWebUIForCurrentState() { - // When there is a pending navigation entry, we want to use the pending WebUI - // that goes along with it to control the basic flags. For example, we want to - // show the pending URL in the URL bar, so we want the display_url flag to - // be from the pending entry. - // - // The confusion comes because there are multiple possibilities for the - // initial load in a tab as a side effect of the way the RenderViewHostManager - // works. - // - // - For the very first tab the load looks "normal". The new tab Web UI is - // the pending one, and we want it to apply here. - // - // - For subsequent new tabs, they'll get a new SiteInstance which will then - // get switched to the one previously associated with the new tab pages. - // This switching will cause the manager to commit the RVH/WebUI. So we'll - // have a committed Web UI in this case. - // - // This condition handles all of these cases: - // - // - First load in first tab: no committed nav entry + pending nav entry + - // pending dom ui: - // -> Use pending Web UI if any. - // - // - First load in second tab: no committed nav entry + pending nav entry + - // no pending Web UI: - // -> Use the committed Web UI if any. - // - // - Second navigation in any tab: committed nav entry + pending nav entry: - // -> Use pending Web UI if any. - // - // - Normal state with no load: committed nav entry + no pending nav entry: - // -> Use committed Web UI. - if (controller_.pending_entry() && - (controller_.GetLastCommittedEntry() || - render_manager_.pending_web_ui())) - return render_manager_.pending_web_ui(); - return render_manager_.web_ui(); -} - -void TabContents::DidNavigateMainFramePostCommit( - const NavigationController::LoadCommittedDetails& details, - const ViewHostMsg_FrameNavigate_Params& params) { - if (opener_web_ui_type_ != WebUIFactory::kNoWebUI) { - // If this is a window.open navigation, use the same WebUI as the renderer - // that opened the window, as long as both renderers have the same - // privileges. - if (opener_web_ui_type_ == - WebUIFactory::GetWebUIType(profile(), GetURL())) { - WebUI* web_ui = WebUIFactory::CreateWebUIForURL(this, GetURL()); - // web_ui might be NULL if the URL refers to a non-existent extension. - if (web_ui) { - render_manager_.SetWebUIPostCommit(web_ui); - web_ui->RenderViewCreated(render_view_host()); - } - } - opener_web_ui_type_ = WebUIFactory::kNoWebUI; - } - - if (details.is_user_initiated_main_frame_load()) { - // Clear the status bubble. This is a workaround for a bug where WebKit - // doesn't let us know that the cursor left an element during a - // transition (this is also why the mouse cursor remains as a hand after - // clicking on a link); see bugs 1184641 and 980803. We don't want to - // clear the bubble when a user navigates to a named anchor in the same - // page. - UpdateTargetURL(details.entry->page_id(), GURL()); - } - - // Allow the new page to set the title again. - received_page_title_ = false; - - // Get the favicon, either from history or request it from the net. - fav_icon_helper_->FetchFavIcon(details.entry->url()); - - // Clear all page actions, blocked content notifications and browser actions - // for this tab, unless this is an in-page navigation. - if (!details.is_in_page) { - ExtensionService* service = profile()->GetExtensionService(); - if (service) { - for (size_t i = 0; i < service->extensions()->size(); ++i) { - ExtensionAction* browser_action = - service->extensions()->at(i)->browser_action(); - if (browser_action) { - browser_action->ClearAllValuesForTab(controller().session_id().id()); - NotificationService::current()->Notify( - NotificationType::EXTENSION_BROWSER_ACTION_UPDATED, - Source<ExtensionAction>(browser_action), - NotificationService::NoDetails()); - } - - ExtensionAction* page_action = - service->extensions()->at(i)->page_action(); - if (page_action) { - page_action->ClearAllValuesForTab(controller().session_id().id()); - PageActionStateChanged(); - } - } - } - - // Close blocked popups. - if (blocked_contents_) { - AutoReset<bool> auto_reset(&dont_notify_render_view_, true); - blocked_contents_->Destroy(); - blocked_contents_ = NULL; - } - - // Clear "blocked" flags. - content_settings_delegate_->ClearBlockedContentSettingsExceptForCookies(); - content_settings_delegate_->GeolocationDidNavigate(details); - - // Once the main frame is navigated, we're no longer considered to have - // displayed insecure content. - displayed_insecure_content_ = false; - } - - // Close constrained windows if necessary. - if (!net::RegistryControlledDomainService::SameDomainOrHost( - details.previous_url, details.entry->url())) - CloseConstrainedWindows(); - - // Notify observers about navigation. - FOR_EACH_OBSERVER(TabContentsObserver, observers_, - DidNavigateMainFramePostCommit(details, params)); -} - -void TabContents::DidNavigateAnyFramePostCommit( - RenderViewHost* render_view_host, - const NavigationController::LoadCommittedDetails& details, - const ViewHostMsg_FrameNavigate_Params& params) { - // If we navigate, start showing messages again. This does nothing to prevent - // a malicious script from spamming messages, since the script could just - // reload the page to stop blocking. - suppress_javascript_messages_ = false; - - // Notify observers about navigation. - FOR_EACH_OBSERVER(TabContentsObserver, observers_, - DidNavigateAnyFramePostCommit(details, params)); - - // Let the LanguageState clear its state. - language_state_.DidNavigate(details); -} - -void TabContents::CloseConstrainedWindows() { - // Clear out any constrained windows since we are leaving this page entirely. - // We use indices instead of iterators in case CloseWindow does something - // that may invalidate an iterator. - for (size_t i = 0; i < child_windows_.size(); ++i) { - ConstrainedWindow* window = child_windows_[child_windows_.size() - 1 - i]; - if (window) { - window->CloseConstrainedWindow(); - BlockTabContent(false); - } - } -} - -void TabContents::UpdateAlternateErrorPageURL() { - GURL url = GetAlternateErrorPageURL(); - render_view_host()->SetAlternateErrorPageURL(url); -} - -void TabContents::UpdateWebPreferences() { - render_view_host()->UpdateWebPreferences(GetWebkitPrefs()); -} - -void TabContents::UpdateZoomLevel() { - render_view_host()->SetZoomLevel(GetZoomLevel()); -} - -void TabContents::UpdateMaxPageIDIfNecessary(SiteInstance* site_instance, - RenderViewHost* rvh) { - // If we are creating a RVH for a restored controller, then we might - // have more page IDs than the SiteInstance's current max page ID. We must - // make sure that the max page ID is larger than any restored page ID. - // Note that it is ok for conflicting page IDs to exist in another tab - // (i.e., NavigationController), but if any page ID is larger than the max, - // the back/forward list will get confused. - int max_restored_page_id = controller_.max_restored_page_id(); - if (max_restored_page_id > 0) { - int curr_max_page_id = site_instance->max_page_id(); - if (max_restored_page_id > curr_max_page_id) { - // Need to update the site instance immediately. - site_instance->UpdateMaxPageID(max_restored_page_id); - - // Also tell the renderer to update its internal representation. We - // need to reserve enough IDs to make all restored page IDs less than - // the max. - if (curr_max_page_id < 0) - curr_max_page_id = 0; - rvh->ReservePageIDRange(max_restored_page_id - curr_max_page_id); - } - } -} - -scoped_refptr<history::HistoryAddPageArgs> -TabContents::CreateHistoryAddPageArgs( - const GURL& virtual_url, - const NavigationController::LoadCommittedDetails& details, - const ViewHostMsg_FrameNavigate_Params& params) { - scoped_refptr<history::HistoryAddPageArgs> add_page_args( - new history::HistoryAddPageArgs( - params.url, base::Time::Now(), this, params.page_id, params.referrer, - params.redirects, params.transition, history::SOURCE_BROWSED, - details.did_replace_entry)); - if (PageTransition::IsMainFrame(params.transition) && - virtual_url != params.url) { - // Hack on the "virtual" URL so that it will appear in history. For some - // types of URLs, we will display a magic URL that is different from where - // the page is actually navigated. We want the user to see in history what - // they saw in the URL bar, so we add the virtual URL as a redirect. This - // only applies to the main frame, as the virtual URL doesn't apply to - // sub-frames. - add_page_args->url = virtual_url; - if (!add_page_args->redirects.empty()) - add_page_args->redirects.back() = virtual_url; - } - return add_page_args; -} - -bool TabContents::UpdateTitleForEntry(NavigationEntry* entry, - const std::wstring& title) { - // For file URLs without a title, use the pathname instead. In the case of a - // synthesized title, we don't want the update to count toward the "one set - // per page of the title to history." - string16 final_title; - bool explicit_set; - if (entry->url().SchemeIsFile() && title.empty()) { - final_title = UTF8ToUTF16(entry->url().ExtractFileName()); - explicit_set = false; // Don't count synthetic titles toward the set limit. - } else { - TrimWhitespace(WideToUTF16Hack(title), TRIM_ALL, &final_title); - explicit_set = true; - } - - if (final_title == entry->title()) - return false; // Nothing changed, don't bother. - - entry->set_title(final_title); - - if (!received_page_title_) { - UpdateHistoryPageTitle(*entry); - received_page_title_ = explicit_set; - } - - // Lastly, set the title for the view. - view_->SetPageTitle(UTF16ToWideHack(final_title)); - - NotificationService::current()->Notify( - NotificationType::TAB_CONTENTS_TITLE_UPDATED, - Source<TabContents>(this), - NotificationService::NoDetails()); - - return true; -} - -void TabContents::NotifySwapped() { - // After sending out a swap notification, we need to send a disconnect - // notification so that clients that pick up a pointer to |this| can NULL the - // pointer. See Bug 1230284. - notify_disconnection_ = true; - NotificationService::current()->Notify( - NotificationType::TAB_CONTENTS_SWAPPED, - Source<TabContents>(this), - NotificationService::NoDetails()); -} - -void TabContents::NotifyConnected() { - notify_disconnection_ = true; - NotificationService::current()->Notify( - NotificationType::TAB_CONTENTS_CONNECTED, - Source<TabContents>(this), - NotificationService::NoDetails()); -} - -void TabContents::NotifyDisconnected() { - if (!notify_disconnection_) - return; - - notify_disconnection_ = false; - NotificationService::current()->Notify( - NotificationType::TAB_CONTENTS_DISCONNECTED, - Source<TabContents>(this), - NotificationService::NoDetails()); -} - -void TabContents::OnGoToEntryAtOffset(int offset) { - if (!delegate_ || delegate_->OnGoToEntryOffset(offset)) { - NavigationEntry* entry = controller_.GetEntryAtOffset(offset); - if (!entry) - return; - // Note that we don't call NavigationController::GotToOffset() as we don't - // want to create a pending navigation entry (it might end up lingering - // http://crbug.com/51680). - entry->set_transition_type(entry->transition_type() | - PageTransition::FORWARD_BACK); - NavigateToEntry(*entry, NavigationController::NO_RELOAD); - } -} - -void TabContents::OnDidGetApplicationInfo(int32 page_id, - const WebApplicationInfo& info) { - web_app_info_ = info; - - if (delegate()) - delegate()->OnDidGetApplicationInfo(this, page_id); -} - -void TabContents::OnInstallApplication(const WebApplicationInfo& info) { - if (delegate()) - delegate()->OnInstallApplication(this, info); -} - -void TabContents::OnPageContents(const GURL& url, - int32 page_id, - const string16& contents, - const std::string& language, - bool page_translatable) { - // Don't index any https pages. People generally don't want their bank - // accounts, etc. indexed on their computer, especially since some of these - // things are not marked cachable. - // TODO(brettw) we may want to consider more elaborate heuristics such as - // the cachability of the page. We may also want to consider subframes (this - // test will still index subframes if the subframe is SSL). - // TODO(zelidrag) bug chromium-os:2808 - figure out if we want to reenable - // content indexing for chromeos in some future releases. -#if !defined(OS_CHROMEOS) - if (!url.SchemeIsSecure()) { - Profile* p = profile(); - if (p && !p->IsOffTheRecord()) { - HistoryService* hs = p->GetHistoryService(Profile::IMPLICIT_ACCESS); - if (hs) - hs->SetPageContents(url, contents); - } - } -#endif - - language_state_.LanguageDetermined(language, page_translatable); - - std::string lang = language; - NotificationService::current()->Notify( - NotificationType::TAB_LANGUAGE_DETERMINED, - Source<TabContents>(this), - Details<std::string>(&lang)); - - // Generate the thumbnail here if the in-browser thumbnailing is enabled. - if (CommandLine::ForCurrentProcess()->HasSwitch( - switches::kEnableInBrowserThumbnailing)) { - ThumbnailGenerator::UpdateThumbnailIfNecessary(this, url); - } -} - -void TabContents::OnPageTranslated(int32 page_id, - const std::string& original_lang, - const std::string& translated_lang, - TranslateErrors::Type error_type) { - language_state_.set_current_language(translated_lang); - language_state_.set_translation_pending(false); - PageTranslatedDetails details(original_lang, translated_lang, error_type); - NotificationService::current()->Notify( - NotificationType::PAGE_TRANSLATED, - Source<TabContents>(this), - Details<PageTranslatedDetails>(&details)); -} - -void TabContents::OnSetSuggestions( - int32 page_id, - const std::vector<std::string>& suggestions) { - if (delegate()) - delegate()->OnSetSuggestions(page_id, suggestions); -} - -void TabContents::OnInstantSupportDetermined(int32 page_id, bool result) { - if (delegate()) - delegate()->OnInstantSupportDetermined(page_id, result); -} - -void TabContents::OnRunFileChooser( - const ViewHostMsg_RunFileChooser_Params& params) { - if (file_select_helper_.get() == NULL) - file_select_helper_.reset(new FileSelectHelper(profile())); - file_select_helper_->RunFileChooser(render_view_host(), params); -} - - -void TabContents::OnContentSettingsAccessed(bool content_was_blocked) { - if (delegate_) - delegate_->OnContentSettingsChange(this); -} - -RenderViewHostDelegate::View* TabContents::GetViewDelegate() { - return view_.get(); -} - -RenderViewHostDelegate::RendererManagement* -TabContents::GetRendererManagementDelegate() { - return &render_manager_; -} - -RenderViewHostDelegate::ContentSettings* -TabContents::GetContentSettingsDelegate() { - return content_settings_delegate_.get(); -} - -RenderViewHostDelegate::SSL* TabContents::GetSSLDelegate() { - return GetSSLHelper(); -} - -AutomationResourceRoutingDelegate* -TabContents::GetAutomationResourceRoutingDelegate() { - return delegate(); -} - -RenderViewHostDelegate::BookmarkDrag* TabContents::GetBookmarkDragDelegate() { - return bookmark_drag_; -} - -void TabContents::SetBookmarkDragDelegate( - RenderViewHostDelegate::BookmarkDrag* bookmark_drag) { - bookmark_drag_ = bookmark_drag; -} - -TabSpecificContentSettings* TabContents::GetTabSpecificContentSettings() const { - return content_settings_delegate_.get(); -} - -RendererPreferences TabContents::GetRendererPrefs(Profile* profile) const { - return renderer_preferences_; -} - -TabContents* TabContents::GetAsTabContents() { - return this; -} - -ViewType::Type TabContents::GetRenderViewType() const { - return ViewType::TAB_CONTENTS; -} - -int TabContents::GetBrowserWindowID() const { - return controller().window_id().id(); -} - -void TabContents::RenderViewCreated(RenderViewHost* render_view_host) { - NotificationService::current()->Notify( - NotificationType::RENDER_VIEW_HOST_CREATED_FOR_TAB, - Source<TabContents>(this), - Details<RenderViewHost>(render_view_host)); - NavigationEntry* entry = controller_.GetActiveEntry(); - if (!entry) - return; - - // When we're creating views, we're still doing initial setup, so we always - // use the pending Web UI rather than any possibly existing committed one. - if (render_manager_.pending_web_ui()) { - render_manager_.pending_web_ui()->RenderViewCreated(render_view_host); - } - - if (entry->IsViewSourceMode()) { - // Put the renderer in view source mode. - render_view_host->Send( - new ViewMsg_EnableViewSourceMode(render_view_host->routing_id())); - } - - view()->RenderViewCreated(render_view_host); -} - -void TabContents::RenderViewReady(RenderViewHost* rvh) { - if (rvh != render_view_host()) { - // Don't notify the world, since this came from a renderer in the - // background. - return; - } - - NotifyConnected(); - bool was_crashed = is_crashed(); - SetIsCrashed(base::TERMINATION_STATUS_STILL_RUNNING, 0); - - // Restore the focus to the tab (otherwise the focus will be on the top - // window). - if (was_crashed && !FocusLocationBarByDefault() && - (!delegate_ || delegate_->ShouldFocusPageAfterCrash())) { - Focus(); - } -} - -void TabContents::RenderViewGone(RenderViewHost* rvh, - base::TerminationStatus status, - int error_code) { - // Ask the print preview if this renderer was valuable. - if (!printing_->OnRenderViewGone(rvh)) - return; - if (rvh != render_view_host()) { - // The pending page's RenderViewHost is gone. - return; - } - - SetIsLoading(false, NULL); - NotifyDisconnected(); - SetIsCrashed(status, error_code); - - // Remove all infobars. - while (!infobar_delegates_.empty()) - RemoveInfoBar(GetInfoBarDelegateAt(infobar_count() - 1)); - - // Tell the view that we've crashed so it can prepare the sad tab page. - // Only do this if we're not in browser shutdown, so that TabContents - // objects that are not in a browser (e.g., HTML dialogs) and thus are - // visible do not flash a sad tab page. - if (browser_shutdown::GetShutdownType() == browser_shutdown::NOT_VALID) - view_->OnTabCrashed(status, error_code); - - // Hide any visible hung renderer warning for this web contents' process. - hung_renderer_dialog::HideForTabContents(this); -} - -void TabContents::RenderViewDeleted(RenderViewHost* rvh) { - NotificationService::current()->Notify( - NotificationType::RENDER_VIEW_HOST_DELETED, - Source<TabContents>(this), - Details<RenderViewHost>(rvh)); - render_manager_.RenderViewDeleted(rvh); -} - -void TabContents::DidNavigate(RenderViewHost* rvh, - const ViewHostMsg_FrameNavigate_Params& params) { - int extra_invalidate_flags = 0; - - if (PageTransition::IsMainFrame(params.transition)) { - if (MaybeUsePreloadedPage(params.url)) { - return; - } - - bool was_bookmark_bar_visible = ShouldShowBookmarkBar(); - - render_manager_.DidNavigateMainFrame(rvh); - - if (was_bookmark_bar_visible != ShouldShowBookmarkBar()) - extra_invalidate_flags |= INVALIDATE_BOOKMARK_BAR; - } - - // Update the site of the SiteInstance if it doesn't have one yet. - if (!GetSiteInstance()->has_site()) - GetSiteInstance()->SetSite(params.url); - - // Need to update MIME type here because it's referred to in - // UpdateNavigationCommands() called by RendererDidNavigate() to - // determine whether or not to enable the encoding menu. - // It's updated only for the main frame. For a subframe, - // RenderView::UpdateURL does not set params.contents_mime_type. - // (see http://code.google.com/p/chromium/issues/detail?id=2929 ) - // TODO(jungshik): Add a test for the encoding menu to avoid - // regressing it again. - if (PageTransition::IsMainFrame(params.transition)) - contents_mime_type_ = params.contents_mime_type; - - NavigationController::LoadCommittedDetails details; - bool did_navigate = controller_.RendererDidNavigate( - params, extra_invalidate_flags, &details); - - // Send notification about committed provisional loads. This notification is - // different from the NAV_ENTRY_COMMITTED notification which doesn't include - // the actual URL navigated to and isn't sent for AUTO_SUBFRAME navigations. - if (details.type != NavigationType::NAV_IGNORE) { - // For AUTO_SUBFRAME navigations, an event for the main frame is generated - // that is not recorded in the navigation history. For the purpose of - // tracking navigation events, we treat this event as a sub frame navigation - // event. - bool is_main_frame = did_navigate ? details.is_main_frame : false; - ProvisionalLoadDetails load_details( - is_main_frame, details.is_in_page, params.url, std::string(), false, - false, params.frame_id); - load_details.set_transition_type(params.transition); - // Whether or not a page transition was triggered by going backward or - // forward in the history is only stored in the navigation controller's - // entry list. - if (did_navigate && - (controller_.GetActiveEntry()->transition_type() & - PageTransition::FORWARD_BACK)) { - load_details.set_transition_type( - params.transition | PageTransition::FORWARD_BACK); - } - NotificationService::current()->Notify( - NotificationType::FRAME_PROVISIONAL_LOAD_COMMITTED, - Source<NavigationController>(&controller_), - Details<ProvisionalLoadDetails>(&load_details)); - } - - // Update history. Note that this needs to happen after the entry is complete, - // which WillNavigate[Main,Sub]Frame will do before this function is called. - if (params.should_update_history) { - // Most of the time, the displayURL matches the loaded URL, but for about: - // URLs, we use a data: URL as the real value. We actually want to save the - // about: URL to the history db and keep the data: URL hidden. This is what - // the TabContents' URL getter does. - scoped_refptr<history::HistoryAddPageArgs> add_page_args( - CreateHistoryAddPageArgs(GetURL(), details, params)); - if (!delegate() || - delegate()->ShouldAddNavigationToHistory(*add_page_args, - details.type)) { - UpdateHistoryForNavigation(add_page_args); - } - } - - if (!did_navigate) - return; // No navigation happened. - - // DO NOT ADD MORE STUFF TO THIS FUNCTION! Your component should either listen - // for the appropriate notification (best) or you can add it to - // DidNavigateMainFramePostCommit / DidNavigateAnyFramePostCommit (only if - // necessary, please). - - // Run post-commit tasks. - if (details.is_main_frame) - DidNavigateMainFramePostCommit(details, params); - DidNavigateAnyFramePostCommit(rvh, details, params); -} - -void TabContents::UpdateState(RenderViewHost* rvh, - int32 page_id, - const std::string& state) { - DCHECK(rvh == render_view_host()); - - // We must be prepared to handle state updates for any page, these occur - // when the user is scrolling and entering form data, as well as when we're - // leaving a page, in which case our state may have already been moved to - // the next page. The navigation controller will look up the appropriate - // NavigationEntry and update it when it is notified via the delegate. - - int entry_index = controller_.GetEntryIndexWithPageID( - GetSiteInstance(), page_id); - if (entry_index < 0) - return; - NavigationEntry* entry = controller_.GetEntryAtIndex(entry_index); - - if (state == entry->content_state()) - return; // Nothing to update. - entry->set_content_state(state); - controller_.NotifyEntryChanged(entry, entry_index); -} - -void TabContents::UpdateTitle(RenderViewHost* rvh, - int32 page_id, const std::wstring& title) { - // If we have a title, that's a pretty good indication that we've started - // getting useful data. - SetNotWaitingForResponse(); - - DCHECK(rvh == render_view_host()); - NavigationEntry* entry = controller_.GetEntryWithPageID(rvh->site_instance(), - page_id); - if (!entry || !UpdateTitleForEntry(entry, title)) - return; - - // Broadcast notifications when the UI should be updated. - if (entry == controller_.GetEntryAtOffset(0)) - NotifyNavigationStateChanged(INVALIDATE_TITLE); -} - -void TabContents::UpdateEncoding(RenderViewHost* render_view_host, - const std::string& encoding) { - set_encoding(encoding); -} - -void TabContents::UpdateTargetURL(int32 page_id, const GURL& url) { - if (delegate()) - delegate()->UpdateTargetURL(this, url); -} - -void TabContents::UpdateThumbnail(const GURL& url, - const SkBitmap& bitmap, - const ThumbnailScore& score) { - if (profile()->IsOffTheRecord()) - return; - - // Tell History about this thumbnail - history::TopSites* ts = profile()->GetTopSites(); - if (ts) - ts->SetPageThumbnail(url, bitmap, score); -} - -void TabContents::UpdateInspectorSetting(const std::string& key, - const std::string& value) { - RenderViewHostDelegateHelper::UpdateInspectorSetting(profile(), key, value); -} - -void TabContents::ClearInspectorSettings() { - RenderViewHostDelegateHelper::ClearInspectorSettings(profile()); -} - -void TabContents::Close(RenderViewHost* rvh) { - // The UI may be in an event-tracking loop, such as between the - // mouse-down and mouse-up in text selection or a button click. - // Defer the close until after tracking is complete, so that we - // don't free objects out from under the UI. - // TODO(shess): This could probably be integrated with the - // IsDoingDrag() test below. Punting for now because I need more - // research to understand how this impacts platforms other than Mac. - // TODO(shess): This could get more fine-grained. For instance, - // closing a tab in another window while selecting text in the - // current window's Omnibox should be just fine. - if (view()->IsEventTracking()) { - view()->CloseTabAfterEventTracking(); - return; - } - - // If we close the tab while we're in the middle of a drag, we'll crash. - // Instead, cancel the drag and close it as soon as the drag ends. - if (view()->IsDoingDrag()) { - view()->CancelDragAndCloseTab(); - return; - } - - // Ignore this if it comes from a RenderViewHost that we aren't showing. - if (delegate() && rvh == render_view_host()) - delegate()->CloseContents(this); -} - -void TabContents::RequestMove(const gfx::Rect& new_bounds) { - if (delegate() && delegate()->IsPopup(this)) - delegate()->MoveContents(this, new_bounds); -} - -void TabContents::DidStartLoading() { - SetIsLoading(true, NULL); - - if (delegate()) { - bool is_print_preview_tab = - printing::PrintPreviewTabController::IsPrintPreviewTab(this); - if (content_restrictions_ || is_print_preview_tab) { - content_restrictions_= is_print_preview_tab ? - CONTENT_RESTRICTION_PRINT : 0; - delegate()->ContentRestrictionsChanged(this); - } - } - - // Notify observers about navigation. - FOR_EACH_OBSERVER(TabContentsObserver, observers_, DidStartLoading()); -} - -void TabContents::DidStopLoading() { - scoped_ptr<LoadNotificationDetails> details; - - NavigationEntry* entry = controller_.GetActiveEntry(); - // An entry may not exist for a stop when loading an initial blank page or - // if an iframe injected by script into a blank page finishes loading. - if (entry) { - base::TimeDelta elapsed = base::TimeTicks::Now() - current_load_start_; - - details.reset(new LoadNotificationDetails( - entry->virtual_url(), - entry->transition_type(), - elapsed, - &controller_, - controller_.GetCurrentEntryIndex())); - } - - SetIsLoading(false, details.get()); - - // Notify observers about navigation. - FOR_EACH_OBSERVER(TabContentsObserver, observers_, DidStopLoading()); -} - -void TabContents::DidChangeLoadProgress(double progress) { - if (delegate()) - delegate()->LoadProgressChanged(progress); -} - -void TabContents::DocumentOnLoadCompletedInMainFrame( - RenderViewHost* render_view_host, - int32 page_id) { - NotificationService::current()->Notify( - NotificationType::LOAD_COMPLETED_MAIN_FRAME, - Source<TabContents>(this), - Details<int>(&page_id)); -} - -void TabContents::RequestOpenURL(const GURL& url, const GURL& referrer, - WindowOpenDisposition disposition) { - if (render_manager_.web_ui()) { - // When we're a Web UI, it will provide a page transition type for us (this - // is so the new tab page can specify AUTO_BOOKMARK for automatically - // generated suggestions). - // - // Note also that we hide the referrer for Web UI pages. We don't really - // want web sites to see a referrer of "chrome://blah" (and some - // chrome: URLs might have search terms or other stuff we don't want to - // send to the site), so we send no referrer. - OpenURL(url, GURL(), disposition, - render_manager_.web_ui()->link_transition_type()); - } else { - OpenURL(url, referrer, disposition, PageTransition::LINK); - } -} - -void TabContents::DomOperationResponse(const std::string& json_string, - int automation_id) { -} - -void TabContents::ProcessWebUIMessage( - const ViewHostMsg_DomMessage_Params& params) { - if (!render_manager_.web_ui()) { - // This can happen if someone uses window.open() to open an extension URL - // from a non-extension context. - render_view_host()->BlockExtensionRequest(params.request_id); - return; - } - render_manager_.web_ui()->ProcessWebUIMessage(params); -} - -void TabContents::ProcessExternalHostMessage(const std::string& message, - const std::string& origin, - const std::string& target) { - if (delegate()) - delegate()->ForwardMessageToExternalHost(message, origin, target); -} - -void TabContents::RunJavaScriptMessage( - const std::wstring& message, - const std::wstring& default_prompt, - const GURL& frame_url, - const int flags, - IPC::Message* reply_msg, - bool* did_suppress_message) { - // Suppress javascript messages when requested and when inside a constrained - // popup window (because that activates them and breaks them out of the - // constrained window jail). - // Also suppress messages when showing an interstitial. The interstitial is - // shown over the previous page, we don't want the hidden page dialogs to - // interfere with the interstitial. - bool suppress_this_message = - suppress_javascript_messages_ || - showing_interstitial_page() || - (delegate() && delegate()->ShouldSuppressDialogs()); - if (delegate()) - suppress_this_message |= - (delegate()->GetConstrainingContents(this) != this); - - *did_suppress_message = suppress_this_message; - - if (!suppress_this_message) { - base::TimeDelta time_since_last_message( - base::TimeTicks::Now() - last_javascript_message_dismissal_); - bool show_suppress_checkbox = false; - // Show a checkbox offering to suppress further messages if this message is - // being displayed within kJavascriptMessageExpectedDelay of the last one. - if (time_since_last_message < - base::TimeDelta::FromMilliseconds(kJavascriptMessageExpectedDelay)) - show_suppress_checkbox = true; - - RunJavascriptMessageBox(profile(), this, frame_url, flags, message, - default_prompt, show_suppress_checkbox, reply_msg); - } else { - // If we are suppressing messages, just reply as is if the user immediately - // pressed "Cancel". - OnMessageBoxClosed(reply_msg, false, std::wstring()); - } -} - -void TabContents::RunBeforeUnloadConfirm(const std::wstring& message, - IPC::Message* reply_msg) { - if (delegate()) - delegate()->WillRunBeforeUnloadConfirm(); - if (delegate() && delegate()->ShouldSuppressDialogs()) { - render_view_host()->JavaScriptMessageBoxClosed(reply_msg, true, - std::wstring()); - return; - } - is_showing_before_unload_dialog_ = true; - RunBeforeUnloadDialog(this, message, reply_msg); -} - -void TabContents::ShowModalHTMLDialog(const GURL& url, int width, int height, - const std::string& json_arguments, - IPC::Message* reply_msg) { - if (delegate()) { - HtmlDialogUIDelegate* dialog_delegate = - new ModalHtmlDialogDelegate(url, width, height, json_arguments, - reply_msg, this); - delegate()->ShowHtmlDialog(dialog_delegate, NULL); - } -} - -GURL TabContents::GetAlternateErrorPageURL() const { - GURL url; - // Disable alternate error pages when in OffTheRecord/Incognito mode. - if (profile()->IsOffTheRecord()) - return url; - - PrefService* prefs = profile()->GetPrefs(); - DCHECK(prefs); - if (prefs->GetBoolean(prefs::kAlternateErrorPagesEnabled)) { - url = google_util::AppendGoogleLocaleParam( - GURL(google_util::kLinkDoctorBaseURL)); - url = google_util::AppendGoogleTLDParam(url); - } - return url; -} - -WebPreferences TabContents::GetWebkitPrefs() { - Profile* profile = render_view_host()->process()->profile(); - bool is_web_ui = false; - WebPreferences web_prefs = - RenderViewHostDelegateHelper::GetWebkitPrefs(profile, is_web_ui); - - // Force accelerated compositing and 2d canvas off for chrome: and - // chrome-extension: pages. - if (GetURL().SchemeIs(chrome::kChromeDevToolsScheme) || - GetURL().SchemeIs(chrome::kChromeUIScheme)) { - web_prefs.accelerated_compositing_enabled = false; - web_prefs.accelerated_2d_canvas_enabled = false; - } - -#if defined(OS_MACOSX) - // Disable accelerated compositing if IOSurface's are not supported, - // as is the case in 10.5. - if (!IOSurfaceSupport::Initialize()) - web_prefs.accelerated_compositing_enabled = false; -#endif - - return web_prefs; -} - -void TabContents::OnUserGesture() { - // See comment in RenderViewHostDelegate::OnUserGesture as to why we do this. - DownloadRequestLimiter* limiter = - g_browser_process->download_request_limiter(); - if (limiter) - limiter->OnUserGesture(this); - ExternalProtocolHandler::PermitLaunchUrl(); -} - -void TabContents::OnIgnoredUIEvent() { - if (constrained_window_count()) { - ConstrainedWindow* window = *constrained_window_begin(); - window->FocusConstrainedWindow(); - } -} - -void TabContents::OnJSOutOfMemory() { - AddInfoBar(new SimpleAlertInfoBarDelegate(this, NULL, - l10n_util::GetStringUTF16(IDS_JS_OUT_OF_MEMORY_PROMPT), true)); -} - -void TabContents::OnCrossSiteResponse(int new_render_process_host_id, - int new_request_id) { - // Allows the TabContents to react when a cross-site response is ready to be - // delivered to a pending RenderViewHost. We must first run the onunload - // handler of the old RenderViewHost before we can allow it to proceed. - render_manager_.OnCrossSiteResponse(new_render_process_host_id, - new_request_id); -} - -void TabContents::RendererUnresponsive(RenderViewHost* rvh, - bool is_during_unload) { - if (is_during_unload) { - // Hang occurred while firing the beforeunload/unload handler. - // Pretend the handler fired so tab closing continues as if it had. - rvh->set_sudden_termination_allowed(true); - - if (!render_manager_.ShouldCloseTabOnUnresponsiveRenderer()) - return; - - // If the tab hangs in the beforeunload/unload handler there's really - // nothing we can do to recover. Pretend the unload listeners have - // all fired and close the tab. If the hang is in the beforeunload handler - // then the user will not have the option of cancelling the close. - Close(rvh); - return; - } - - if (render_view_host() && render_view_host()->IsRenderViewLive() && - (!delegate() || delegate()->ShouldShowHungRendererDialog())) { - hung_renderer_dialog::ShowForTabContents(this); - } -} - -void TabContents::RendererResponsive(RenderViewHost* render_view_host) { - hung_renderer_dialog::HideForTabContents(this); -} - -void TabContents::LoadStateChanged(const GURL& url, - net::LoadState load_state, - uint64 upload_position, - uint64 upload_size) { - load_state_ = load_state; - upload_position_ = upload_position; - upload_size_ = upload_size; - std::wstring languages = - UTF8ToWide(profile()->GetPrefs()->GetString(prefs::kAcceptLanguages)); - std::string host = url.host(); - load_state_host_ = WideToUTF16Hack( - net::IDNToUnicode(host.c_str(), host.size(), languages, NULL)); - if (load_state_ == net::LOAD_STATE_READING_RESPONSE) - SetNotWaitingForResponse(); - if (is_loading()) - NotifyNavigationStateChanged(INVALIDATE_LOAD | INVALIDATE_TAB); -} - -bool TabContents::IsExternalTabContainer() const { - if (!delegate()) - return false; - - return delegate()->IsExternalTabContainer(); -} - -void TabContents::DidInsertCSS() { - // This RVHDelegate function is used for extensions and not us. -} - -void TabContents::FocusedNodeChanged(bool is_editable_node) { - NotificationService::current()->Notify( - NotificationType::FOCUS_CHANGED_IN_PAGE, - Source<TabContents>(this), - Details<const bool>(&is_editable_node)); -} - -void TabContents::UpdateZoomLimits(int minimum_percent, - int maximum_percent, - bool remember) { - minimum_zoom_percent_ = minimum_percent; - maximum_zoom_percent_ = maximum_percent; - temporary_zoom_settings_ = !remember; -} - -void TabContents::WorkerCrashed() { - AddInfoBar(new SimpleAlertInfoBarDelegate(this, NULL, - l10n_util::GetStringUTF16(IDS_WEBWORKER_CRASHED_PROMPT), true)); -} - -void TabContents::BeforeUnloadFiredFromRenderManager( - bool proceed, - bool* proceed_to_fire_unload) { - if (delegate()) - delegate()->BeforeUnloadFired(this, proceed, proceed_to_fire_unload); -} - -void TabContents::DidStartLoadingFromRenderManager( - RenderViewHost* render_view_host) { - DidStartLoading(); -} - -void TabContents::RenderViewGoneFromRenderManager( - RenderViewHost* render_view_host) { - DCHECK(crashed_status_ != base::TERMINATION_STATUS_STILL_RUNNING); - RenderViewGone(render_view_host, crashed_status_, crashed_error_code_); -} - -void TabContents::UpdateRenderViewSizeForRenderManager() { - // TODO(brettw) this is a hack. See TabContentsView::SizeContents. - gfx::Size size = view_->GetContainerSize(); - // 0x0 isn't a valid window size (minimal window size is 1x1) but it may be - // here during container initialization and normal window size will be set - // later. In case of tab duplication this resizing to 0x0 prevents setting - // normal size later so just ignore it. - if (!size.IsEmpty()) - view_->SizeContents(size); -} - -void TabContents::NotifySwappedFromRenderManager() { - NotifySwapped(); -} - -NavigationController& TabContents::GetControllerForRenderManager() { - return controller(); -} - -WebUI* TabContents::CreateWebUIForRenderManager(const GURL& url) { - return WebUIFactory::CreateWebUIForURL(this, url); -} - -NavigationEntry* -TabContents::GetLastCommittedNavigationEntryForRenderManager() { - return controller_.GetLastCommittedEntry(); -} - -bool TabContents::CreateRenderViewForRenderManager( - RenderViewHost* render_view_host) { - RenderWidgetHostView* rwh_view = view_->CreateViewForWidget(render_view_host); - - if (!render_view_host->CreateRenderView(string16())) - return false; - - // Now that the RenderView has been created, we need to tell it its size. - rwh_view->SetSize(view_->GetContainerSize()); - - UpdateMaxPageIDIfNecessary(render_view_host->site_instance(), - render_view_host); - return true; -} - -void TabContents::Observe(NotificationType type, - const NotificationSource& source, - const NotificationDetails& details) { - switch (type.value) { - case NotificationType::PREF_CHANGED: { - std::string* pref_name_in = Details<std::string>(details).ptr(); - DCHECK(Source<PrefService>(source).ptr() == profile()->GetPrefs()); - if (*pref_name_in == prefs::kAlternateErrorPagesEnabled) { - UpdateAlternateErrorPageURL(); - } else if ((*pref_name_in == prefs::kDefaultCharset) || - StartsWithASCII(*pref_name_in, "webkit.webprefs.", true)) { - UpdateWebPreferences(); - } else if (*pref_name_in == prefs::kDefaultZoomLevel) { - UpdateZoomLevel(); - } else { - NOTREACHED() << "unexpected pref change notification" << *pref_name_in; - } - break; - } - case NotificationType::RENDER_WIDGET_HOST_DESTROYED: - view_->RenderWidgetHostDestroyed(Source<RenderWidgetHost>(source).ptr()); - break; - - case NotificationType::NAV_ENTRY_COMMITTED: { - DCHECK(&controller_ == Source<NavigationController>(source).ptr()); - - NavigationController::LoadCommittedDetails& committed_details = - *(Details<NavigationController::LoadCommittedDetails>(details).ptr()); - ExpireInfoBars(committed_details); - break; - } - -#if defined(OS_LINUX) - case NotificationType::BROWSER_THEME_CHANGED: { - renderer_preferences_util::UpdateFromSystemSettings( - &renderer_preferences_, profile()); - render_view_host()->SyncRendererPrefs(); - break; - } -#endif - - case NotificationType::USER_STYLE_SHEET_UPDATED: - UpdateWebPreferences(); - break; - - case NotificationType::CONTENT_SETTINGS_CHANGED: { - Details<const ContentSettingsDetails> settings_details(details); - NavigationEntry* entry = controller_.GetActiveEntry(); - GURL entry_url; - if (entry) - entry_url = entry->url(); - if (settings_details.ptr()->update_all() || - settings_details.ptr()->pattern().Matches(entry_url)) { - render_view_host()->SendContentSettings(entry_url, - profile()->GetHostContentSettingsMap()-> - GetContentSettings(entry_url)); - } - break; - } - - case NotificationType::EXTENSION_LOADED: - break; - - case NotificationType::EXTENSION_UNLOADED: - break; - - case NotificationType::GOOGLE_URL_UPDATED: - UpdateAlternateErrorPageURL(); - break; - - default: - NOTREACHED(); - } -} - -void TabContents::UpdateExtensionAppIcon(const Extension* extension) { - extension_app_icon_.reset(); - - if (extension) { - extension_app_image_loader_.reset(new ImageLoadingTracker(this)); - extension_app_image_loader_->LoadImage( - extension, - extension->GetIconResource(Extension::EXTENSION_ICON_SMALLISH, - ExtensionIconSet::MATCH_EXACTLY), - gfx::Size(Extension::EXTENSION_ICON_SMALLISH, - Extension::EXTENSION_ICON_SMALLISH), - ImageLoadingTracker::CACHE); - } else { - extension_app_image_loader_.reset(NULL); - } -} - -const Extension* TabContents::GetExtensionContaining(const GURL& url) { - ExtensionService* extensions_service = profile()->GetExtensionService(); - if (!extensions_service) - return NULL; - - const Extension* extension = extensions_service->GetExtensionByURL(url); - return extension ? - extension : extensions_service->GetExtensionByWebExtent(url); -} - -void TabContents::OnImageLoaded(SkBitmap* image, ExtensionResource resource, - int index) { - if (image) { - extension_app_icon_ = *image; - NotifyNavigationStateChanged(INVALIDATE_TAB); - } -} - -gfx::NativeWindow TabContents::GetMessageBoxRootWindow() { - return view_->GetTopLevelNativeWindow(); -} - -void TabContents::OnMessageBoxClosed(IPC::Message* reply_msg, - bool success, - const std::wstring& prompt) { - last_javascript_message_dismissal_ = base::TimeTicks::Now(); - if (is_showing_before_unload_dialog_ && !success) { - // If a beforeunload dialog is canceled, we need to stop the throbber from - // spinning, since we forced it to start spinning in Navigate. - DidStopLoading(); - - tab_close_start_time_ = base::TimeTicks(); - } - is_showing_before_unload_dialog_ = false; - render_view_host()->JavaScriptMessageBoxClosed(reply_msg, success, prompt); -} - -void TabContents::SetSuppressMessageBoxes(bool suppress_message_boxes) { - set_suppress_javascript_messages(suppress_message_boxes); -} - -TabContents* TabContents::AsTabContents() { - return this; -} - -ExtensionHost* TabContents::AsExtensionHost() { - return NULL; -} - -void TabContents::set_encoding(const std::string& encoding) { - encoding_ = CharacterEncoding::GetCanonicalEncodingNameByAliasName(encoding); -} - -void TabContents::SetAppIcon(const SkBitmap& app_icon) { - app_icon_ = app_icon; - NotifyNavigationStateChanged(INVALIDATE_TITLE); -} - -void TabContents::SwapInRenderViewHost(RenderViewHost* rvh) { - render_manager_.SwapInRenderViewHost(rvh); -} - -void TabContents::CreateViewAndSetSizeForRVH(RenderViewHost* rvh) { - RenderWidgetHostView* rwh_view = view()->CreateViewForWidget(rvh); - rwh_view->SetSize(view()->GetContainerSize()); -} - -bool TabContents::MaybeUsePreloadedPage(const GURL& url) { - prerender::PrerenderManager* pm = profile()->GetPrerenderManager(); - if (pm != NULL) { - if (pm->MaybeUsePreloadedPage(this, url)) - return true; - } - return false; -} diff --git a/chrome/browser/tab_contents/tab_contents.h b/chrome/browser/tab_contents/tab_contents.h index dcadb15..e8dcbdb 100644 --- a/chrome/browser/tab_contents/tab_contents.h +++ b/chrome/browser/tab_contents/tab_contents.h @@ -6,1257 +6,7 @@ #define CHROME_BROWSER_TAB_CONTENTS_TAB_CONTENTS_H_ #pragma once -#include <deque> -#include <map> -#include <string> -#include <vector> - -#include "base/basictypes.h" -#include "base/gtest_prod_util.h" -#include "base/scoped_ptr.h" -#include "base/string16.h" -#include "chrome/browser/download/save_package.h" -#include "chrome/browser/extensions/image_loading_tracker.h" -#include "chrome/browser/fav_icon_helper.h" -#include "chrome/browser/prefs/pref_change_registrar.h" -#include "chrome/browser/renderer_host/render_view_host_delegate.h" -#include "chrome/browser/tab_contents/constrained_window.h" -#include "chrome/browser/tab_contents/language_state.h" -#include "chrome/browser/tab_contents/navigation_controller.h" -#include "chrome/browser/tab_contents/navigation_entry.h" -#include "chrome/browser/tab_contents/page_navigator.h" -#include "chrome/browser/tab_contents/render_view_host_manager.h" -#include "chrome/browser/tab_contents/tab_specific_content_settings.h" -#include "chrome/browser/ui/app_modal_dialogs/js_modal_dialog.h" -#include "chrome/browser/webui/web_ui_factory.h" -#include "chrome/common/notification_registrar.h" -#include "chrome/common/property_bag.h" -#include "chrome/common/renderer_preferences.h" -#include "chrome/common/translate_errors.h" -#include "chrome/common/web_apps.h" -#include "net/base/load_states.h" -#include "ui/gfx/native_widget_types.h" - -#if defined(OS_WIN) -#include "base/win/scoped_handle.h" -#endif - -namespace gfx { -class Rect; -} - -namespace history { -class HistoryAddPageArgs; -} - -namespace prerender { -class PrerenderManager; -class PrerenderPLTRecorder; -} - -namespace printing { -class PrintPreviewMessageHandler; -class PrintViewManager; -} - -namespace safe_browsing { -class ClientSideDetectionHost; -} - -class AutocompleteHistoryManager; -class AutoFillManager; -class BlockedContentContainer; -class WebUI; -class DesktopNotificationHandlerForTC; -class DownloadItem; -class Extension; -class FileSelectHelper; -class InfoBarDelegate; -class LoadNotificationDetails; -class OmniboxSearchHint; -class PluginObserver; -class Profile; -class RenderViewHost; -class SessionStorageNamespace; -class SiteInstance; -class SkBitmap; -class TabContents; -class TabContentsDelegate; -class TabContentsObserver; -class TabContentsSSLHelper; -class TabContentsView; -class URLPattern; -struct RendererPreferences; -struct ThumbnailScore; -struct ViewHostMsg_DomMessage_Params; -struct ViewHostMsg_FrameNavigate_Params; -struct ViewHostMsg_RunFileChooser_Params; -struct WebPreferences; - -// Describes what goes in the main content area of a tab. TabContents is -// the only type of TabContents, and these should be merged together. -class TabContents : public PageNavigator, - public NotificationObserver, - public RenderViewHostDelegate, - public RenderViewHostManager::Delegate, - public JavaScriptAppModalDialogDelegate, - public ImageLoadingTracker::Observer, - public TabSpecificContentSettings::Delegate { - public: - // Flags passed to the TabContentsDelegate.NavigationStateChanged to tell it - // what has changed. Combine them to update more than one thing. - enum InvalidateTypes { - INVALIDATE_URL = 1 << 0, // The URL has changed. - INVALIDATE_TAB = 1 << 1, // The favicon, app icon, or crashed - // state changed. - INVALIDATE_LOAD = 1 << 2, // The loading state has changed. - INVALIDATE_PAGE_ACTIONS = 1 << 3, // Page action icons have changed. - INVALIDATE_BOOKMARK_BAR = 1 << 4, // State of ShouldShowBookmarkBar - // changed. - INVALIDATE_TITLE = 1 << 5, // The title changed. - }; - - // |base_tab_contents| is used if we want to size the new tab contents view - // based on an existing tab contents view. This can be NULL if not needed. - // - // The session storage namespace parameter allows multiple render views and - // tab contentses to share the same session storage (part of the WebStorage - // spec) space. This is useful when restoring tabs, but most callers should - // pass in NULL which will cause a new SessionStorageNamespace to be created. - TabContents(Profile* profile, - SiteInstance* site_instance, - int routing_id, - const TabContents* base_tab_contents, - SessionStorageNamespace* session_storage_namespace); - virtual ~TabContents(); - - static void RegisterUserPrefs(PrefService* prefs); - - // Intrinsic tab state ------------------------------------------------------- - - // Returns the property bag for this tab contents, where callers can add - // extra data they may wish to associate with the tab. Returns a pointer - // rather than a reference since the PropertyAccessors expect this. - const PropertyBag* property_bag() const { return &property_bag_; } - PropertyBag* property_bag() { return &property_bag_; } - - TabContentsDelegate* delegate() const { return delegate_; } - void set_delegate(TabContentsDelegate* d) { delegate_ = d; } - - // Gets the controller for this tab contents. - NavigationController& controller() { return controller_; } - const NavigationController& controller() const { return controller_; } - - // Returns the user profile associated with this TabContents (via the - // NavigationController). - Profile* profile() const { return controller_.profile(); } - - // Returns true if contains content rendered by an extension. - bool HostsExtension() const; - - // Returns the TabContentsSSLHelper, creating it if necessary. - TabContentsSSLHelper* GetSSLHelper(); - - // Returns the SavePackage which manages the page saving job. May be NULL. - SavePackage* save_package() const { return save_package_.get(); } - - // Return the currently active RenderProcessHost and RenderViewHost. Each of - // these may change over time. - RenderProcessHost* GetRenderProcessHost() const; - RenderViewHost* render_view_host() const { - return render_manager_.current_host(); - } - - WebUI* web_ui() const { - return render_manager_.web_ui() ? render_manager_.web_ui() - : render_manager_.pending_web_ui(); - } - - // Returns the currently active RenderWidgetHostView. This may change over - // time and can be NULL (during setup and teardown). - RenderWidgetHostView* GetRenderWidgetHostView() const { - return render_manager_.GetRenderWidgetHostView(); - } - - // The TabContentsView will never change and is guaranteed non-NULL. - TabContentsView* view() const { - return view_.get(); - } - - // Returns the FavIconHelper of this TabContents. - FavIconHelper& fav_icon_helper() { - return *fav_icon_helper_.get(); - } - - // App extensions ------------------------------------------------------------ - - // Sets the extension denoting this as an app. If |extension| is non-null this - // tab becomes an app-tab. TabContents does not listen for unload events for - // the extension. It's up to consumers of TabContents to do that. - // - // NOTE: this should only be manipulated before the tab is added to a browser. - // TODO(sky): resolve if this is the right way to identify an app tab. If it - // is, than this should be passed in the constructor. - void SetExtensionApp(const Extension* extension); - - // Convenience for setting the app extension by id. This does nothing if - // |extension_app_id| is empty, or an extension can't be found given the - // specified id. - void SetExtensionAppById(const std::string& extension_app_id); - - const Extension* extension_app() const { return extension_app_; } - bool is_app() const { return extension_app_ != NULL; } - - // If an app extension has been explicitly set for this TabContents its icon - // is returned. - // - // NOTE: the returned icon is larger than 16x16 (its size is - // Extension::EXTENSION_ICON_SMALLISH). - SkBitmap* GetExtensionAppIcon(); - - // Tab navigation state ------------------------------------------------------ - - // Returns the current navigation properties, which if a navigation is - // pending may be provisional (e.g., the navigation could result in a - // download, in which case the URL would revert to what it was previously). - virtual const GURL& GetURL() const; - virtual const string16& GetTitle() const; - - // Initial title assigned to NavigationEntries from Navigate. - static string16 GetDefaultTitle(); - - // The max PageID of any page that this TabContents has loaded. PageIDs - // increase with each new page that is loaded by a tab. If this is a - // TabContents, then the max PageID is kept separately on each SiteInstance. - // Returns -1 if no PageIDs have yet been seen. - int32 GetMaxPageID(); - - // Updates the max PageID to be at least the given PageID. - void UpdateMaxPageID(int32 page_id); - - // Returns the site instance associated with the current page. By default, - // there is no site instance. TabContents overrides this to provide proper - // access to its site instance. - virtual SiteInstance* GetSiteInstance() const; - - // Defines whether this tab's URL should be displayed in the browser's URL - // bar. Normally this is true so you can see the URL. This is set to false - // for the new tab page and related pages so that the URL bar is empty and - // the user is invited to type into it. - virtual bool ShouldDisplayURL(); - - // Returns the favicon for this tab, or an isNull() bitmap if the tab does not - // have a favicon. The default implementation uses the current navigation - // entry. - SkBitmap GetFavIcon() const; - - // Returns true if we are not using the default favicon. - bool FavIconIsValid() const; - - // Returns whether the favicon should be displayed. If this returns false, no - // space is provided for the favicon, and the favicon is never displayed. - virtual bool ShouldDisplayFavIcon(); - - // Returns a human-readable description the tab's loading state. - virtual string16 GetStatusText() const; - - // Add and remove observers for page navigation notifications. Adding or - // removing multiple times has no effect. The order in which notifications - // are sent to observers is undefined. Clients must be sure to remove the - // observer before they go away. - void AddObserver(TabContentsObserver* observer); - void RemoveObserver(TabContentsObserver* observer); - - // Return whether this tab contents is loading a resource. - bool is_loading() const { return is_loading_; } - - // Returns whether this tab contents is waiting for a first-response for the - // main resource of the page. This controls whether the throbber state is - // "waiting" or "loading." - bool waiting_for_response() const { return waiting_for_response_; } - - const std::string& encoding() const { return encoding_; } - void set_encoding(const std::string& encoding); - void reset_encoding() { - encoding_.clear(); - } - - const WebApplicationInfo& web_app_info() const { - return web_app_info_; - } - - const SkBitmap& app_icon() const { return app_icon_; } - - // Sets an app icon associated with TabContents and fires an INVALIDATE_TITLE - // navigation state change to trigger repaint of title. - void SetAppIcon(const SkBitmap& app_icon); - - bool displayed_insecure_content() const { - return displayed_insecure_content_; - } - - // Internal state ------------------------------------------------------------ - - // This flag indicates whether the tab contents is currently being - // screenshotted by the DraggedTabController. - bool capturing_contents() const { return capturing_contents_; } - void set_capturing_contents(bool cap) { capturing_contents_ = cap; } - - // Indicates whether this tab should be considered crashed. The setter will - // also notify the delegate when the flag is changed. - bool is_crashed() const { - return (crashed_status_ == base::TERMINATION_STATUS_PROCESS_CRASHED || - crashed_status_ == base::TERMINATION_STATUS_ABNORMAL_TERMINATION || - crashed_status_ == base::TERMINATION_STATUS_PROCESS_WAS_KILLED); - } - base::TerminationStatus crashed_status() const { return crashed_status_; } - int crashed_error_code() const { return crashed_error_code_; } - void SetIsCrashed(base::TerminationStatus status, int error_code); - - // Call this after updating a page action to notify clients about the changes. - void PageActionStateChanged(); - - // Whether the tab is in the process of being destroyed. - // Added as a tentative work-around for focus related bug #4633. This allows - // us not to store focus when a tab is being closed. - bool is_being_destroyed() const { return is_being_destroyed_; } - - // Convenience method for notifying the delegate of a navigation state - // change. See TabContentsDelegate. - void NotifyNavigationStateChanged(unsigned changed_flags); - - // Invoked when the tab contents becomes selected. If you override, be sure - // and invoke super's implementation. - virtual void DidBecomeSelected(); - base::TimeTicks last_selected_time() const { - return last_selected_time_; - } - - // Invoked when the tab contents becomes hidden. - // NOTE: If you override this, call the superclass version too! - virtual void WasHidden(); - - // Activates this contents within its containing window, bringing that window - // to the foreground if necessary. - void Activate(); - - // Deactivates this contents by deactivating its containing window. - void Deactivate(); - - // TODO(brettw) document these. - virtual void ShowContents(); - virtual void HideContents(); - - // Returns true if the before unload and unload listeners need to be - // fired. The value of this changes over time. For example, if true and the - // before unload listener is executed and allows the user to exit, then this - // returns false. - bool NeedToFireBeforeUnload(); - -#ifdef UNIT_TEST - // Expose the render manager for testing. - RenderViewHostManager* render_manager() { return &render_manager_; } -#endif - - // In the underlying RenderViewHostManager, swaps in the provided - // RenderViewHost to replace the current RenderViewHost. The current RVH - // will be shutdown and ultimately deleted. - void SwapInRenderViewHost(RenderViewHost* rvh); - - // Commands ------------------------------------------------------------------ - - // Implementation of PageNavigator. - virtual void OpenURL(const GURL& url, const GURL& referrer, - WindowOpenDisposition disposition, - PageTransition::Type transition); - - // Called by the NavigationController to cause the TabContents to navigate to - // the current pending entry. The NavigationController should be called back - // with CommitPendingEntry/RendererDidNavigate on success or - // DiscardPendingEntry. The callbacks can be inside of this function, or at - // some future time. - // - // The entry has a PageID of -1 if newly created (corresponding to navigation - // to a new URL). - // - // If this method returns false, then the navigation is discarded (equivalent - // to calling DiscardPendingEntry on the NavigationController). - virtual bool NavigateToPendingEntry( - NavigationController::ReloadType reload_type); - - // Stop any pending navigation. - virtual void Stop(); - - // Called on a TabContents when it isn't a popup, but a new window. - virtual void DisassociateFromPopupCount(); - - // Creates a new TabContents with the same state as this one. The returned - // heap-allocated pointer is owned by the caller. - virtual TabContents* Clone(); - - // Shows the page info. - void ShowPageInfo(const GURL& url, - const NavigationEntry::SSLStatus& ssl, - bool show_history); - - // Saves the favicon for the current page. - void SaveFavicon(); - - // Window management --------------------------------------------------------- - - // Create a new window constrained to this TabContents' clip and visibility. - // The window is initialized by using the supplied delegate to obtain basic - // window characteristics, and the supplied view for the content. Note that - // the returned ConstrainedWindow might not yet be visible. - ConstrainedWindow* CreateConstrainedDialog( - ConstrainedWindowDelegate* delegate); - - // Adds a new tab or window with the given already-created contents - void AddNewContents(TabContents* new_contents, - WindowOpenDisposition disposition, - const gfx::Rect& initial_pos, - bool user_gesture); - - // Execute code in this tab. Returns true if the message was successfully - // sent. - bool ExecuteCode(int request_id, const std::string& extension_id, - bool is_js_code, const std::string& code_string, - bool all_frames); - - // Called when the blocked popup notification is shown or hidden. - virtual void PopupNotificationVisibilityChanged(bool visible); - - // Returns the number of constrained windows in this tab. Used by tests. - size_t constrained_window_count() { return child_windows_.size(); } - - typedef std::deque<ConstrainedWindow*> ConstrainedWindowList; - - // Return an iterator for the first constrained window in this tab contents. - ConstrainedWindowList::iterator constrained_window_begin() - { return child_windows_.begin(); } - - // Return an iterator for the last constrained window in this tab contents. - ConstrainedWindowList::iterator constrained_window_end() - { return child_windows_.end(); } - - // Views and focus ----------------------------------------------------------- - // TODO(brettw): Most of these should be removed and the caller should call - // the view directly. - - // Returns the actual window that is focused when this TabContents is shown. - gfx::NativeView GetContentNativeView() const; - - // Returns the NativeView associated with this TabContents. Outside of - // automation in the context of the UI, this is required to be implemented. - gfx::NativeView GetNativeView() const; - - // Returns the bounds of this TabContents in the screen coordinate system. - void GetContainerBounds(gfx::Rect *out) const; - - // Makes the tab the focused window. - void Focus(); - - // Focuses the first (last if |reverse| is true) element in the page. - // Invoked when this tab is getting the focus through tab traversal (|reverse| - // is true when using Shift-Tab). - void FocusThroughTabTraversal(bool reverse); - - // These next two functions are declared on RenderViewHostManager::Delegate - // but also accessed directly by other callers. - - // Returns true if the location bar should be focused by default rather than - // the page contents. The view calls this function when the tab is focused - // to see what it should do. - virtual bool FocusLocationBarByDefault(); - - // Focuses the location bar. - virtual void SetFocusToLocationBar(bool select_all); - - // Creates a view and sets the size for the specified RVH. - virtual void CreateViewAndSetSizeForRVH(RenderViewHost* rvh); - - // Infobars ------------------------------------------------------------------ - - // Adds an InfoBar for the specified |delegate|. - virtual void AddInfoBar(InfoBarDelegate* delegate); - - // Removes the InfoBar for the specified |delegate|. - void RemoveInfoBar(InfoBarDelegate* delegate); - - // Replaces one infobar with another, without any animation in between. - void ReplaceInfoBar(InfoBarDelegate* old_delegate, - InfoBarDelegate* new_delegate); - - // Enumeration and access functions. - size_t infobar_count() const { return infobar_delegates_.size(); } - // WARNING: This does not sanity-check |index|! - InfoBarDelegate* GetInfoBarDelegateAt(size_t index) { - return infobar_delegates_[index]; - } - - // Toolbars and such --------------------------------------------------------- - - // Returns true if a Bookmark Bar should be shown for this tab. - virtual bool ShouldShowBookmarkBar(); - - // Notifies the delegate that a download is about to be started. - // This notification is fired before a local temporary file has been created. - bool CanDownload(int request_id); - - // Notifies the delegate that a download started. - void OnStartDownload(DownloadItem* download); - - // Notify our delegate that some of our content has animated. - void ToolbarSizeChanged(bool is_animating); - - // Called when a ConstrainedWindow we own is about to be closed. - void WillClose(ConstrainedWindow* window); - - // Called when a BlockedContentContainer we own is about to be closed. - void WillCloseBlockedContentContainer(BlockedContentContainer* container); - - // Called when a ConstrainedWindow we own is moved or resized. - void DidMoveOrResize(ConstrainedWindow* window); - - // Interstitials ------------------------------------------------------------- - - // Various other systems need to know about our interstitials. - bool showing_interstitial_page() const { - return render_manager_.interstitial_page() != NULL; - } - - // Sets the passed passed interstitial as the currently showing interstitial. - // |interstitial_page| should be non NULL (use the remove_interstitial_page - // method to unset the interstitial) and no interstitial page should be set - // when there is already a non NULL interstitial page set. - void set_interstitial_page(InterstitialPage* interstitial_page) { - render_manager_.set_interstitial_page(interstitial_page); - } - - // Unsets the currently showing interstitial. - void remove_interstitial_page() { - render_manager_.remove_interstitial_page(); - } - - // Returns the currently showing interstitial, NULL if no interstitial is - // showing. - InterstitialPage* interstitial_page() const { - return render_manager_.interstitial_page(); - } - - // Misc state & callbacks ---------------------------------------------------- - - // Set whether the contents should block javascript message boxes or not. - // Default is not to block any message boxes. - void set_suppress_javascript_messages(bool suppress_javascript_messages) { - suppress_javascript_messages_ = suppress_javascript_messages; - } - - // Prepare for saving the current web page to disk. - void OnSavePage(); - - // Save page with the main HTML file path, the directory for saving resources, - // and the save type: HTML only or complete web page. Returns true if the - // saving process has been initiated successfully. - bool SavePage(const FilePath& main_file, const FilePath& dir_path, - SavePackage::SavePackageType save_type); - - // Tells the user's email client to open a compose window containing the - // current page's URL. - void EmailPageLocation(); - - // Displays asynchronously a print preview (generated by the renderer) if not - // already displayed and ask the user for its preferred print settings with - // the "Print..." dialog box. (managed by the print worker thread). - // TODO(maruel): Creates a snapshot of the renderer to be used for the new - // tab for the printing facility. - void PrintPreview(); - - // Prints the current document immediately. Since the rendering is - // asynchronous, the actual printing will not be completed on the return of - // this function. Returns false if printing is impossible at the moment. - bool PrintNow(); - - // Notify the completion of a printing job. - void PrintingDone(int document_cookie, bool success); - - // Returns true if the active NavigationEntry's page_id equals page_id. - bool IsActiveEntry(int32 page_id); - - const std::string& contents_mime_type() const { - return contents_mime_type_; - } - - // Returns true if this TabContents will notify about disconnection. - bool notify_disconnection() const { return notify_disconnection_; } - - // Override the encoding and reload the page by sending down - // ViewMsg_SetPageEncoding to the renderer. |UpdateEncoding| is kinda - // the opposite of this, by which 'browser' is notified of - // the encoding of the current tab from 'renderer' (determined by - // auto-detect, http header, meta, bom detection, etc). - void SetOverrideEncoding(const std::string& encoding); - - // Remove any user-defined override encoding and reload by sending down - // ViewMsg_ResetPageEncodingToDefault to the renderer. - void ResetOverrideEncoding(); - - void WindowMoveOrResizeStarted(); - - // Sets whether all TabContents added by way of |AddNewContents| should be - // blocked. Transitioning from all blocked to not all blocked results in - // reevaluating any blocked TabContents, which may result in unblocking some - // of the blocked TabContents. - void SetAllContentsBlocked(bool value); - - BlockedContentContainer* blocked_content_container() const { - return blocked_contents_; - } - - RendererPreferences* GetMutableRendererPrefs() { - return &renderer_preferences_; - } - - void set_opener_web_ui_type(WebUITypeID opener_web_ui_type) { - opener_web_ui_type_ = opener_web_ui_type; - } - - // We want to time how long it takes to create a new tab page. This method - // gets called as parts of the new tab page have loaded. - void LogNewTabTime(const std::string& event_name); - - // Set the time when we started to create the new tab page. This time is - // from before we created this TabContents. - void set_new_tab_start_time(const base::TimeTicks& time) { - new_tab_start_time_ = time; - } - - // Notification that tab closing has started. This can be called multiple - // times, subsequent calls are ignored. - void OnCloseStarted(); - - LanguageState& language_state() { - return language_state_; - } - - // Returns true if underlying TabContentsView should accept drag-n-drop. - bool ShouldAcceptDragAndDrop() const; - - // A render view-originated drag has ended. Informs the render view host and - // tab contents delegate. - void SystemDragEnded(); - - // Indicates if this tab was explicitly closed by the user (control-w, close - // tab menu item...). This is false for actions that indirectly close the tab, - // such as closing the window. The setter is maintained by TabStripModel, and - // the getter only useful from within TAB_CLOSED notification - void set_closed_by_user_gesture(bool value) { - closed_by_user_gesture_ = value; - } - bool closed_by_user_gesture() const { return closed_by_user_gesture_; } - - // Overridden from JavaScriptAppModalDialogDelegate: - virtual void OnMessageBoxClosed(IPC::Message* reply_msg, - bool success, - const std::wstring& prompt); - virtual void SetSuppressMessageBoxes(bool suppress_message_boxes); - virtual gfx::NativeWindow GetMessageBoxRootWindow(); - virtual TabContents* AsTabContents(); - virtual ExtensionHost* AsExtensionHost(); - - // The BookmarkDragDelegate is used to forward bookmark drag and drop events - // to extensions. - virtual RenderViewHostDelegate::BookmarkDrag* GetBookmarkDragDelegate(); - - // It is up to callers to call SetBookmarkDragDelegate(NULL) when - // |bookmark_drag| is deleted since this class does not take ownership of - // |bookmark_drag|. - virtual void SetBookmarkDragDelegate( - RenderViewHostDelegate::BookmarkDrag* bookmark_drag); - - // The TabSpecificContentSettings object is used to query the blocked content - // state by various UI elements. - TabSpecificContentSettings* GetTabSpecificContentSettings() const; - - // Updates history with the specified navigation. This is called by - // OnMsgNavigate to update history state. - void UpdateHistoryForNavigation( - scoped_refptr<history::HistoryAddPageArgs> add_page_args); - - // Sends the page title to the history service. This is called when we receive - // the page title and we know we want to update history. - void UpdateHistoryPageTitle(const NavigationEntry& entry); - - // Gets the zoom level for this tab. - double GetZoomLevel() const; - - // Gets the zoom percent for this tab. - int GetZoomPercent(bool* enable_increment, bool* enable_decrement); - - // Shows a fade effect over this tab contents. Repeated calls will be ignored - // until the fade is canceled. If |animate| is true the fade should animate. - void FadeForInstant(bool animate); - - // Immediately removes the fade. - void CancelInstantFade(); - - // Opens view-source tab for this contents. - void ViewSource(); - - // Gets the minimum/maximum zoom percent. - int minimum_zoom_percent() const { return minimum_zoom_percent_; } - int maximum_zoom_percent() const { return maximum_zoom_percent_; } - - int content_restrictions() const { return content_restrictions_; } - - AutocompleteHistoryManager* autocomplete_history_manager() { - return autocomplete_history_manager_.get(); - } - AutoFillManager* autofill_manager() { return autofill_manager_.get(); } - - safe_browsing::ClientSideDetectionHost* safebrowsing_detection_host() { - return safebrowsing_detection_host_.get(); - } - - protected: - // from RenderViewHostDelegate. - virtual bool OnMessageReceived(const IPC::Message& message); - - private: - friend class NavigationController; - // Used to access the child_windows_ (ConstrainedWindowList) for testing - // automation purposes. - friend class TestingAutomationProvider; - - FRIEND_TEST_ALL_PREFIXES(TabContentsTest, NoJSMessageOnInterstitials); - FRIEND_TEST_ALL_PREFIXES(TabContentsTest, UpdateTitle); - FRIEND_TEST_ALL_PREFIXES(TabContentsTest, CrossSiteCantPreemptAfterUnload); - FRIEND_TEST_ALL_PREFIXES(FormStructureBrowserTest, HTMLFiles); - FRIEND_TEST_ALL_PREFIXES(NavigationControllerTest, HistoryNavigate); - FRIEND_TEST_ALL_PREFIXES(RenderViewHostManagerTest, PageDoesBackAndReload); - - // Temporary until the view/contents separation is complete. - friend class TabContentsView; -#if defined(OS_WIN) - friend class TabContentsViewWin; -#elif defined(OS_MACOSX) - friend class TabContentsViewMac; -#elif defined(TOOLKIT_USES_GTK) - friend class TabContentsViewGtk; -#endif - - // So InterstitialPage can access SetIsLoading. - friend class InterstitialPage; - - // TODO(brettw) TestTabContents shouldn't exist! - friend class TestTabContents; - - // Used to access the CreateHistoryAddPageArgs member function. - friend class ExternalTabContainer; - - // Used to access RVH Delegates. - friend class prerender::PrerenderManager; - - // Add all the TabContentObservers. - void AddObservers(); - - // Message handlers. - void OnDidStartProvisionalLoadForFrame(int64 frame_id, - bool main_frame, - const GURL& url); - void OnDidRedirectProvisionalLoad(int32 page_id, - const GURL& source_url, - const GURL& target_url); - void OnDidFailProvisionalLoadWithError(int64 frame_id, - bool main_frame, - int error_code, - const GURL& url, - bool showing_repost_interstitial); - void OnDidLoadResourceFromMemoryCache(const GURL& url, - const std::string& security_info); - void OnDidDisplayInsecureContent(); - void OnDidRunInsecureContent(const std::string& security_origin, - const GURL& target_url); - void OnDocumentLoadedInFrame(int64 frame_id); - void OnDidFinishLoad(int64 frame_id); - void OnUpdateContentRestrictions(int restrictions); - void OnPDFHasUnsupportedFeature(); - - void OnGoToEntryAtOffset(int offset); - void OnDidGetApplicationInfo(int32 page_id, const WebApplicationInfo& info); - void OnInstallApplication(const WebApplicationInfo& info); - void OnPageContents(const GURL& url, - int32 page_id, - const string16& contents, - const std::string& language, - bool page_translatable); - void OnPageTranslated(int32 page_id, - const std::string& original_lang, - const std::string& translated_lang, - TranslateErrors::Type error_type); - void OnSetSuggestions(int32 page_id, - const std::vector<std::string>& suggestions); - void OnInstantSupportDetermined(int32 page_id, bool result); - void OnRunFileChooser(const ViewHostMsg_RunFileChooser_Params& params); - - // Changes the IsLoading state and notifies delegate as needed - // |details| is used to provide details on the load that just finished - // (but can be null if not applicable). Can be overridden. - void SetIsLoading(bool is_loading, - LoadNotificationDetails* details); - - // Adds the incoming |new_contents| to the |blocked_contents_| container. - void AddPopup(TabContents* new_contents, - const gfx::Rect& initial_pos); - - // Called by derived classes to indicate that we're no longer waiting for a - // response. This won't actually update the throbber, but it will get picked - // up at the next animation step if the throbber is going. - void SetNotWaitingForResponse() { waiting_for_response_ = false; } - - ConstrainedWindowList child_windows_; - - // Expires InfoBars that need to be expired, according to the state carried - // in |details|, in response to a new NavigationEntry being committed (the - // user navigated to another page). - void ExpireInfoBars( - const NavigationController::LoadCommittedDetails& details); - - // Returns the WebUI for the current state of the tab. This will either be - // the pending WebUI, the committed WebUI, or NULL. - WebUI* GetWebUIForCurrentState(); - - // Navigation helpers -------------------------------------------------------- - // - // These functions are helpers for Navigate() and DidNavigate(). - - // Handles post-navigation tasks in DidNavigate AFTER the entry has been - // committed to the navigation controller. Note that the navigation entry is - // not provided since it may be invalid/changed after being committed. The - // current navigation entry is in the NavigationController at this point. - void DidNavigateMainFramePostCommit( - const NavigationController::LoadCommittedDetails& details, - const ViewHostMsg_FrameNavigate_Params& params); - void DidNavigateAnyFramePostCommit( - RenderViewHost* render_view_host, - const NavigationController::LoadCommittedDetails& details, - const ViewHostMsg_FrameNavigate_Params& params); - - // Closes all constrained windows. - void CloseConstrainedWindows(); - - // Send the alternate error page URL to the renderer. This method is virtual - // so special html pages can override this (e.g., the new tab page). - virtual void UpdateAlternateErrorPageURL(); - - // Send webkit specific settings to the renderer. - void UpdateWebPreferences(); - - // Instruct the renderer to update the zoom level. - void UpdateZoomLevel(); - - // If our controller was restored and the page id is > than the site - // instance's page id, the site instances page id is updated as well as the - // renderers max page id. - void UpdateMaxPageIDIfNecessary(SiteInstance* site_instance, - RenderViewHost* rvh); - - // Returns the history::HistoryAddPageArgs to use for adding a page to - // history. - scoped_refptr<history::HistoryAddPageArgs> CreateHistoryAddPageArgs( - const GURL& virtual_url, - const NavigationController::LoadCommittedDetails& details, - const ViewHostMsg_FrameNavigate_Params& params); - - // Saves the given title to the navigation entry and does associated work. It - // will update history and the view for the new title, and also synthesize - // titles for file URLs that have none (so we require that the URL of the - // entry already be set). - // - // This is used as the backend for state updates, which include a new title, - // or the dedicated set title message. It returns true if the new title is - // different and was therefore updated. - bool UpdateTitleForEntry(NavigationEntry* entry, const std::wstring& title); - - // Causes the TabContents to navigate in the right renderer to |entry|, which - // must be already part of the entries in the navigation controller. - // This does not change the NavigationController state. - bool NavigateToEntry(const NavigationEntry& entry, - NavigationController::ReloadType reload_type); - - // Misc non-view stuff ------------------------------------------------------- - - // Helper functions for sending notifications. - void NotifySwapped(); - void NotifyConnected(); - void NotifyDisconnected(); - - // TabSpecificContentSettings::Delegate implementation. - virtual void OnContentSettingsAccessed(bool content_was_blocked); - - // RenderViewHostDelegate ---------------------------------------------------- - - // RenderViewHostDelegate implementation. - virtual RenderViewHostDelegate::View* GetViewDelegate(); - virtual RenderViewHostDelegate::RendererManagement* - GetRendererManagementDelegate(); - virtual RenderViewHostDelegate::ContentSettings* GetContentSettingsDelegate(); - virtual RenderViewHostDelegate::SSL* GetSSLDelegate(); - virtual AutomationResourceRoutingDelegate* - GetAutomationResourceRoutingDelegate(); - virtual TabContents* GetAsTabContents(); - virtual ViewType::Type GetRenderViewType() const; - virtual int GetBrowserWindowID() const; - virtual void RenderViewCreated(RenderViewHost* render_view_host); - virtual void RenderViewReady(RenderViewHost* render_view_host); - virtual void RenderViewGone(RenderViewHost* render_view_host, - base::TerminationStatus status, - int error_code); - virtual void RenderViewDeleted(RenderViewHost* render_view_host); - virtual void DidNavigate(RenderViewHost* render_view_host, - const ViewHostMsg_FrameNavigate_Params& params); - virtual void UpdateState(RenderViewHost* render_view_host, - int32 page_id, - const std::string& state); - virtual void UpdateTitle(RenderViewHost* render_view_host, - int32 page_id, - const std::wstring& title); - virtual void UpdateEncoding(RenderViewHost* render_view_host, - const std::string& encoding); - virtual void UpdateTargetURL(int32 page_id, const GURL& url); - virtual void UpdateThumbnail(const GURL& url, - const SkBitmap& bitmap, - const ThumbnailScore& score); - virtual void UpdateInspectorSetting(const std::string& key, - const std::string& value); - virtual void ClearInspectorSettings(); - virtual void Close(RenderViewHost* render_view_host); - virtual void RequestMove(const gfx::Rect& new_bounds); - virtual void DidStartLoading(); - virtual void DidStopLoading(); - virtual void DidChangeLoadProgress(double progress); - virtual void DocumentOnLoadCompletedInMainFrame( - RenderViewHost* render_view_host, - int32 page_id); - virtual void RequestOpenURL(const GURL& url, const GURL& referrer, - WindowOpenDisposition disposition); - virtual void DomOperationResponse(const std::string& json_string, - int automation_id); - virtual void ProcessWebUIMessage(const ViewHostMsg_DomMessage_Params& params); - virtual void ProcessExternalHostMessage(const std::string& message, - const std::string& origin, - const std::string& target); - virtual void RunJavaScriptMessage(const std::wstring& message, - const std::wstring& default_prompt, - const GURL& frame_url, - const int flags, - IPC::Message* reply_msg, - bool* did_suppress_message); - virtual void RunBeforeUnloadConfirm(const std::wstring& message, - IPC::Message* reply_msg); - virtual void ShowModalHTMLDialog(const GURL& url, int width, int height, - const std::string& json_arguments, - IPC::Message* reply_msg); - virtual GURL GetAlternateErrorPageURL() const; - virtual RendererPreferences GetRendererPrefs(Profile* profile) const; - virtual WebPreferences GetWebkitPrefs(); - virtual void OnUserGesture(); - virtual void OnIgnoredUIEvent(); - virtual void OnJSOutOfMemory(); - virtual void OnCrossSiteResponse(int new_render_process_host_id, - int new_request_id); - virtual void RendererUnresponsive(RenderViewHost* render_view_host, - bool is_during_unload); - virtual void RendererResponsive(RenderViewHost* render_view_host); - virtual void LoadStateChanged(const GURL& url, net::LoadState load_state, - uint64 upload_position, uint64 upload_size); - virtual bool IsExternalTabContainer() const; - virtual void DidInsertCSS(); - virtual void FocusedNodeChanged(bool is_editable_node); - virtual void UpdateZoomLimits(int minimum_percent, - int maximum_percent, - bool remember); - virtual void WorkerCrashed(); - - // RenderViewHostManager::Delegate ------------------------------------------- - - // Blocks/unblocks interaction with renderer process. - void BlockTabContent(bool blocked); - - virtual void BeforeUnloadFiredFromRenderManager( - bool proceed, - bool* proceed_to_fire_unload); - virtual void DidStartLoadingFromRenderManager( - RenderViewHost* render_view_host); - virtual void RenderViewGoneFromRenderManager( - RenderViewHost* render_view_host); - virtual void UpdateRenderViewSizeForRenderManager(); - virtual void NotifySwappedFromRenderManager(); - virtual NavigationController& GetControllerForRenderManager(); - virtual WebUI* CreateWebUIForRenderManager(const GURL& url); - virtual NavigationEntry* GetLastCommittedNavigationEntryForRenderManager(); - - // Initializes the given renderer if necessary and creates the view ID - // corresponding to this view host. If this method is not called and the - // process is not shared, then the TabContents will act as though the renderer - // is not running (i.e., it will render "sad tab"). This method is - // automatically called from LoadURL. - // - // If you are attaching to an already-existing RenderView, you should call - // InitWithExistingID. - virtual bool CreateRenderViewForRenderManager( - RenderViewHost* render_view_host); - - // NotificationObserver ------------------------------------------------------ - - virtual void Observe(NotificationType type, - const NotificationSource& source, - const NotificationDetails& details); - - // App extensions related methods: - - // Returns the first extension whose extent contains |url|. - const Extension* GetExtensionContaining(const GURL& url); - - // Resets app_icon_ and if |extension| is non-null creates a new - // ImageLoadingTracker to load the extension's image. - void UpdateExtensionAppIcon(const Extension* extension); - - // ImageLoadingTracker::Observer. - virtual void OnImageLoaded(SkBitmap* image, ExtensionResource resource, - int index); - - // Checks with the PrerenderManager if the specified URL has been preloaded, - // and if so, swap the RenderViewHost with the preload into this TabContents - // object. - bool MaybeUsePreloadedPage(const GURL& url); - - // Data for core operation --------------------------------------------------- - - // Delegate for notifying our owner about stuff. Not owned by us. - TabContentsDelegate* delegate_; - - // Handles the back/forward list and loading. - NavigationController controller_; - - // The corresponding view. - scoped_ptr<TabContentsView> view_; - - // Helper classes ------------------------------------------------------------ - - // Manages creation and swapping of render views. - RenderViewHostManager render_manager_; - - // Stores random bits of data for others to associate with this object. - PropertyBag property_bag_; - - // Registers and unregisters us for notifications. - NotificationRegistrar registrar_; - - // Registers and unregisters for pref notifications. - PrefChangeRegistrar pref_change_registrar_; - - // Handles print job for this contents. - scoped_ptr<printing::PrintViewManager> printing_; - - // Handles print preview for this contents. - scoped_ptr<printing::PrintPreviewMessageHandler> print_preview_; - - // SavePackage, lazily created. - scoped_refptr<SavePackage> save_package_; - - // AutocompleteHistoryManager. - scoped_ptr<AutocompleteHistoryManager> autocomplete_history_manager_; - - // AutoFillManager. - scoped_ptr<AutoFillManager> autofill_manager_; - - // Handles plugin messages. - scoped_ptr<PluginObserver> plugin_observer_; - - // Prerender PageLoadTime Recorder. - scoped_ptr<prerender::PrerenderPLTRecorder> prerender_plt_recorder_; - - // TabContentsSSLHelper, lazily created. - scoped_ptr<TabContentsSSLHelper> ssl_helper_; - - // FileSelectHelper, lazily created. - scoped_ptr<FileSelectHelper> file_select_helper_; - - // Handles drag and drop event forwarding to extensions. - BookmarkDrag* bookmark_drag_; - - // Handles downloading favicons. - scoped_ptr<FavIconHelper> fav_icon_helper_; - - // Cached web app info data. - WebApplicationInfo web_app_info_; - - // Cached web app icon. - SkBitmap app_icon_; - - // RenderViewHost::ContentSettingsDelegate. - scoped_ptr<TabSpecificContentSettings> content_settings_delegate_; - - // Handles desktop notification IPCs. - scoped_ptr<DesktopNotificationHandlerForTC> desktop_notification_handler_; - - // Handles IPCs related to SafeBrowsing client-side phishing detection. - scoped_ptr<safe_browsing::ClientSideDetectionHost> - safebrowsing_detection_host_; - - // Data for loading state ---------------------------------------------------- - - // Indicates whether we're currently loading a resource. - bool is_loading_; - - // Indicates if the tab is considered crashed. - base::TerminationStatus crashed_status_; - int crashed_error_code_; - - // See waiting_for_response() above. - bool waiting_for_response_; - - // Indicates the largest PageID we've seen. This field is ignored if we are - // a TabContents, in which case the max page ID is stored separately with - // each SiteInstance. - // TODO(brettw) this seems like it can be removed according to the comment. - int32 max_page_id_; - - // System time at which the current load was started. - base::TimeTicks current_load_start_; - - // The current load state and the URL associated with it. - net::LoadState load_state_; - string16 load_state_host_; - // Upload progress, for displaying in the status bar. - // Set to zero when there is no significant upload happening. - uint64 upload_size_; - uint64 upload_position_; - - // Data for current page ----------------------------------------------------- - - // Whether we have a (non-empty) title for the current page. - // Used to prevent subsequent title updates from affecting history. This - // prevents some weirdness because some AJAXy apps use titles for status - // messages. - bool received_page_title_; - - // When a navigation occurs, we record its contents MIME type. It can be - // used to check whether we can do something for some special contents. - std::string contents_mime_type_; - - // Character encoding. - std::string encoding_; - - // Object that holds any blocked TabContents spawned from this TabContents. - BlockedContentContainer* blocked_contents_; - - // Should we block all child TabContents this attempts to spawn. - bool all_contents_blocked_; - - // TODO(pkasting): Hack to try and fix Linux browser tests. - bool dont_notify_render_view_; - - // True if this is a secure page which displayed insecure content. - bool displayed_insecure_content_; - - // Data for shelves and stuff ------------------------------------------------ - - // Delegates for InfoBars associated with this TabContents. - std::vector<InfoBarDelegate*> infobar_delegates_; - - // Data for app extensions --------------------------------------------------- - - // If non-null this tab is an app tab and this is the extension the tab was - // created for. - const Extension* extension_app_; - - // Icon for extension_app_ (if non-null) or extension_for_current_page_. - SkBitmap extension_app_icon_; - - // Used for loading extension_app_icon_. - scoped_ptr<ImageLoadingTracker> extension_app_image_loader_; - - // Data for misc internal state ---------------------------------------------- - - // See capturing_contents() above. - bool capturing_contents_; - - // See getter above. - bool is_being_destroyed_; - - // Indicates whether we should notify about disconnection of this - // TabContents. This is used to ensure disconnection notifications only - // happen if a connection notification has happened and that they happen only - // once. - bool notify_disconnection_; - - // Maps from handle to page_id. - typedef std::map<FaviconService::Handle, int32> HistoryRequestMap; - HistoryRequestMap history_requests_; - -#if defined(OS_WIN) - // Handle to an event that's set when the page is showing a message box (or - // equivalent constrained window). Plugin processes check this to know if - // they should pump messages then. - base::win::ScopedHandle message_box_active_; -#endif - - // The time that the last javascript message was dismissed. - base::TimeTicks last_javascript_message_dismissal_; - - // True if the user has decided to block future javascript messages. This is - // reset on navigations to false on navigations. - bool suppress_javascript_messages_; - - // Set to true when there is an active "before unload" dialog. When true, - // we've forced the throbber to start in Navigate, and we need to remember to - // turn it off in OnJavaScriptMessageBoxClosed if the navigation is canceled. - bool is_showing_before_unload_dialog_; - - // Shows an info-bar to users when they search from a known search engine and - // have never used the monibox for search before. - scoped_ptr<OmniboxSearchHint> omnibox_search_hint_; - - // Settings that get passed to the renderer process. - RendererPreferences renderer_preferences_; - - // If this tab was created from a renderer using window.open, this will be - // non-NULL and represent the WebUI of the opening renderer. - WebUITypeID opener_web_ui_type_; - - // The time that we started to create the new tab page. - base::TimeTicks new_tab_start_time_; - - // The time that we started to close the tab. - base::TimeTicks tab_close_start_time_; - - // The time that this tab was last selected. - base::TimeTicks last_selected_time_; - - // Information about the language the page is in and has been translated to. - LanguageState language_state_; - - // See description above setter. - bool closed_by_user_gesture_; - - // Minimum/maximum zoom percent. - int minimum_zoom_percent_; - int maximum_zoom_percent_; - // If true, the default zoom limits have been overriden for this tab, in which - // case we don't want saved settings to apply to it and we don't want to - // remember it. - bool temporary_zoom_settings_; - - // A list of observers notified when page state changes. Weak references. - ObserverList<TabContentsObserver> observers_; - - // Content restrictions, used to disable print/copy etc based on content's - // (full-page plugins for now only) permissions. - int content_restrictions_; - - DISALLOW_COPY_AND_ASSIGN(TabContents); -}; +// TODO(jam): remove this file when all files have been converted. +#include "content/browser/tab_contents/tab_contents.h" #endif // CHROME_BROWSER_TAB_CONTENTS_TAB_CONTENTS_H_ diff --git a/chrome/browser/tab_contents/tab_contents_delegate.cc b/chrome/browser/tab_contents/tab_contents_delegate.cc deleted file mode 100644 index 7b0dc4b..0000000 --- a/chrome/browser/tab_contents/tab_contents_delegate.cc +++ /dev/null @@ -1,224 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/tab_contents/tab_contents_delegate.h" - -#include "chrome/common/url_constants.h" -#include "ui/gfx/rect.h" - -std::string TabContentsDelegate::GetNavigationHeaders(const GURL& url) { - return std::string(); -} - -void TabContentsDelegate::LoadProgressChanged(double progress) { -} - -void TabContentsDelegate::DetachContents(TabContents* source) { -} - -bool TabContentsDelegate::IsPopup(const TabContents* source) const { - return false; -} - -TabContents* TabContentsDelegate::GetConstrainingContents(TabContents* source) { - return source; -} - -bool TabContentsDelegate::ShouldFocusConstrainedWindow() { - return true; -} - -void TabContentsDelegate::WillShowConstrainedWindow(TabContents* source) { -} - -void TabContentsDelegate::ContentsMouseEvent( - TabContents* source, const gfx::Point& location, bool motion) { -} - -void TabContentsDelegate::ContentsZoomChange(bool zoom_in) { } - -void TabContentsDelegate::OnContentSettingsChange(TabContents* source) { } - -bool TabContentsDelegate::IsApplication() const { return false; } - -void TabContentsDelegate::ConvertContentsToApplication(TabContents* source) { } - -bool TabContentsDelegate::CanReloadContents(TabContents* source) const { - return true; -} - -void TabContentsDelegate::ShowHtmlDialog(HtmlDialogUIDelegate* delegate, - gfx::NativeWindow parent_window) { -} - -void TabContentsDelegate::WillRunBeforeUnloadConfirm() { -} - -bool TabContentsDelegate::ShouldSuppressDialogs() { - return false; -} - -void TabContentsDelegate::BeforeUnloadFired(TabContents* tab, - bool proceed, - bool* proceed_to_fire_unload) { - *proceed_to_fire_unload = true; -} - -void TabContentsDelegate::ForwardMessageToExternalHost( - const std::string& message, - const std::string& origin, - const std::string& target) { -} - -bool TabContentsDelegate::IsExternalTabContainer() const { return false; } - -void TabContentsDelegate::SetFocusToLocationBar(bool select_all) {} - -bool TabContentsDelegate::ShouldFocusPageAfterCrash() { - return true; -} - -void TabContentsDelegate::RenderWidgetShowing() {} - -bool TabContentsDelegate::TakeFocus(bool reverse) { - return false; -} - -void TabContentsDelegate::LostCapture() { -} - -void TabContentsDelegate::SetTabContentBlocked( - TabContents* contents, bool blocked) { -} - -void TabContentsDelegate::TabContentsFocused(TabContents* tab_content) { -} - -int TabContentsDelegate::GetExtraRenderViewHeight() const { - return 0; -} - -bool TabContentsDelegate::CanDownload(int request_id) { - return true; -} - -void TabContentsDelegate::OnStartDownload(DownloadItem* download, - TabContents* tab) { -} - -bool TabContentsDelegate::HandleContextMenu(const ContextMenuParams& params) { - return false; -} - -bool TabContentsDelegate::ExecuteContextMenuCommand(int command) { - return false; -} - -void TabContentsDelegate::ShowPageInfo(Profile* profile, - const GURL& url, - const NavigationEntry::SSLStatus& ssl, - bool show_history) { -} - -void TabContentsDelegate::ViewSourceForTab(TabContents* source, - const GURL& page_url) { - // Fall back implementation based entirely on the view-source scheme. - // It suffers from http://crbug.com/523 and that is why browser overrides - // it with proper implementation. - GURL url = GURL(chrome::kViewSourceScheme + std::string(":") + - page_url.spec()); - OpenURLFromTab(source, - url, - GURL(), - NEW_FOREGROUND_TAB, - PageTransition::LINK); -} - -bool TabContentsDelegate::PreHandleKeyboardEvent( - const NativeWebKeyboardEvent& event, - bool* is_keyboard_shortcut) { - return false; -} - -void TabContentsDelegate::HandleKeyboardEvent( - const NativeWebKeyboardEvent& event) { -} - -void TabContentsDelegate::HandleMouseUp() { -} - -void TabContentsDelegate::HandleMouseActivate() { -} - -void TabContentsDelegate::DragEnded() { -} - -void TabContentsDelegate::ShowRepostFormWarningDialog( - TabContents* tab_contents) { -} - -void TabContentsDelegate::ShowContentSettingsWindow( - ContentSettingsType content_type) { -} - -void TabContentsDelegate::ShowCollectedCookiesDialog( - TabContents* tab_contents) { -} - -bool TabContentsDelegate::OnGoToEntryOffset(int offset) { - return true; -} - -bool TabContentsDelegate::ShouldAddNavigationToHistory( - const history::HistoryAddPageArgs& add_page_args, - NavigationType::Type navigation_type) { - return true; -} - -void TabContentsDelegate::OnDidGetApplicationInfo(TabContents* tab_contents, - int32 page_id) { -} - -// Notification when an application programmatically requests installation. -void TabContentsDelegate::OnInstallApplication( - TabContents* tab_contents, - const WebApplicationInfo& app_info) { -} - -gfx::NativeWindow TabContentsDelegate::GetFrameNativeWindow() { - return NULL; -} - -void TabContentsDelegate::TabContentsCreated(TabContents* new_contents) { -} - -bool TabContentsDelegate::infobars_enabled() { - return true; -} - -bool TabContentsDelegate::ShouldEnablePreferredSizeNotifications() { - return false; -} - -void TabContentsDelegate::UpdatePreferredSize(const gfx::Size& pref_size) { -} - -void TabContentsDelegate::OnSetSuggestions( - int32 page_id, - const std::vector<std::string>& suggestions) { -} - -void TabContentsDelegate::OnInstantSupportDetermined(int32 page_id, - bool result) { -} - -void TabContentsDelegate::ContentRestrictionsChanged(TabContents* source) { -} - -bool TabContentsDelegate::ShouldShowHungRendererDialog() { - return true; -} - -TabContentsDelegate::~TabContentsDelegate() { -} diff --git a/chrome/browser/tab_contents/tab_contents_delegate.h b/chrome/browser/tab_contents/tab_contents_delegate.h index 10891a5..23d5803 100644 --- a/chrome/browser/tab_contents/tab_contents_delegate.h +++ b/chrome/browser/tab_contents/tab_contents_delegate.h @@ -6,323 +6,7 @@ #define CHROME_BROWSER_TAB_CONTENTS_TAB_CONTENTS_DELEGATE_H_ #pragma once -#include <string> -#include <vector> - -#include "base/basictypes.h" -#include "chrome/browser/automation/automation_resource_routing_delegate.h" -#include "chrome/browser/tab_contents/navigation_entry.h" -#include "chrome/common/content_settings_types.h" -#include "chrome/common/navigation_types.h" -#include "chrome/common/page_transition_types.h" -#include "ui/gfx/native_widget_types.h" -#include "webkit/glue/window_open_disposition.h" - -namespace gfx { -class Point; -class Rect; -class Size; -} - -namespace history { -class HistoryAddPageArgs; -} - -struct ContextMenuParams; -class DownloadItem; -class GURL; -class HtmlDialogUIDelegate; -struct NativeWebKeyboardEvent; -class Profile; -class RenderViewHost; -class TabContents; -struct WebApplicationInfo; - -// Objects implement this interface to get notified about changes in the -// TabContents and to provide necessary functionality. -class TabContentsDelegate : public AutomationResourceRoutingDelegate { - public: - // Opens a new URL inside the passed in TabContents (if source is 0 open - // in the current front-most tab), unless |disposition| indicates the url - // should be opened in a new tab or window. - // - // A NULL source indicates the current tab (callers should probably use - // OpenURL() for these cases which does it for you). - virtual void OpenURLFromTab(TabContents* source, - const GURL& url, const GURL& referrer, - WindowOpenDisposition disposition, - PageTransition::Type transition) = 0; - - // Called to inform the delegate that the tab content's navigation state - // changed. The |changed_flags| indicates the parts of the navigation state - // that have been updated, and is any combination of the - // |TabContents::InvalidateTypes| bits. - virtual void NavigationStateChanged(const TabContents* source, - unsigned changed_flags) = 0; - - // Returns the set of headers to add to the navigation request. Use - // net::HttpUtil::AppendHeaderIfMissing to build the set of headers. - virtual std::string GetNavigationHeaders(const GURL& url); - - // Creates a new tab with the already-created TabContents 'new_contents'. - // The window for the added contents should be reparented correctly when this - // method returns. If |disposition| is NEW_POPUP, |pos| should hold the - // initial position. - virtual void AddNewContents(TabContents* source, - TabContents* new_contents, - WindowOpenDisposition disposition, - const gfx::Rect& initial_pos, - bool user_gesture) = 0; - - // Selects the specified contents, bringing its container to the front. - virtual void ActivateContents(TabContents* contents) = 0; - - // Deactivates the specified contents by deactivating its container and - // potentialy moving it to the back of the Z order. - virtual void DeactivateContents(TabContents* contents) = 0; - - // Notifies the delegate that this contents is starting or is done loading - // some resource. The delegate should use this notification to represent - // loading feedback. See TabContents::is_loading() - virtual void LoadingStateChanged(TabContents* source) = 0; - - // Notifies the delegate that the page has made some progress loading. - // |progress| is a value between 0.0 (nothing loaded) to 1.0 (page fully - // loaded). - // Note that to receive this notification, you must have called - // SetReportLoadProgressEnabled(true) in the render view. - virtual void LoadProgressChanged(double progress); - - // Request the delegate to close this tab contents, and do whatever cleanup - // it needs to do. - virtual void CloseContents(TabContents* source) = 0; - - // Request the delegate to move this tab contents to the specified position - // in screen coordinates. - virtual void MoveContents(TabContents* source, const gfx::Rect& pos) = 0; - - // Causes the delegate to detach |source| and clean up any internal data - // pointing to it. After this call ownership of |source| passes to the - // caller, and it is safe to call "source->set_delegate(someone_else);". - virtual void DetachContents(TabContents* source); - - // Called to determine if the TabContents is contained in a popup window. - virtual bool IsPopup(const TabContents* source) const; - - // If |source| is constrained, returns the tab containing it. Otherwise - // returns |source|. - virtual TabContents* GetConstrainingContents(TabContents* source); - - // Returns true if constrained windows should be focused. Default is true. - virtual bool ShouldFocusConstrainedWindow(); - - // Invoked prior to the TabContents showing a constrained window. - virtual void WillShowConstrainedWindow(TabContents* source); - - // Notification that some of our content has changed size as - // part of an animation. - virtual void ToolbarSizeChanged(TabContents* source, bool is_animating) = 0; - - // Notification that the target URL has changed. - virtual void UpdateTargetURL(TabContents* source, const GURL& url) = 0; - - // Notification that there was a mouse event, along with the absolute - // coordinates of the mouse pointer and whether it was a normal motion event - // (otherwise, the pointer left the contents area). - virtual void ContentsMouseEvent( - TabContents* source, const gfx::Point& location, bool motion); - - // Request the delegate to change the zoom level of the current tab. - virtual void ContentsZoomChange(bool zoom_in); - - // Notifies the delegate that something has changed about what content the - // TabContents is blocking. Interested parties should call - // TabContents::IsContentBlocked() to see if something they care about has - // changed. - virtual void OnContentSettingsChange(TabContents* source); - - // Check whether this contents is inside a window dedicated to running a web - // application. - virtual bool IsApplication() const; - - // Detach the given tab and convert it to a "webapp" view. The tab must be - // a TabContents with a valid WebApp set. - virtual void ConvertContentsToApplication(TabContents* source); - - // Whether the specified tab can be reloaded. - // Reloading can be disabled e. g. for the DevTools window. - virtual bool CanReloadContents(TabContents* source) const; - - // Show a dialog with HTML content. |delegate| contains a pointer to the - // delegate who knows how to display the dialog (which file URL and JSON - // string input to use during initialization). |parent_window| is the window - // that should be parent of the dialog, or NULL for the default. - virtual void ShowHtmlDialog(HtmlDialogUIDelegate* delegate, - gfx::NativeWindow parent_window); - - // Invoked prior to showing before unload handler confirmation dialog. - virtual void WillRunBeforeUnloadConfirm(); - - // Returns true if javascript dialogs and unload alerts are suppressed. - // Default is false. - virtual bool ShouldSuppressDialogs(); - - // Tells us that we've finished firing this tab's beforeunload event. - // The proceed bool tells us whether the user chose to proceed closing the - // tab. Returns true if the tab can continue on firing it's unload event. - // If we're closing the entire browser, then we'll want to delay firing - // unload events until all the beforeunload events have fired. - virtual void BeforeUnloadFired(TabContents* tab, - bool proceed, - bool* proceed_to_fire_unload); - - // Send IPC to external host. Default implementation is do nothing. - virtual void ForwardMessageToExternalHost(const std::string& message, - const std::string& origin, - const std::string& target); - - // If the delegate is hosting tabs externally. - virtual bool IsExternalTabContainer() const; - - // Sets focus to the location bar or some other place that is appropriate. - // This is called when the tab wants to encourage user input, like for the - // new tab page. - virtual void SetFocusToLocationBar(bool select_all); - - // Returns whether the page should be focused when transitioning from crashed - // to live. Default is true. - virtual bool ShouldFocusPageAfterCrash(); - - // Called when a popup select is about to be displayed. The delegate can use - // this to disable inactive rendering for the frame in the window the select - // is opened within if necessary. - virtual void RenderWidgetShowing(); - - // This is called when WebKit tells us that it is done tabbing through - // controls on the page. Provides a way for TabContentsDelegates to handle - // this. Returns true if the delegate successfully handled it. - virtual bool TakeFocus(bool reverse); - - // Invoked when the page loses mouse capture. - virtual void LostCapture(); - - // Changes the blocked state of the tab at |index|. TabContents are - // considered blocked while displaying a tab modal dialog. During that time - // renderer host will ignore any UI interaction within TabContent outside of - // the currently displaying dialog. - virtual void SetTabContentBlocked(TabContents* contents, bool blocked); - - // Notification that |tab_contents| has gained focus. - virtual void TabContentsFocused(TabContents* tab_content); - - // Return much extra vertical space should be allotted to the - // render view widget during various animations (e.g. infobar closing). - // This is used to make painting look smoother. - virtual int GetExtraRenderViewHeight() const; - - virtual bool CanDownload(int request_id); - - virtual void OnStartDownload(DownloadItem* download, TabContents* tab); - - // Returns true if the context menu operation was handled by the delegate. - virtual bool HandleContextMenu(const ContextMenuParams& params); - - // Returns true if the context menu command was handled - virtual bool ExecuteContextMenuCommand(int command); - - // Shows the page info using the specified information. - // |url| is the url of the page/frame the info applies to, |ssl| is the SSL - // information for that page/frame. If |show_history| is true, a section - // showing how many times that URL has been visited is added to the page info. - virtual void ShowPageInfo(Profile* profile, - const GURL& url, - const NavigationEntry::SSLStatus& ssl, - bool show_history); - - // Opens source view for given tab contents that is navigated to the given - // page url. - virtual void ViewSourceForTab(TabContents* source, const GURL& page_url); - - // Allows delegates to handle keyboard events before sending to the renderer. - // Returns true if the |event| was handled. Otherwise, if the |event| would be - // handled in HandleKeyboardEvent() method as a normal keyboard shortcut, - // |*is_keyboard_shortcut| should be set to true. - virtual bool PreHandleKeyboardEvent(const NativeWebKeyboardEvent& event, - bool* is_keyboard_shortcut); - - // Allows delegates to handle unhandled keyboard messages coming back from - // the renderer. - virtual void HandleKeyboardEvent(const NativeWebKeyboardEvent& event); - - virtual void HandleMouseUp(); - virtual void HandleMouseActivate(); - - // Render view drag n drop ended. - virtual void DragEnded(); - - // Shows the repost form confirmation dialog box. - virtual void ShowRepostFormWarningDialog(TabContents* tab_contents); - - // Shows the Content Settings dialog for a given content type. - virtual void ShowContentSettingsWindow(ContentSettingsType content_type); - - // Shows the cookies collected in the tab contents. - virtual void ShowCollectedCookiesDialog(TabContents* tab_contents); - - // Allows delegate to override navigation to the history entries. - // Returns true to allow TabContents to continue with the default processing. - virtual bool OnGoToEntryOffset(int offset); - - // Returns whether this tab contents should add the specified navigation to - // history. - virtual bool ShouldAddNavigationToHistory( - const history::HistoryAddPageArgs& add_page_args, - NavigationType::Type navigation_type); - - // Notification that a user's request to install an application has completed. - virtual void OnDidGetApplicationInfo(TabContents* tab_contents, - int32 page_id); - - // Notification when an application programmatically requests installation. - virtual void OnInstallApplication(TabContents* tab_contents, - const WebApplicationInfo& app_info); - - // Returns the native window framing the view containing the tab contents. - virtual gfx::NativeWindow GetFrameNativeWindow(); - - // Notifies the delegate about the creation of a new TabContents. This - // typically happens when popups are created. - virtual void TabContentsCreated(TabContents* new_contents); - - // Returns whether infobars are enabled. Overrideable by child classes. - virtual bool infobars_enabled(); - - // Whether the renderer should report its preferred size when it changes by - // calling UpdatePreferredSize(). - // Note that this is set when the RenderViewHost is created and cannot be - // changed after that. - virtual bool ShouldEnablePreferredSizeNotifications(); - - // Notification that the preferred size of the contents has changed. - // Only called if ShouldEnablePreferredSizeNotifications() returns true. - virtual void UpdatePreferredSize(const gfx::Size& pref_size); - - // Notifies the delegate that the page has a suggest result. - virtual void OnSetSuggestions(int32 page_id, - const std::vector<std::string>& result); - - // Notifies the delegate whether the page supports instant-style interaction. - virtual void OnInstantSupportDetermined(int32 page_id, bool result); - - // Notifies the delegate that the content restrictions for this tab has - // changed. - virtual void ContentRestrictionsChanged(TabContents* source); - - // Returns true if the hung renderer dialog should be shown. Default is true. - virtual bool ShouldShowHungRendererDialog(); - - protected: - virtual ~TabContentsDelegate(); -}; +// TODO(jam): remove this file when all files have been converted. +#include "content/browser/tab_contents/tab_contents_delegate.h" #endif // CHROME_BROWSER_TAB_CONTENTS_TAB_CONTENTS_DELEGATE_H_ diff --git a/chrome/browser/tab_contents/tab_contents_observer.cc b/chrome/browser/tab_contents/tab_contents_observer.cc deleted file mode 100644 index 738539a..0000000 --- a/chrome/browser/tab_contents/tab_contents_observer.cc +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/tab_contents/tab_contents_observer.h" - -#include "chrome/browser/renderer_host/render_view_host.h" -#include "chrome/browser/tab_contents/tab_contents.h" - -TabContentsObserver::TabContentsObserver(TabContents* tab_contents) - : tab_contents_(tab_contents), - routing_id_(tab_contents->render_view_host()->routing_id()) { - tab_contents_->AddObserver(this); -} - -TabContentsObserver::~TabContentsObserver() { - if (tab_contents_) - tab_contents_->RemoveObserver(this); -} - -bool TabContentsObserver::OnMessageReceived(const IPC::Message& message) { - return false; -} - -bool TabContentsObserver::Send(IPC::Message* message) { - if (!tab_contents_->render_view_host()) { - delete message; - return false; - } - - return tab_contents_->render_view_host()->Send(message); -} diff --git a/chrome/browser/tab_contents/tab_contents_observer.h b/chrome/browser/tab_contents/tab_contents_observer.h index 55a609c..0af56b32 100644 --- a/chrome/browser/tab_contents/tab_contents_observer.h +++ b/chrome/browser/tab_contents/tab_contents_observer.h @@ -5,65 +5,7 @@ #ifndef CHROME_BROWSER_TAB_CONTENTS_TAB_CONTENTS_OBSERVER_H_ #define CHROME_BROWSER_TAB_CONTENTS_TAB_CONTENTS_OBSERVER_H_ -#include "chrome/browser/tab_contents/navigation_controller.h" -#include "ipc/ipc_channel.h" - -struct ViewHostMsg_FrameNavigate_Params; - -// An observer API implemented by classes which are interested in various page -// load events from TabContents. They also get a chance to filter IPC messages. -class TabContentsObserver : public IPC::Channel::Listener { - public: - virtual void NavigateToPendingEntry() { } - - virtual void DidNavigateMainFramePostCommit( - const NavigationController::LoadCommittedDetails& details, - const ViewHostMsg_FrameNavigate_Params& params) { } - virtual void DidNavigateAnyFramePostCommit( - const NavigationController::LoadCommittedDetails& details, - const ViewHostMsg_FrameNavigate_Params& params) { } - - virtual void DidStartLoading() { } - virtual void DidStopLoading() { } - -#if 0 - // For unifying with delegate... - - // Notifies the delegate that this contents is starting or is done loading - // some resource. The delegate should use this notification to represent - // loading feedback. See TabContents::is_loading() - virtual void LoadingStateChanged(TabContents* contents) { } - // Called to inform the delegate that the tab content's navigation state - // changed. The |changed_flags| indicates the parts of the navigation state - // that have been updated, and is any combination of the - // |TabContents::InvalidateTypes| bits. - virtual void NavigationStateChanged(const TabContents* source, - unsigned changed_flags) { } -#endif - - protected: - TabContentsObserver(TabContents* tab_contents); - virtual ~TabContentsObserver(); - - // IPC::Channel::Listener implementation. - virtual bool OnMessageReceived(const IPC::Message& message); - - // IPC::Message::Sender implementation. - virtual bool Send(IPC::Message* message); - - TabContents* tab_contents() { return tab_contents_; } - int routing_id() { return routing_id_; } - - private: - friend class TabContents; - - void set_tab_contents(TabContents* tc) { tab_contents_ = tc; } - - TabContents* tab_contents_; - // The routing ID of the associated TabContents. - int routing_id_; - - DISALLOW_COPY_AND_ASSIGN(TabContentsObserver); -}; +// TODO(jam): remove this file when all files have been converted. +#include "content/browser/tab_contents/tab_contents_observer.h" #endif // CHROME_BROWSER_TAB_CONTENTS_TAB_CONTENTS_OBSERVER_H_ diff --git a/chrome/browser/tab_contents/tab_contents_view.cc b/chrome/browser/tab_contents/tab_contents_view.cc deleted file mode 100644 index 9574a56..0000000 --- a/chrome/browser/tab_contents/tab_contents_view.cc +++ /dev/null @@ -1,169 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/tab_contents/tab_contents_view.h" - -#include "chrome/browser/renderer_host/render_process_host.h" -#include "chrome/browser/renderer_host/render_view_host.h" -#include "chrome/browser/renderer_host/render_widget_host.h" -#include "chrome/browser/renderer_host/render_view_host_delegate.h" -#include "chrome/browser/renderer_host/render_widget_host_view.h" -#include "chrome/browser/tab_contents/tab_contents.h" -#include "chrome/browser/tab_contents/tab_contents_delegate.h" -#include "chrome/common/notification_service.h" -#include "chrome/common/render_messages_params.h" - -TabContentsView::TabContentsView(TabContents* tab_contents) - : tab_contents_(tab_contents) { -} - -TabContentsView::~TabContentsView() {} - -void TabContentsView::RenderWidgetHostDestroyed(RenderWidgetHost* host) { - if (host->view()) - host->view()->WillDestroyRenderWidget(host); - delegate_view_helper_.RenderWidgetHostDestroyed(host); -} - -void TabContentsView::RenderViewCreated(RenderViewHost* host) { - // Default implementation does nothing. Platforms may override. -} - -void TabContentsView::CreateNewWindow( - int route_id, - const ViewHostMsg_CreateWindow_Params& params) { - TabContents* new_contents = delegate_view_helper_.CreateNewWindow( - route_id, - tab_contents_->profile(), - tab_contents_->GetSiteInstance(), - WebUIFactory::GetWebUIType(tab_contents_->profile(), - tab_contents_->GetURL()), - tab_contents_, - params.window_container_type, - params.frame_name); - - if (new_contents) { - NotificationService::current()->Notify( - NotificationType::CREATING_NEW_WINDOW, - Source<TabContents>(tab_contents_), - Details<const ViewHostMsg_CreateWindow_Params>(¶ms)); - - if (tab_contents_->delegate()) - tab_contents_->delegate()->TabContentsCreated(new_contents); - } -} - -void TabContentsView::CreateNewWidget(int route_id, - WebKit::WebPopupType popup_type) { - CreateNewWidgetInternal(route_id, popup_type); -} - -void TabContentsView::CreateNewFullscreenWidget(int route_id) { - CreateNewFullscreenWidgetInternal(route_id); -} - -void TabContentsView::ShowCreatedWindow(int route_id, - WindowOpenDisposition disposition, - const gfx::Rect& initial_pos, - bool user_gesture) { - TabContents* contents = delegate_view_helper_.GetCreatedWindow(route_id); - if (contents) { - tab_contents()->AddNewContents(contents, disposition, initial_pos, - user_gesture); - } -} - -void TabContentsView::ShowCreatedWidget(int route_id, - const gfx::Rect& initial_pos) { - RenderWidgetHostView* widget_host_view = - delegate_view_helper_.GetCreatedWidget(route_id); - ShowCreatedWidgetInternal(widget_host_view, initial_pos); -} - -void TabContentsView::Activate() { - tab_contents_->Activate(); -} - -void TabContentsView::Deactivate() { - tab_contents_->Deactivate(); -} - -void TabContentsView::ShowCreatedFullscreenWidget(int route_id) { - RenderWidgetHostView* widget_host_view = - delegate_view_helper_.GetCreatedWidget(route_id); - ShowCreatedFullscreenWidgetInternal(widget_host_view); -} - -void TabContentsView::LostCapture() { - if (tab_contents_->delegate()) - tab_contents_->delegate()->LostCapture(); -} - -bool TabContentsView::PreHandleKeyboardEvent( - const NativeWebKeyboardEvent& event, bool* is_keyboard_shortcut) { - return tab_contents_->delegate() && - tab_contents_->delegate()->PreHandleKeyboardEvent( - event, is_keyboard_shortcut); -} - -void TabContentsView::UpdatePreferredSize(const gfx::Size& pref_size) { - if (tab_contents_->delegate()) - tab_contents_->delegate()->UpdatePreferredSize(pref_size); -} - -bool TabContentsView::IsDoingDrag() const { - return false; -} - -bool TabContentsView::IsEventTracking() const { - return false; -} - -TabContentsView::TabContentsView() : tab_contents_(NULL) {} - -void TabContentsView::HandleKeyboardEvent(const NativeWebKeyboardEvent& event) { - if (tab_contents_->delegate()) - tab_contents_->delegate()->HandleKeyboardEvent(event); -} - -void TabContentsView::HandleMouseUp() { - if (tab_contents_->delegate()) - tab_contents_->delegate()->HandleMouseUp(); -} - -void TabContentsView::HandleMouseActivate() { - if (tab_contents_->delegate()) - tab_contents_->delegate()->HandleMouseActivate(); -} - -RenderWidgetHostView* TabContentsView::CreateNewWidgetInternal( - int route_id, WebKit::WebPopupType popup_type) { - return delegate_view_helper_.CreateNewWidget(route_id, popup_type, - tab_contents()->render_view_host()->process()); -} - -RenderWidgetHostView* TabContentsView::CreateNewFullscreenWidgetInternal( - int route_id) { - return delegate_view_helper_.CreateNewFullscreenWidget( - route_id, tab_contents()->render_view_host()->process()); -} - -void TabContentsView::ShowCreatedWidgetInternal( - RenderWidgetHostView* widget_host_view, const gfx::Rect& initial_pos) { - if (tab_contents_->delegate()) - tab_contents_->delegate()->RenderWidgetShowing(); - - widget_host_view->InitAsPopup(tab_contents_->GetRenderWidgetHostView(), - initial_pos); - widget_host_view->GetRenderWidgetHost()->Init(); -} - -void TabContentsView::ShowCreatedFullscreenWidgetInternal( - RenderWidgetHostView* widget_host_view) { - if (tab_contents_->delegate()) - tab_contents_->delegate()->RenderWidgetShowing(); - - widget_host_view->InitAsFullscreen(); - widget_host_view->GetRenderWidgetHost()->Init(); -} diff --git a/chrome/browser/tab_contents/tab_contents_view.h b/chrome/browser/tab_contents/tab_contents_view.h index a25b13f..a703cf2 100644 --- a/chrome/browser/tab_contents/tab_contents_view.h +++ b/chrome/browser/tab_contents/tab_contents_view.h @@ -6,213 +6,7 @@ #define CHROME_BROWSER_TAB_CONTENTS_TAB_CONTENTS_VIEW_H_ #pragma once -#include <map> -#include <string> - -#include "base/basictypes.h" -#include "chrome/browser/renderer_host/render_view_host_delegate.h" -#include "chrome/browser/tab_contents/render_view_host_delegate_helper.h" -#include "ui/gfx/native_widget_types.h" -#include "ui/gfx/rect.h" -#include "ui/gfx/size.h" - -class RenderViewHost; -class RenderWidgetHost; -class RenderWidgetHostView; -class TabContents; - -// The TabContentsView is an interface that is implemented by the platform- -// dependent web contents views. The TabContents uses this interface to talk to -// them. View-related messages will also get forwarded directly to this class -// from RenderViewHost via RenderViewHostDelegate::View. -// -// It contains a small amount of logic with respect to creating new sub-view -// that should be the same for all platforms. -class TabContentsView : public RenderViewHostDelegate::View { - public: - explicit TabContentsView(TabContents* tab_contents); - virtual ~TabContentsView(); - - // Creates the appropriate type of TabContentsView for the current system. - // The return value is a new heap allocated view with ownership passing to - // the caller. - static TabContentsView* Create(TabContents* tab_contents); - - TabContents* tab_contents() const { return tab_contents_; } - - virtual void CreateView(const gfx::Size& initial_size) = 0; - - // Sets up the View that holds the rendered web page, receives messages for - // it and contains page plugins. The host view should be sized to the current - // size of the TabContents. - virtual RenderWidgetHostView* CreateViewForWidget( - RenderWidgetHost* render_widget_host) = 0; - - // Returns the native widget that contains the contents of the tab. - virtual gfx::NativeView GetNativeView() const = 0; - - // Returns the native widget with the main content of the tab (i.e. the main - // render view host, though there may be many popups in the tab as children of - // the container). - virtual gfx::NativeView GetContentNativeView() const = 0; - - // Returns the outermost native view. This will be used as the parent for - // dialog boxes. - virtual gfx::NativeWindow GetTopLevelNativeWindow() const = 0; - - // Computes the rectangle for the native widget that contains the contents of - // the tab relative to its parent. - virtual void GetContainerBounds(gfx::Rect *out) const = 0; - - // Helper function for GetContainerBounds. Most callers just want to know the - // size, and this makes it more clear. - gfx::Size GetContainerSize() const { - gfx::Rect rc; - GetContainerBounds(&rc); - return gfx::Size(rc.width(), rc.height()); - } - - // Sets the page title for the native widgets corresponding to the view. This - // is not strictly necessary and isn't expected to be displayed anywhere, but - // can aid certain debugging tools such as Spy++ on Windows where you are - // trying to find a specific window. - virtual void SetPageTitle(const std::wstring& title) = 0; - - // Used to notify the view that a tab has crashed so each platform can - // prepare the sad tab. - virtual void OnTabCrashed(base::TerminationStatus status, - int error_code) = 0; - - // TODO(brettw) this is a hack. It's used in two places at the time of this - // writing: (1) when render view hosts switch, we need to size the replaced - // one to be correct, since it wouldn't have known about sizes that happened - // while it was hidden; (2) in constrained windows. - // - // (1) will be fixed once interstitials are cleaned up. (2) seems like it - // should be cleaned up or done some other way, since this works for normal - // TabContents without the special code. - virtual void SizeContents(const gfx::Size& size) = 0; - - // Invoked from the platform dependent web contents view when a - // RenderWidgetHost is deleted. Removes |host| from internal maps. - void RenderWidgetHostDestroyed(RenderWidgetHost* host); - - // Invoked when the TabContents is notified that the RenderView has been - // fully created. The default implementation does nothing; override - // for platform-specific behavior is needed. - virtual void RenderViewCreated(RenderViewHost* host); - - // Sets focus to the native widget for this tab. - virtual void Focus() = 0; - - // Sets focus to the appropriate element when the tab contents is shown the - // first time. - virtual void SetInitialFocus() = 0; - - // Stores the currently focused view. - virtual void StoreFocus() = 0; - - // Restores focus to the last focus view. If StoreFocus has not yet been - // invoked, SetInitialFocus is invoked. - virtual void RestoreFocus() = 0; - - // RenderViewHostDelegate::View method. Forwards to the TabContentsDelegate. - virtual void LostCapture(); - - // Keyboard events forwarding from the RenderViewHost. - // The default implementation just forward the events to the - // TabContentsDelegate object. - virtual bool PreHandleKeyboardEvent(const NativeWebKeyboardEvent& event, - bool* is_keyboard_shortcut); - - // Keyboard events forwarding from the RenderViewHost. - // The default implementation just forward the events to the - // TabContentsDelegate object. - virtual void HandleKeyboardEvent(const NativeWebKeyboardEvent& event); - - // Simple mouse event forwarding from the RenderViewHost. - virtual void HandleMouseMove() {} - virtual void HandleMouseDown() {} - virtual void HandleMouseLeave() {} - virtual void HandleMouseUp(); - virtual void HandleMouseActivate(); - - // Notification that the preferred size of the contents has changed. - virtual void UpdatePreferredSize(const gfx::Size& pref_size); - - // If we try to close the tab while a drag is in progress, we crash. These - // methods allow the tab contents to determine if a drag is in progress and - // postpone the tab closing. - virtual bool IsDoingDrag() const; - virtual void CancelDragAndCloseTab() {} - - // If we close the tab while a UI control is in an event-tracking - // loop, the control may message freed objects and crash. - // TabContents::Close() calls IsEventTracking(), and if it returns - // true CloseTabAfterEventTracking() is called and the close is not - // completed. - virtual bool IsEventTracking() const; - virtual void CloseTabAfterEventTracking() {} - - // Get the bounds of the View, relative to the parent. - virtual void GetViewBounds(gfx::Rect* out) const = 0; - - protected: - TabContentsView(); // Abstract interface. - - // Internal functions used to support the CreateNewWidget() method. If a - // platform requires plugging into widget creation at a lower level then a - // subclass might want to override these functions, but otherwise they should - // be fine just implementing RenderWidgetHostView::InitAsPopup(). - // - // The Create function returns the newly created widget so it can be - // associated with the given route. When the widget needs to be shown later, - // we'll look it up again and pass the object to the Show functions rather - // than the route ID. - virtual RenderWidgetHostView* CreateNewWidgetInternal( - int route_id, - WebKit::WebPopupType popup_type); - virtual void ShowCreatedWidgetInternal(RenderWidgetHostView* widget_host_view, - const gfx::Rect& initial_pos); - virtual void ShowCreatedFullscreenWidgetInternal( - RenderWidgetHostView* widget_host_view); - virtual RenderWidgetHostView* CreateNewFullscreenWidgetInternal(int route_id); - - // Common implementations of some RenderViewHostDelegate::View methods. - RenderViewHostDelegateViewHelper delegate_view_helper_; - - private: - // We implement these functions on RenderViewHostDelegate::View directly and - // do some book-keeping associated with the request. The request is then - // forwarded to *Internal which does platform-specific work. - virtual void CreateNewWindow( - int route_id, - const ViewHostMsg_CreateWindow_Params& params); - virtual void CreateNewWidget(int route_id, WebKit::WebPopupType popup_type); - virtual void CreateNewFullscreenWidget(int route_id); - virtual void ShowCreatedWindow(int route_id, - WindowOpenDisposition disposition, - const gfx::Rect& initial_pos, - bool user_gesture); - virtual void ShowCreatedWidget(int route_id, const gfx::Rect& initial_pos); - virtual void Activate(); - virtual void Deactivate(); - virtual void ShowCreatedFullscreenWidget(int route_id); - - // The TabContents whose contents we display. - TabContents* tab_contents_; - - // Tracks created TabContents objects that have not been shown yet. They are - // identified by the route ID passed to CreateNewWindow. - typedef std::map<int, TabContents*> PendingContents; - PendingContents pending_contents_; - - // These maps hold on to the widgets that we created on behalf of the - // renderer that haven't shown yet. - typedef std::map<int, RenderWidgetHostView*> PendingWidgetViews; - PendingWidgetViews pending_widget_views_; - - DISALLOW_COPY_AND_ASSIGN(TabContentsView); -}; +// TODO(jam): remove this file when all files have been converted. +#include "content/browser/tab_contents/tab_contents_view.h" #endif // CHROME_BROWSER_TAB_CONTENTS_TAB_CONTENTS_VIEW_H_ diff --git a/chrome/browser/tab_contents/test_tab_contents.cc b/chrome/browser/tab_contents/test_tab_contents.cc deleted file mode 100644 index 69fc0cf..0000000 --- a/chrome/browser/tab_contents/test_tab_contents.cc +++ /dev/null @@ -1,107 +0,0 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/tab_contents/test_tab_contents.h" - -#include <utility> - -#include "chrome/browser/browser_url_handler.h" -#include "chrome/browser/renderer_host/mock_render_process_host.h" -#include "chrome/browser/renderer_host/render_view_host.h" -#include "chrome/browser/renderer_host/site_instance.h" -#include "chrome/browser/renderer_host/test/test_render_view_host.h" -#include "chrome/browser/tab_contents/infobar_delegate.h" -#include "chrome/common/notification_details.h" -#include "chrome/common/notification_source.h" -#include "chrome/common/page_transition_types.h" - -TestTabContents::TestTabContents(Profile* profile, SiteInstance* instance) - : TabContents(profile, instance, MSG_ROUTING_NONE, NULL, NULL), - transition_cross_site(false) { - // Listen for infobar events so we can call InfoBarClosed() on the infobar - // delegates and give them an opportunity to delete themselves. (Since we - // have no InfobarContainer in TestTabContents, InfoBarClosed() is not called - // most likely leading to the infobar delegates being leaked.) - Source<TabContents> source(this); - registrar_.Add(this, NotificationType::TAB_CONTENTS_INFOBAR_REMOVED, - source); - registrar_.Add(this, NotificationType::TAB_CONTENTS_INFOBAR_REPLACED, - source); -} - -void TestTabContents::Observe(NotificationType type, - const NotificationSource& source, - const NotificationDetails& details) { - // TabContents does not handle TAB_CONTENTS_INFOBAR_* so we don't pass it - // these notifications. - switch (type.value) { - case NotificationType::TAB_CONTENTS_INFOBAR_REMOVED: - Details<InfoBarDelegate>(details).ptr()->InfoBarClosed(); - break; - case NotificationType::TAB_CONTENTS_INFOBAR_REPLACED: - Details<std::pair<InfoBarDelegate*, InfoBarDelegate*> >(details).ptr()-> - first->InfoBarClosed(); - break; - default: - TabContents::Observe(type, source, details); - break; - } -} - -TestRenderViewHost* TestTabContents::pending_rvh() const { - return static_cast<TestRenderViewHost*>( - render_manager_.pending_render_view_host_); -} - -bool TestTabContents::CreateRenderViewForRenderManager( - RenderViewHost* render_view_host) { - // This will go to a TestRenderViewHost. - render_view_host->CreateRenderView(string16()); - return true; -} - -TabContents* TestTabContents::Clone() { - TabContents* tc = new TestTabContents( - profile(), SiteInstance::CreateSiteInstance(profile())); - tc->controller().CopyStateFrom(controller_); - return tc; -} - -void TestTabContents::NavigateAndCommit(const GURL& url) { - controller().LoadURL(url, GURL(), PageTransition::LINK); - GURL loaded_url(url); - bool reverse_on_redirect = false; - BrowserURLHandler::RewriteURLIfNecessary( - &loaded_url, profile(), &reverse_on_redirect); - - // LoadURL created a navigation entry, now simulate the RenderView sending - // a notification that it actually navigated. - CommitPendingNavigation(); -} - -void TestTabContents::CommitPendingNavigation() { - // If we are doing a cross-site navigation, this simulates the current RVH - // notifying that it has unloaded so the pending RVH is resumed and can - // navigate. - ProceedWithCrossSiteNavigation(); - TestRenderViewHost* rvh = pending_rvh(); - if (!rvh) - rvh = static_cast<TestRenderViewHost*>(render_manager_.current_host()); - - const NavigationEntry* entry = controller().pending_entry(); - DCHECK(entry); - int page_id = entry->page_id(); - if (page_id == -1) { - // It's a new navigation, assign a never-seen page id to it. - page_id = - static_cast<MockRenderProcessHost*>(rvh->process())->max_page_id() + 1; - } - rvh->SendNavigate(page_id, entry->url()); -} - -void TestTabContents::ProceedWithCrossSiteNavigation() { - if (!pending_rvh()) - return; - render_manager_.ShouldClosePage(true, true); -} diff --git a/chrome/browser/tab_contents/test_tab_contents.h b/chrome/browser/tab_contents/test_tab_contents.h index 729730b..583bd81 100644 --- a/chrome/browser/tab_contents/test_tab_contents.h +++ b/chrome/browser/tab_contents/test_tab_contents.h @@ -6,76 +6,7 @@ #define CHROME_BROWSER_TAB_CONTENTS_TEST_TAB_CONTENTS_H_ #pragma once -#include "chrome/browser/tab_contents/tab_contents.h" -#include "chrome/common/notification_registrar.h" -#include "webkit/glue/webpreferences.h" - -class Profile; -class TestRenderViewHost; - -// Subclass TabContents to ensure it creates TestRenderViewHosts and does -// not do anything involving views. -class TestTabContents : public TabContents { - public: - // The render view host factory will be passed on to the - TestTabContents(Profile* profile, SiteInstance* instance); - - TestRenderViewHost* pending_rvh() const; - - // State accessor. - bool cross_navigation_pending() { - return render_manager_.cross_navigation_pending_; - } - - // Overrides TabContents::ShouldTransitionCrossSite so that we can test both - // alternatives without using command-line switches. - bool ShouldTransitionCrossSite() { return transition_cross_site; } - - // Overrides TabContents::Observe. We are listening to infobar related - // notifications so we can call InfoBarClosed() on the infobar delegates to - // prevent them from leaking. - virtual void Observe(NotificationType type, - const NotificationSource& source, - const NotificationDetails& details); - - // Promote DidNavigate to public. - void TestDidNavigate(RenderViewHost* render_view_host, - const ViewHostMsg_FrameNavigate_Params& params) { - DidNavigate(render_view_host, params); - } - - // Promote GetWebkitPrefs to public. - WebPreferences TestGetWebkitPrefs() { - return GetWebkitPrefs(); - } - - // Prevent interaction with views. - virtual bool CreateRenderViewForRenderManager( - RenderViewHost* render_view_host); - virtual void UpdateRenderViewSizeForRenderManager() {} - - // Returns a clone of this TestTabContents. The returned object is also a - // TestTabContents. The caller owns the returned object. - virtual TabContents* Clone(); - - // Creates a pending navigation to the given URL with the default parameters - // and then commits the load with a page ID one larger than any seen. This - // emulates what happens on a new navigation. - void NavigateAndCommit(const GURL& url); - - // Simulates the appropriate RenderView (pending if any, current otherwise) - // sending a navigate notification for the NavigationController pending entry. - void CommitPendingNavigation(); - - // Simulates the current RVH notifying that it has unloaded so that the - // pending RVH navigation can proceed. - // Does nothing if no cross-navigation is pending. - void ProceedWithCrossSiteNavigation(); - - // Set by individual tests. - bool transition_cross_site; - - NotificationRegistrar registrar_; -}; +// TODO(jam): remove this file when all files have been converted. +#include "content/browser/tab_contents/test_tab_contents.h" #endif // CHROME_BROWSER_TAB_CONTENTS_TEST_TAB_CONTENTS_H_ diff --git a/chrome/browser/ui/browser.cc b/chrome/browser/ui/browser.cc index 8075796..e75750a 100644 --- a/chrome/browser/ui/browser.cc +++ b/chrome/browser/ui/browser.cc @@ -102,6 +102,7 @@ #include "chrome/common/profiling.h" #include "chrome/common/url_constants.h" #include "chrome/common/web_apps.h" +#include "content/browser/tab_contents/infobar_delegate.h" #include "grit/chromium_strings.h" #include "grit/generated_resources.h" #include "grit/locale_settings.h" @@ -825,7 +826,7 @@ string16 Browser::GetWindowTitleForCurrentTab() const { FormatTitleForDisplay(&title); } if (title.empty()) - title = TabContents::GetDefaultTitle(); + title = TabContentsWrapper::GetDefaultTitle(); #if defined(OS_MACOSX) || defined(OS_CHROMEOS) // On Mac or ChromeOS, we don't want to suffix the page title with @@ -2746,7 +2747,7 @@ void Browser::TabSelectedAt(TabContentsWrapper* old_contents, status_bubble->Hide(); // Show the loading state (if any). - status_bubble->SetStatus(GetSelectedTabContents()->GetStatusText()); + status_bubble->SetStatus(GetSelectedTabContentsWrapper()->GetStatusText()); } if (HasFindBarController()) { @@ -2917,7 +2918,8 @@ void Browser::LoadingStateChanged(TabContents* source) { if (source == selected_contents) { UpdateReloadStopState(source->is_loading(), false); if (GetStatusBubble()) { - GetStatusBubble()->SetStatus(GetSelectedTabContents()->GetStatusText()); + GetStatusBubble()->SetStatus( + GetSelectedTabContentsWrapper()->GetStatusText()); } if (!source->is_loading() && @@ -3267,6 +3269,14 @@ void Browser::ContentRestrictionsChanged(TabContents* source) { UpdateCommandsForContentRestrictionState(); } +void Browser::WorkerCrashed() { + TabContents* tab_contents = GetSelectedTabContents(); + if (!tab_contents) + return; + tab_contents->AddInfoBar(new SimpleAlertInfoBarDelegate(tab_contents, NULL, + l10n_util::GetStringUTF16(IDS_WEBWORKER_CRASHED_PROMPT), true)); +} + /////////////////////////////////////////////////////////////////////////////// // Browser, TabContentsWrapperDelegate implementation: @@ -3884,8 +3894,10 @@ void Browser::ProcessPendingUIUpdates() { window()->GetLocationBar()->UpdatePageActions(); // Updating the URL happens synchronously in ScheduleUIUpdate. - if (flags & TabContents::INVALIDATE_LOAD && GetStatusBubble()) - GetStatusBubble()->SetStatus(contents->GetStatusText()); + if (flags & TabContents::INVALIDATE_LOAD && GetStatusBubble()) { + GetStatusBubble()->SetStatus( + GetSelectedTabContentsWrapper()->GetStatusText()); + } if (flags & (TabContents::INVALIDATE_TAB | TabContents::INVALIDATE_TITLE)) { diff --git a/chrome/browser/ui/browser.h b/chrome/browser/ui/browser.h index 7c073ef..ba4a6cd 100644 --- a/chrome/browser/ui/browser.h +++ b/chrome/browser/ui/browser.h @@ -807,6 +807,7 @@ class Browser : public TabHandlerDelegate, virtual void OnInstallApplication(TabContents* tab_contents, const WebApplicationInfo& app_info); virtual void ContentRestrictionsChanged(TabContents* source); + virtual void WorkerCrashed(); // Overridden from TabContentsWrapperDelegate: virtual void URLStarredChanged(TabContentsWrapper* source, diff --git a/chrome/browser/ui/cocoa/hung_renderer_controller.mm b/chrome/browser/ui/cocoa/hung_renderer_controller.mm index 2853658..652fc08 100644 --- a/chrome/browser/ui/cocoa/hung_renderer_controller.mm +++ b/chrome/browser/ui/cocoa/hung_renderer_controller.mm @@ -15,6 +15,7 @@ #include "chrome/browser/renderer_host/render_view_host.h" #include "chrome/browser/tab_contents/tab_contents.h" #import "chrome/browser/ui/cocoa/multi_key_equivalent_button.h" +#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" #include "chrome/common/logging_chrome.h" #include "chrome/common/result_codes.h" #include "grit/chromium_strings.h" @@ -139,7 +140,7 @@ HungRendererController* g_instance = NULL; if (it->GetRenderProcessHost() == hungContents_->GetRenderProcessHost()) { string16 title = (*it)->GetTitle(); if (title.empty()) - title = TabContents::GetDefaultTitle(); + title = TabContentsWrapper::GetDefaultTitle(); [titles addObject:base::SysUTF16ToNSString(title)]; // TabContents can return a null SkBitmap if it has no favicon. If this diff --git a/chrome/browser/ui/gtk/hung_renderer_dialog_gtk.cc b/chrome/browser/ui/gtk/hung_renderer_dialog_gtk.cc index fc41e24..b2bf521 100644 --- a/chrome/browser/ui/gtk/hung_renderer_dialog_gtk.cc +++ b/chrome/browser/ui/gtk/hung_renderer_dialog_gtk.cc @@ -13,6 +13,7 @@ #include "chrome/browser/renderer_host/render_view_host.h" #include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/browser/ui/gtk/gtk_util.h" +#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" #include "chrome/common/logging_chrome.h" #include "chrome/common/result_codes.h" #include "grit/chromium_strings.h" @@ -152,7 +153,7 @@ void HungRendererDialogGtk::ShowForTabContents(TabContents* hung_contents) { gtk_list_store_append(model_, &tree_iter); std::string title = UTF16ToUTF8(it->GetTitle()); if (title.empty()) - title = UTF16ToUTF8(TabContents::GetDefaultTitle()); + title = UTF16ToUTF8(TabContentsWrapper::GetDefaultTitle()); SkBitmap favicon = it->GetFavIcon(); GdkPixbuf* pixbuf = NULL; diff --git a/chrome/browser/ui/gtk/tabs/tab_renderer_gtk.cc b/chrome/browser/ui/gtk/tabs/tab_renderer_gtk.cc index 3abd11b..19b20a5 100644 --- a/chrome/browser/ui/gtk/tabs/tab_renderer_gtk.cc +++ b/chrome/browser/ui/gtk/tabs/tab_renderer_gtk.cc @@ -16,6 +16,7 @@ #include "chrome/browser/ui/gtk/custom_button.h" #include "chrome/browser/ui/gtk/gtk_theme_provider.h" #include "chrome/browser/ui/gtk/gtk_util.h" +#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" #include "chrome/common/notification_service.h" #include "grit/app_resources.h" #include "grit/generated_resources.h" @@ -808,7 +809,7 @@ void TabRendererGtk::PaintTitle(gfx::Canvas* canvas) { if (title.empty()) { title = data_.loading ? l10n_util::GetStringUTF16(IDS_TAB_LOADING_TITLE) : - TabContents::GetDefaultTitle(); + TabContentsWrapper::GetDefaultTitle(); } else { Browser::FormatTitleForDisplay(&title); } diff --git a/chrome/browser/ui/tab_contents/tab_contents_wrapper.cc b/chrome/browser/ui/tab_contents/tab_contents_wrapper.cc index d1d46bfd..8541170 100644 --- a/chrome/browser/ui/tab_contents/tab_contents_wrapper.cc +++ b/chrome/browser/ui/tab_contents/tab_contents_wrapper.cc @@ -8,12 +8,21 @@ #include "chrome/browser/bookmarks/bookmark_model.h" #include "chrome/browser/password_manager/password_manager.h" #include "chrome/browser/password_manager_delegate_impl.h" +#include "chrome/browser/prefs/pref_service.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/tab_contents/infobar_delegate.h" #include "chrome/browser/ui/find_bar/find_tab_helper.h" #include "chrome/browser/ui/search_engines/search_engine_tab_helper.h" #include "chrome/browser/ui/tab_contents/tab_contents_wrapper_delegate.h" #include "chrome/common/notification_service.h" +#include "chrome/common/pref_names.h" +#include "chrome/common/render_messages.h" +#include "content/browser/tab_contents/tab_contents.h" +#include "grit/locale_settings.h" +#include "grit/generated_resources.h" +#include "grit/platform_locale_settings.h" +#include "ui/base/l10n/l10n_util.h" +#include "webkit/glue/webpreferences.h" static base::LazyInstance<PropertyAccessor<TabContentsWrapper*> > g_tab_contents_wrapper_property_accessor(base::LINKER_INITIALIZED); @@ -54,6 +63,106 @@ PropertyAccessor<TabContentsWrapper*>* TabContentsWrapper::property_accessor() { return g_tab_contents_wrapper_property_accessor.Pointer(); } +void TabContentsWrapper::RegisterUserPrefs(PrefService* prefs) { + prefs->RegisterBooleanPref(prefs::kAlternateErrorPagesEnabled, true); + + WebPreferences pref_defaults; + prefs->RegisterBooleanPref(prefs::kWebKitJavascriptEnabled, + pref_defaults.javascript_enabled); + prefs->RegisterBooleanPref(prefs::kWebKitWebSecurityEnabled, + pref_defaults.web_security_enabled); + prefs->RegisterBooleanPref( + prefs::kWebKitJavascriptCanOpenWindowsAutomatically, true); + prefs->RegisterBooleanPref(prefs::kWebKitLoadsImagesAutomatically, + pref_defaults.loads_images_automatically); + prefs->RegisterBooleanPref(prefs::kWebKitPluginsEnabled, + pref_defaults.plugins_enabled); + prefs->RegisterBooleanPref(prefs::kWebKitDomPasteEnabled, + pref_defaults.dom_paste_enabled); + prefs->RegisterBooleanPref(prefs::kWebKitShrinksStandaloneImagesToFit, + pref_defaults.shrinks_standalone_images_to_fit); + prefs->RegisterDictionaryPref(prefs::kWebKitInspectorSettings); + prefs->RegisterBooleanPref(prefs::kWebKitTextAreasAreResizable, + pref_defaults.text_areas_are_resizable); + prefs->RegisterBooleanPref(prefs::kWebKitJavaEnabled, + pref_defaults.java_enabled); + prefs->RegisterBooleanPref(prefs::kWebkitTabsToLinks, + pref_defaults.tabs_to_links); + + prefs->RegisterLocalizedStringPref(prefs::kAcceptLanguages, + IDS_ACCEPT_LANGUAGES); + prefs->RegisterLocalizedStringPref(prefs::kDefaultCharset, + IDS_DEFAULT_ENCODING); + prefs->RegisterLocalizedBooleanPref(prefs::kWebKitStandardFontIsSerif, + IDS_STANDARD_FONT_IS_SERIF); + prefs->RegisterLocalizedStringPref(prefs::kWebKitFixedFontFamily, + IDS_FIXED_FONT_FAMILY); + prefs->RegisterLocalizedStringPref(prefs::kWebKitSerifFontFamily, + IDS_SERIF_FONT_FAMILY); + prefs->RegisterLocalizedStringPref(prefs::kWebKitSansSerifFontFamily, + IDS_SANS_SERIF_FONT_FAMILY); + prefs->RegisterLocalizedStringPref(prefs::kWebKitCursiveFontFamily, + IDS_CURSIVE_FONT_FAMILY); + prefs->RegisterLocalizedStringPref(prefs::kWebKitFantasyFontFamily, + IDS_FANTASY_FONT_FAMILY); + prefs->RegisterLocalizedIntegerPref(prefs::kWebKitDefaultFontSize, + IDS_DEFAULT_FONT_SIZE); + prefs->RegisterLocalizedIntegerPref(prefs::kWebKitDefaultFixedFontSize, + IDS_DEFAULT_FIXED_FONT_SIZE); + prefs->RegisterLocalizedIntegerPref(prefs::kWebKitMinimumFontSize, + IDS_MINIMUM_FONT_SIZE); + prefs->RegisterLocalizedIntegerPref(prefs::kWebKitMinimumLogicalFontSize, + IDS_MINIMUM_LOGICAL_FONT_SIZE); + prefs->RegisterLocalizedBooleanPref(prefs::kWebKitUsesUniversalDetector, + IDS_USES_UNIVERSAL_DETECTOR); + prefs->RegisterLocalizedStringPref(prefs::kStaticEncodings, + IDS_STATIC_ENCODING_LIST); +} + +string16 TabContentsWrapper::GetDefaultTitle() { + return l10n_util::GetStringUTF16(IDS_DEFAULT_TAB_TITLE); +} + +string16 TabContentsWrapper::GetStatusText() const { + if (!tab_contents()->is_loading() || + tab_contents()->load_state() == net::LOAD_STATE_IDLE) { + return string16(); + } + + switch (tab_contents()->load_state()) { + case net::LOAD_STATE_WAITING_FOR_CACHE: + return l10n_util::GetStringUTF16(IDS_LOAD_STATE_WAITING_FOR_CACHE); + case net::LOAD_STATE_ESTABLISHING_PROXY_TUNNEL: + return + l10n_util::GetStringUTF16(IDS_LOAD_STATE_ESTABLISHING_PROXY_TUNNEL); + case net::LOAD_STATE_RESOLVING_PROXY_FOR_URL: + return l10n_util::GetStringUTF16(IDS_LOAD_STATE_RESOLVING_PROXY_FOR_URL); + case net::LOAD_STATE_RESOLVING_HOST: + return l10n_util::GetStringUTF16(IDS_LOAD_STATE_RESOLVING_HOST); + case net::LOAD_STATE_CONNECTING: + return l10n_util::GetStringUTF16(IDS_LOAD_STATE_CONNECTING); + case net::LOAD_STATE_SSL_HANDSHAKE: + return l10n_util::GetStringUTF16(IDS_LOAD_STATE_SSL_HANDSHAKE); + case net::LOAD_STATE_SENDING_REQUEST: + if (tab_contents()->upload_size()) + return l10n_util::GetStringFUTF16Int( + IDS_LOAD_STATE_SENDING_REQUEST_WITH_PROGRESS, + static_cast<int>((100 * tab_contents()->upload_position()) / + tab_contents()->upload_size())); + else + return l10n_util::GetStringUTF16(IDS_LOAD_STATE_SENDING_REQUEST); + case net::LOAD_STATE_WAITING_FOR_RESPONSE: + return l10n_util::GetStringFUTF16(IDS_LOAD_STATE_WAITING_FOR_RESPONSE, + tab_contents()->load_state_host()); + // Ignore net::LOAD_STATE_READING_RESPONSE and net::LOAD_STATE_IDLE + case net::LOAD_STATE_IDLE: + case net::LOAD_STATE_READING_RESPONSE: + break; + } + + return string16(); +} + TabContentsWrapper* TabContentsWrapper::Clone() { TabContents* new_contents = tab_contents()->Clone(); TabContentsWrapper* new_wrapper = new TabContentsWrapper(new_contents); @@ -77,6 +186,15 @@ void TabContentsWrapper::DidNavigateMainFramePostCommit( UpdateStarredStateForCurrentURL(); } +bool TabContentsWrapper::OnMessageReceived(const IPC::Message& message) { + bool handled = true; + IPC_BEGIN_MESSAGE_MAP(TabContentsWrapper, message) + IPC_MESSAGE_HANDLER(ViewHostMsg_JSOutOfMemory, OnJSOutOfMemory) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP() + return handled; +} + //////////////////////////////////////////////////////////////////////////////// // TabContentsWrapper, NotificationObserver implementation: @@ -105,6 +223,11 @@ void TabContentsWrapper::Observe(NotificationType type, //////////////////////////////////////////////////////////////////////////////// // Internal helpers +void TabContentsWrapper::OnJSOutOfMemory() { + tab_contents()->AddInfoBar(new SimpleAlertInfoBarDelegate(tab_contents(), + NULL, l10n_util::GetStringUTF16(IDS_JS_OUT_OF_MEMORY_PROMPT), true)); +} + void TabContentsWrapper::UpdateStarredStateForCurrentURL() { BookmarkModel* model = tab_contents()->profile()->GetBookmarkModel(); const bool old_state = is_starred_; diff --git a/chrome/browser/ui/tab_contents/tab_contents_wrapper.h b/chrome/browser/ui/tab_contents/tab_contents_wrapper.h index 510fb76..faaf5b8 100644 --- a/chrome/browser/ui/tab_contents/tab_contents_wrapper.h +++ b/chrome/browser/ui/tab_contents/tab_contents_wrapper.h @@ -39,6 +39,14 @@ class TabContentsWrapper : public NotificationObserver, // its property bag to avoid adding additional interfaces. static PropertyAccessor<TabContentsWrapper*>* property_accessor(); + static void RegisterUserPrefs(PrefService* prefs); + + // Initial title assigned to NavigationEntries from Navigate. + static string16 GetDefaultTitle(); + + // Returns a human-readable description the tab's loading state. + string16 GetStatusText() const; + // Create a TabContentsWrapper with the same state as this one. The returned // heap-allocated pointer is owned by the caller. TabContentsWrapper* Clone(); @@ -88,6 +96,7 @@ class TabContentsWrapper : public NotificationObserver, virtual void DidNavigateMainFramePostCommit( const NavigationController::LoadCommittedDetails& details, const ViewHostMsg_FrameNavigate_Params& params) OVERRIDE; + virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; // NotificationObserver overrides: virtual void Observe(NotificationType type, @@ -97,6 +106,9 @@ class TabContentsWrapper : public NotificationObserver, private: // Internal helpers ---------------------------------------------------------- + // Message handlers. + void OnJSOutOfMemory(); + // Updates the starred state from the bookmark bar model. If the state has // changed, the delegate is notified. void UpdateStarredStateForCurrentURL(); diff --git a/chrome/browser/ui/views/hung_renderer_view.cc b/chrome/browser/ui/views/hung_renderer_view.cc index ffefd9f..65a3478 100644 --- a/chrome/browser/ui/views/hung_renderer_view.cc +++ b/chrome/browser/ui/views/hung_renderer_view.cc @@ -10,6 +10,7 @@ #include "chrome/browser/renderer_host/render_process_host.h" #include "chrome/browser/renderer_host/render_view_host.h" #include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" #include "chrome/common/chrome_constants.h" #include "chrome/common/logging_chrome.h" #include "chrome/common/result_codes.h" @@ -93,7 +94,7 @@ string16 HungPagesTableModel::GetText(int row, int column_id) { DCHECK(row >= 0 && row < RowCount()); string16 title = tab_contentses_[row]->GetTitle(); if (title.empty()) - title = TabContents::GetDefaultTitle(); + title = TabContentsWrapper::GetDefaultTitle(); // TODO(xji): Consider adding a special case if the title text is a URL, // since those should always have LTR directionality. Please refer to // http://crbug.com/6726 for more information. diff --git a/chrome/browser/ui/views/tabs/base_tab.cc b/chrome/browser/ui/views/tabs/base_tab.cc index 53d66ec..4350d04 100644 --- a/chrome/browser/ui/views/tabs/base_tab.cc +++ b/chrome/browser/ui/views/tabs/base_tab.cc @@ -12,6 +12,7 @@ #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/view_ids.h" #include "chrome/browser/ui/views/tabs/tab_controller.h" +#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" #include "chrome/common/chrome_switches.h" #include "grit/app_resources.h" #include "grit/generated_resources.h" @@ -437,7 +438,7 @@ void BaseTab::PaintTitle(gfx::Canvas* canvas, SkColor title_color) { if (title.empty()) { title = data().loading ? l10n_util::GetStringUTF16(IDS_TAB_LOADING_TITLE) : - TabContents::GetDefaultTitle(); + TabContentsWrapper::GetDefaultTitle(); } else { Browser::FormatTitleForDisplay(&title); } diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp index 6b78cae..3af5e70 100644 --- a/chrome/chrome.gyp +++ b/chrome/chrome.gyp @@ -1624,7 +1624,7 @@ '../app/app.gyp:*', '../base/base.gyp:*', '../chrome_frame/chrome_frame.gyp:*', - '../ui/gfx/gfx.gyp:*', + '../content/content.gyp:*', '../ipc/ipc.gyp:*', '../media/media.gyp:*', '../net/net.gyp:*', @@ -1649,6 +1649,7 @@ '../third_party/qcms/qcms.gyp:*', '../third_party/sqlite/sqlite.gyp:*', '../third_party/zlib/zlib.gyp:*', + '../ui/gfx/gfx.gyp:*', '../webkit/support/webkit_support.gyp:*', '../webkit/webkit.gyp:*', diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index f12073e..4d232df 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -27,6 +27,7 @@ 'userfeedback_proto', '../app/app.gyp:app_resources', '../app/app.gyp:app_strings', + '../content/content.gyp:content_browser', '../media/media.gyp:media', '../ppapi/ppapi.gyp:ppapi_proxy', # For PpapiMsg_LoadPlugin '../printing/printing.gyp:printing', @@ -2288,24 +2289,10 @@ 'browser/sync/token_migrator.h', 'browser/tab_closeable_state_watcher.cc', 'browser/tab_closeable_state_watcher.h', - 'browser/tab_contents/background_contents.cc', - 'browser/tab_contents/background_contents.h', - 'browser/tab_contents/constrained_window.h', 'browser/tab_contents/infobar_delegate.cc', 'browser/tab_contents/infobar_delegate.h', - 'browser/tab_contents/interstitial_page.cc', - 'browser/tab_contents/interstitial_page.h', - 'browser/tab_contents/language_state.cc', - 'browser/tab_contents/language_state.h', - 'browser/tab_contents/navigation_controller.cc', - 'browser/tab_contents/navigation_controller.h', - 'browser/tab_contents/navigation_entry.cc', - 'browser/tab_contents/navigation_entry.h', - 'browser/tab_contents/page_navigator.h', 'browser/tab_contents/popup_menu_helper_mac.h', 'browser/tab_contents/popup_menu_helper_mac.mm', - 'browser/tab_contents/provisional_load_details.cc', - 'browser/tab_contents/provisional_load_details.h', 'browser/tab_contents/render_view_context_menu.cc', 'browser/tab_contents/render_view_context_menu.h', 'browser/tab_contents/render_view_context_menu_gtk.cc', @@ -2314,18 +2301,8 @@ 'browser/tab_contents/render_view_context_menu_mac.mm', 'browser/tab_contents/render_view_host_delegate_helper.cc', 'browser/tab_contents/render_view_host_delegate_helper.h', - 'browser/tab_contents/render_view_host_manager.cc', - 'browser/tab_contents/render_view_host_manager.h', - 'browser/tab_contents/tab_contents.cc', - 'browser/tab_contents/tab_contents.h', - 'browser/tab_contents/tab_contents_delegate.cc', - 'browser/tab_contents/tab_contents_delegate.h', - 'browser/tab_contents/tab_contents_observer.cc', - 'browser/tab_contents/tab_contents_observer.h', 'browser/tab_contents/tab_contents_ssl_helper.cc', 'browser/tab_contents/tab_contents_ssl_helper.h', - 'browser/tab_contents/tab_contents_view.cc', - 'browser/tab_contents/tab_contents_view.h', 'browser/tab_contents/tab_contents_view_gtk.cc', 'browser/tab_contents/tab_contents_view_gtk.h', 'browser/tab_contents/tab_contents_view_mac.h', diff --git a/chrome/chrome_common.gypi b/chrome/chrome_common.gypi index 2c4025b..618364b 100644 --- a/chrome/chrome_common.gypi +++ b/chrome/chrome_common.gypi @@ -216,6 +216,8 @@ '../base/base.gyp:base', '../base/base.gyp:base_i18n', '../build/temp_gyp/googleurl.gyp:googleurl', + # Don't include now since it's empty and so will cause a linker error. + #'../content/content.gyp:content_common', '../ipc/ipc.gyp:ipc', '../net/net.gyp:net', '../printing/printing.gyp:printing', diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi index 8c7545b..1d7e6c5 100644 --- a/chrome/chrome_tests.gypi +++ b/chrome/chrome_tests.gypi @@ -95,8 +95,6 @@ 'browser/sync/profile_sync_service_mock.h', 'browser/sync/syncable/syncable_mock.cc', 'browser/sync/syncable/syncable_mock.h', - 'browser/tab_contents/test_tab_contents.cc', - 'browser/tab_contents/test_tab_contents.h', 'browser/ui/browser.h', 'browser/ui/cocoa/browser_test_helper.h', 'browser/ui/tab_contents/test_tab_contents_wrapper.cc', @@ -182,6 +180,8 @@ 'test/unit/chrome_test_suite.h', 'test/values_test_util.cc', 'test/values_test_util.h', + '../content/browser/tab_contents/test_tab_contents.cc', + '../content/browser/tab_contents/test_tab_contents.h', ], 'conditions': [ ['OS=="linux"', { @@ -1548,9 +1548,6 @@ 'browser/sync/test_profile_sync_service.cc', 'browser/sync/util/cryptographer_unittest.cc', 'browser/sync/util/nigori_unittest.cc', - 'browser/tab_contents/navigation_controller_unittest.cc', - 'browser/tab_contents/navigation_entry_unittest.cc', - 'browser/tab_contents/render_view_host_manager_unittest.cc', 'browser/tab_contents/tab_specific_content_settings_unittest.cc', 'browser/tab_contents/thumbnail_generator_unittest.cc', 'browser/tab_contents/web_contents_unittest.cc', @@ -1848,6 +1845,9 @@ 'test/v8_unit_test.cc', 'test/v8_unit_test.h', 'tools/convert_dict/convert_dict_unittest.cc', + '../content/browser/tab_contents/navigation_controller_unittest.cc', + '../content/browser/tab_contents/navigation_entry_unittest.cc', + '../content/browser/tab_contents/render_view_host_manager_unittest.cc', '../testing/gtest_mac_unittest.mm', '../third_party/cld/encodings/compact_lang_det/compact_lang_det_unittest_small.cc', '../webkit/fileapi/file_system_dir_url_request_job_unittest.cc', |