From f3ec774a2c177d3c6845553d3bf9735a7b8a5907 Mon Sep 17 00:00:00 2001 From: "ben@chromium.org" Date: Thu, 15 Jan 2009 00:59:16 +0000 Subject: Move a bunch of TabContents related files into a tab_contents subdir Review URL: http://codereview.chromium.org/18250 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@8058 0039d316-1c4b-4281-b951-d872f2087c98 --- chrome/browser/about_internets_status_view.cc | 69 - chrome/browser/about_internets_status_view.h | 45 - chrome/browser/alternate_nav_url_fetcher.cc | 6 +- chrome/browser/alternate_nav_url_fetcher.h | 2 +- chrome/browser/autocomplete/autocomplete_edit.cc | 2 +- chrome/browser/autofill_manager.cc | 2 +- .../automation_constrained_window_tracker.h | 2 +- chrome/browser/automation/automation_provider.cc | 6 +- chrome/browser/automation/automation_tab_tracker.h | 2 +- chrome/browser/back_forward_menu_model.cc | 6 +- chrome/browser/back_forward_menu_model_unittest.cc | 8 +- chrome/browser/bookmarks/bookmark_context_menu.cc | 4 +- .../bookmarks/bookmark_context_menu_test.cc | 2 +- chrome/browser/bookmarks/bookmark_utils.cc | 4 +- chrome/browser/browser.cc | 10 +- chrome/browser/browser.h | 4 +- chrome/browser/browser.scons | 40 +- chrome/browser/browser.vcproj | 494 ++++-- chrome/browser/browser_about_handler.cc | 2 +- chrome/browser/browser_about_handler.h | 2 +- chrome/browser/browser_commands_unittest.cc | 4 +- chrome/browser/browser_init.cc | 4 +- chrome/browser/browser_list.cc | 2 +- chrome/browser/browser_prefs.cc | 2 +- chrome/browser/browsing_instance.cc | 2 +- chrome/browser/cert_store.cc | 2 +- chrome/browser/constrained_window.h | 68 - chrome/browser/debugger/debugger_host_impl.cpp | 2 +- chrome/browser/debugger/debugger_node.cc | 2 +- chrome/browser/debugger/debugger_shell.cc | 2 +- chrome/browser/debugger/debugger_view.cc | 4 +- chrome/browser/debugger/debugger_view.h | 2 +- chrome/browser/debugger/debugger_window.cc | 4 +- chrome/browser/dom_ui/dom_ui_contents.cc | 2 +- chrome/browser/dom_ui/dom_ui_contents.h | 2 +- chrome/browser/dom_ui/dom_ui_host.cc | 4 +- chrome/browser/dom_ui/dom_ui_host.h | 2 +- chrome/browser/dom_ui/new_tab_ui.cc | 2 +- chrome/browser/download/download_file.cc | 4 +- chrome/browser/download/download_manager.cc | 4 +- .../browser/download/download_request_manager.cc | 12 +- .../download/download_request_manager_unittest.cc | 2 +- chrome/browser/download/save_file_manager.cc | 6 +- chrome/browser/download/save_package.cc | 4 +- .../browser/encoding_menu_controller_delegate.cc | 2 +- chrome/browser/external_tab_container.cc | 4 +- chrome/browser/external_tab_container.h | 2 +- chrome/browser/fav_icon_helper.cc | 8 +- chrome/browser/history_tab_ui.h | 2 +- chrome/browser/history_view.cc | 4 +- chrome/browser/infobar_delegate.cc | 93 - chrome/browser/infobar_delegate.h | 206 --- chrome/browser/interstitial_page.cc | 362 ---- chrome/browser/interstitial_page.h | 168 -- chrome/browser/ipc_status_view.cc | 370 ---- chrome/browser/ipc_status_view.h | 89 - chrome/browser/jsmessage_box_handler.cc | 2 +- chrome/browser/load_notification_details.h | 2 +- chrome/browser/login_prompt.cc | 8 +- chrome/browser/memory_details.cc | 4 +- chrome/browser/native_ui_contents.cc | 671 -------- chrome/browser/native_ui_contents.h | 295 ---- chrome/browser/navigation_controller.cc | 1233 -------------- chrome/browser/navigation_controller.h | 550 ------ chrome/browser/navigation_controller_unittest.cc | 10 +- chrome/browser/navigation_entry.cc | 64 - chrome/browser/navigation_entry.h | 399 ----- chrome/browser/network_status_view.cc | 320 ---- chrome/browser/network_status_view.h | 117 -- chrome/browser/page_navigator.h | 27 - chrome/browser/password_manager.cc | 2 +- chrome/browser/password_manager.h | 2 +- chrome/browser/plugin_installer.cc | 2 +- chrome/browser/plugin_installer.h | 2 +- chrome/browser/printing/print_view_manager.cc | 4 +- chrome/browser/profile.cc | 2 +- chrome/browser/profile_manager.cc | 2 +- chrome/browser/provisional_load_details.cc | 25 - chrome/browser/provisional_load_details.h | 60 - chrome/browser/render_process_host.cc | 2 +- .../browser/render_view_context_menu_controller.cc | 6 +- chrome/browser/render_view_host.cc | 8 +- chrome/browser/render_view_host_manager.cc | 6 +- .../renderer_host/cross_site_resource_handler.cc | 4 +- .../renderer_host/resource_dispatcher_host.cc | 4 +- chrome/browser/repost_form_warning_dialog.cc | 2 +- .../safe_browsing/safe_browsing_blocking_page.cc | 8 +- .../safe_browsing/safe_browsing_blocking_page.h | 2 +- .../browser/safe_browsing/safe_browsing_service.cc | 2 +- chrome/browser/sessions/base_session_service.cc | 4 +- chrome/browser/sessions/session_restore.cc | 4 +- chrome/browser/sessions/session_service.cc | 6 +- .../browser/sessions/session_service_unittest.cc | 2 +- chrome/browser/sessions/session_types.cc | 2 +- chrome/browser/sessions/tab_restore_service.cc | 4 +- .../sessions/tab_restore_service_unittest.cc | 2 +- chrome/browser/site_instance.cc | 145 -- chrome/browser/site_instance.h | 156 -- chrome/browser/site_instance_unittest.cc | 4 +- chrome/browser/ssl_blocking_page.cc | 6 +- chrome/browser/ssl_blocking_page.h | 2 +- chrome/browser/ssl_manager.cc | 14 +- chrome/browser/ssl_manager.h | 4 +- chrome/browser/ssl_policy.cc | 6 +- chrome/browser/status_view.cc | 74 - chrome/browser/status_view.h | 84 - chrome/browser/tab_contents.cc | 605 ------- chrome/browser/tab_contents.h | 560 ------ .../tab_contents/about_internets_status_view.cc | 69 + .../tab_contents/about_internets_status_view.h | 45 + chrome/browser/tab_contents/constrained_window.h | 68 + chrome/browser/tab_contents/infobar_delegate.cc | 93 + chrome/browser/tab_contents/infobar_delegate.h | 206 +++ chrome/browser/tab_contents/interstitial_page.cc | 362 ++++ chrome/browser/tab_contents/interstitial_page.h | 168 ++ chrome/browser/tab_contents/ipc_status_view.cc | 370 ++++ chrome/browser/tab_contents/ipc_status_view.h | 89 + chrome/browser/tab_contents/native_ui_contents.cc | 671 ++++++++ chrome/browser/tab_contents/native_ui_contents.h | 295 ++++ .../browser/tab_contents/navigation_controller.cc | 1233 ++++++++++++++ .../browser/tab_contents/navigation_controller.h | 550 ++++++ chrome/browser/tab_contents/navigation_entry.cc | 64 + chrome/browser/tab_contents/navigation_entry.h | 399 +++++ chrome/browser/tab_contents/network_status_view.cc | 320 ++++ chrome/browser/tab_contents/network_status_view.h | 117 ++ chrome/browser/tab_contents/page_navigator.h | 27 + .../tab_contents/provisional_load_details.cc | 25 + .../tab_contents/provisional_load_details.h | 60 + chrome/browser/tab_contents/site_instance.cc | 145 ++ chrome/browser/tab_contents/site_instance.h | 156 ++ chrome/browser/tab_contents/status_view.cc | 74 + chrome/browser/tab_contents/status_view.h | 84 + chrome/browser/tab_contents/tab_contents.cc | 605 +++++++ chrome/browser/tab_contents/tab_contents.h | 560 ++++++ .../browser/tab_contents/tab_contents_delegate.h | 150 ++ .../browser/tab_contents/tab_contents_factory.cc | 161 ++ chrome/browser/tab_contents/tab_contents_factory.h | 28 + chrome/browser/tab_contents/tab_contents_type.h | 31 + chrome/browser/tab_contents/tab_util.cc | 39 + chrome/browser/tab_contents/tab_util.h | 26 + .../browser/tab_contents/view_source_contents.cc | 19 + chrome/browser/tab_contents/view_source_contents.h | 27 + chrome/browser/tab_contents/view_source_uitest.cc | 110 ++ chrome/browser/tab_contents/web_contents.cc | 1796 ++++++++++++++++++++ chrome/browser/tab_contents/web_contents.h | 572 +++++++ .../browser/tab_contents/web_contents_unittest.cc | 1271 ++++++++++++++ chrome/browser/tab_contents/web_contents_view.cc | 60 + chrome/browser/tab_contents/web_contents_view.h | 191 +++ .../browser/tab_contents/web_contents_view_win.cc | 646 +++++++ .../browser/tab_contents/web_contents_view_win.h | 128 ++ chrome/browser/tab_contents/web_drag_source.cc | 45 + chrome/browser/tab_contents/web_drag_source.h | 49 + chrome/browser/tab_contents/web_drop_target.cc | 182 ++ chrome/browser/tab_contents/web_drop_target.h | 74 + chrome/browser/tab_contents_delegate.h | 150 -- chrome/browser/tab_contents_factory.cc | 162 -- chrome/browser/tab_contents_factory.h | 28 - chrome/browser/tab_contents_type.h | 31 - chrome/browser/tab_util.cc | 39 - chrome/browser/tab_util.h | 26 - chrome/browser/tabs/tab_strip_model.cc | 6 +- chrome/browser/tabs/tab_strip_model.h | 2 +- .../tabs/tab_strip_model_order_controller.cc | 2 +- chrome/browser/tabs/tab_strip_model_unittest.cc | 8 +- chrome/browser/task_manager.cc | 2 +- chrome/browser/task_manager.h | 2 +- chrome/browser/task_manager_resource_providers.cc | 4 +- chrome/browser/toolbar_model.cc | 6 +- chrome/browser/view_source_contents.cc | 19 - chrome/browser/view_source_contents.h | 27 - chrome/browser/view_source_uitest.cc | 110 -- chrome/browser/views/blocked_popup_container.cc | 2 +- chrome/browser/views/blocked_popup_container.h | 4 +- chrome/browser/views/bookmark_bar_view.cc | 4 +- chrome/browser/views/bookmark_bar_view_test.cc | 2 +- chrome/browser/views/bug_report_view.cc | 6 +- chrome/browser/views/constrained_window_impl.cc | 6 +- chrome/browser/views/constrained_window_impl.h | 4 +- chrome/browser/views/download_shelf_view.cc | 4 +- chrome/browser/views/download_started_animation.cc | 2 +- chrome/browser/views/download_tab_view.h | 2 +- chrome/browser/views/external_protocol_dialog.cc | 4 +- chrome/browser/views/find_bar_win.cc | 4 +- chrome/browser/views/frame/browser_view.cc | 6 +- .../browser/views/frame/opaque_non_client_view.cc | 2 +- chrome/browser/views/html_dialog_view.h | 2 +- chrome/browser/views/hung_renderer_view.cc | 2 +- chrome/browser/views/hwnd_html_view.cc | 2 +- chrome/browser/views/infobars/infobar_container.cc | 4 +- chrome/browser/views/infobars/infobars.h | 6 +- chrome/browser/views/location_bar_view.cc | 2 +- chrome/browser/views/location_bar_view.h | 2 +- chrome/browser/views/page_info_window.h | 2 +- chrome/browser/views/shelf_item_dialog.cc | 2 +- .../browser/views/tab_contents_container_view.cc | 4 +- chrome/browser/views/tab_icon_view.cc | 2 +- .../browser/views/tabs/dragged_tab_controller.cc | 4 +- chrome/browser/views/tabs/dragged_tab_controller.h | 2 +- chrome/browser/views/tabs/dragged_tab_view.cc | 2 +- chrome/browser/views/tabs/hwnd_photobooth.cc | 2 +- chrome/browser/views/tabs/tab_renderer.cc | 2 +- chrome/browser/views/tabs/tab_strip.cc | 4 +- chrome/browser/views/toolbar_view.cc | 4 +- chrome/browser/web_app.cc | 2 +- chrome/browser/web_app_icon_manager.cc | 2 +- chrome/browser/web_contents.cc | 1796 -------------------- chrome/browser/web_contents.h | 572 ------- chrome/browser/web_contents_unittest.cc | 1271 -------------- chrome/browser/web_contents_view.cc | 60 - chrome/browser/web_contents_view.h | 191 --- chrome/browser/web_contents_view_win.cc | 646 ------- chrome/browser/web_contents_view_win.h | 128 -- chrome/browser/web_drag_source.cc | 45 - chrome/browser/web_drag_source.h | 49 - chrome/browser/web_drop_target.cc | 182 -- chrome/browser/web_drop_target.h | 74 - 216 files changed, 13028 insertions(+), 12873 deletions(-) delete mode 100644 chrome/browser/about_internets_status_view.cc delete mode 100644 chrome/browser/about_internets_status_view.h delete mode 100644 chrome/browser/constrained_window.h delete mode 100644 chrome/browser/infobar_delegate.cc delete mode 100644 chrome/browser/infobar_delegate.h delete mode 100644 chrome/browser/interstitial_page.cc delete mode 100644 chrome/browser/interstitial_page.h delete mode 100644 chrome/browser/ipc_status_view.cc delete mode 100644 chrome/browser/ipc_status_view.h delete mode 100644 chrome/browser/native_ui_contents.cc delete mode 100644 chrome/browser/native_ui_contents.h delete mode 100644 chrome/browser/navigation_controller.cc delete mode 100644 chrome/browser/navigation_controller.h delete mode 100644 chrome/browser/navigation_entry.cc delete mode 100644 chrome/browser/navigation_entry.h delete mode 100644 chrome/browser/network_status_view.cc delete mode 100644 chrome/browser/network_status_view.h delete mode 100644 chrome/browser/page_navigator.h delete mode 100644 chrome/browser/provisional_load_details.cc delete mode 100644 chrome/browser/provisional_load_details.h delete mode 100644 chrome/browser/site_instance.cc delete mode 100644 chrome/browser/site_instance.h delete mode 100644 chrome/browser/status_view.cc delete mode 100644 chrome/browser/status_view.h delete mode 100644 chrome/browser/tab_contents.cc delete mode 100644 chrome/browser/tab_contents.h create mode 100644 chrome/browser/tab_contents/about_internets_status_view.cc create mode 100644 chrome/browser/tab_contents/about_internets_status_view.h create mode 100644 chrome/browser/tab_contents/constrained_window.h create mode 100644 chrome/browser/tab_contents/infobar_delegate.cc create mode 100644 chrome/browser/tab_contents/infobar_delegate.h create mode 100644 chrome/browser/tab_contents/interstitial_page.cc create mode 100644 chrome/browser/tab_contents/interstitial_page.h create mode 100644 chrome/browser/tab_contents/ipc_status_view.cc create mode 100644 chrome/browser/tab_contents/ipc_status_view.h create mode 100644 chrome/browser/tab_contents/native_ui_contents.cc create mode 100644 chrome/browser/tab_contents/native_ui_contents.h create mode 100644 chrome/browser/tab_contents/navigation_controller.cc create mode 100644 chrome/browser/tab_contents/navigation_controller.h create mode 100644 chrome/browser/tab_contents/navigation_entry.cc create mode 100644 chrome/browser/tab_contents/navigation_entry.h create mode 100644 chrome/browser/tab_contents/network_status_view.cc create mode 100644 chrome/browser/tab_contents/network_status_view.h create mode 100644 chrome/browser/tab_contents/page_navigator.h create mode 100644 chrome/browser/tab_contents/provisional_load_details.cc create mode 100644 chrome/browser/tab_contents/provisional_load_details.h create mode 100644 chrome/browser/tab_contents/site_instance.cc create mode 100644 chrome/browser/tab_contents/site_instance.h create mode 100644 chrome/browser/tab_contents/status_view.cc create mode 100644 chrome/browser/tab_contents/status_view.h create mode 100644 chrome/browser/tab_contents/tab_contents.cc create mode 100644 chrome/browser/tab_contents/tab_contents.h create mode 100644 chrome/browser/tab_contents/tab_contents_delegate.h create mode 100644 chrome/browser/tab_contents/tab_contents_factory.cc create mode 100644 chrome/browser/tab_contents/tab_contents_factory.h create mode 100644 chrome/browser/tab_contents/tab_contents_type.h create mode 100644 chrome/browser/tab_contents/tab_util.cc create mode 100644 chrome/browser/tab_contents/tab_util.h create mode 100644 chrome/browser/tab_contents/view_source_contents.cc create mode 100644 chrome/browser/tab_contents/view_source_contents.h create mode 100644 chrome/browser/tab_contents/view_source_uitest.cc create mode 100644 chrome/browser/tab_contents/web_contents.cc create mode 100644 chrome/browser/tab_contents/web_contents.h create mode 100644 chrome/browser/tab_contents/web_contents_unittest.cc create mode 100644 chrome/browser/tab_contents/web_contents_view.cc create mode 100644 chrome/browser/tab_contents/web_contents_view.h create mode 100644 chrome/browser/tab_contents/web_contents_view_win.cc create mode 100644 chrome/browser/tab_contents/web_contents_view_win.h create mode 100644 chrome/browser/tab_contents/web_drag_source.cc create mode 100644 chrome/browser/tab_contents/web_drag_source.h create mode 100644 chrome/browser/tab_contents/web_drop_target.cc create mode 100644 chrome/browser/tab_contents/web_drop_target.h delete mode 100644 chrome/browser/tab_contents_delegate.h delete mode 100644 chrome/browser/tab_contents_factory.cc delete mode 100644 chrome/browser/tab_contents_factory.h delete mode 100644 chrome/browser/tab_contents_type.h delete mode 100644 chrome/browser/tab_util.cc delete mode 100644 chrome/browser/tab_util.h delete mode 100644 chrome/browser/view_source_contents.cc delete mode 100644 chrome/browser/view_source_contents.h delete mode 100644 chrome/browser/view_source_uitest.cc delete mode 100644 chrome/browser/web_contents.cc delete mode 100644 chrome/browser/web_contents.h delete mode 100644 chrome/browser/web_contents_unittest.cc delete mode 100644 chrome/browser/web_contents_view.cc delete mode 100644 chrome/browser/web_contents_view.h delete mode 100644 chrome/browser/web_contents_view_win.cc delete mode 100644 chrome/browser/web_contents_view_win.h delete mode 100644 chrome/browser/web_drag_source.cc delete mode 100644 chrome/browser/web_drag_source.h delete mode 100644 chrome/browser/web_drop_target.cc delete mode 100644 chrome/browser/web_drop_target.h (limited to 'chrome/browser') diff --git a/chrome/browser/about_internets_status_view.cc b/chrome/browser/about_internets_status_view.cc deleted file mode 100644 index 36c8cfa..0000000 --- a/chrome/browser/about_internets_status_view.cc +++ /dev/null @@ -1,69 +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 "base/file_util.h" -#include "base/path_service.h" -#include "base/string_util.h" -#include "chrome/browser/about_internets_status_view.h" -#include "chrome/browser/tab_contents_delegate.h" - -AboutInternetsStatusView::AboutInternetsStatusView() - : StatusView(TAB_CONTENTS_ABOUT_INTERNETS_STATUS_VIEW) {} - -AboutInternetsStatusView::~AboutInternetsStatusView() { - if (process_handle_.IsValid()) - TerminateProcess(process_handle_.Get(), 0); -} - -const std::wstring AboutInternetsStatusView::GetDefaultTitle() const { - return L"Don't Clog the Tubes!"; -} - -const std::wstring& AboutInternetsStatusView::GetTitle() const { - return title_; -} - -void AboutInternetsStatusView::OnCreate(const CRect& rect) { - HWND contents_hwnd = GetContainerHWND(); - STARTUPINFO startup_info; - memset(&startup_info, 0, sizeof(startup_info)); - startup_info.cb = sizeof(startup_info); - PROCESS_INFORMATION process_info = {0}; - - std::wstring path; - PathService::Get(base::DIR_SYSTEM, &path); - file_util::AppendToPath(&path, L"sspipes.scr"); - std::wstring parameters; - parameters.append(path.c_str()); - // Append the handle of the HWND that we want to render the pipes into. - parameters.append(L" /p "); - parameters.append( - Int64ToWString(reinterpret_cast(contents_hwnd)).c_str()); - BOOL result = - CreateProcess(NULL, - const_cast(parameters.c_str()), - NULL, // LPSECURITY_ATTRIBUTES lpProcessAttributes - NULL, // LPSECURITY_ATTRIBUTES lpThreadAttributes - FALSE, // BOOL bInheritHandles - CREATE_DEFAULT_ERROR_MODE, // DWORD dwCreationFlags - NULL, // LPVOID lpEnvironment - NULL, // LPCTSTR lpCurrentDirectory - &startup_info, // LPstartup_info lpstartup_info - &process_info); // LPPROCESS_INFORMATION - // lpProcessInformation - - if (result) { - title_ = GetDefaultTitle(); - CloseHandle(process_info.hThread); - process_handle_.Set(process_info.hProcess); - } else { - title_ = L"The Tubes are Clogged!"; - } -} - -void AboutInternetsStatusView::OnSize(const CRect& rect) { - // We're required to implement this because it is abstract, but we don't - // actually have anything to do right here. -} - diff --git a/chrome/browser/about_internets_status_view.h b/chrome/browser/about_internets_status_view.h deleted file mode 100644 index dd33a21..0000000 --- a/chrome/browser/about_internets_status_view.h +++ /dev/null @@ -1,45 +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. - -#ifndef CHROME_BROWSER_ABOUT_INTERNETS_STATUS_VIEW_H__ -#define CHROME_BROWSER_ABOUT_INTERNETS_STATUS_VIEW_H__ - -#include "base/scoped_handle.h" -#include "chrome/browser/status_view.h" - -// Displays sspipes.scr in the content HWND. -class AboutInternetsStatusView : public StatusView { - public: - AboutInternetsStatusView(); - virtual ~AboutInternetsStatusView(); - - // TabContents overrides - virtual const std::wstring GetDefaultTitle() const; - virtual const std::wstring& GetTitle() const; - - // StatusView implementations - - // Starts sspipes.scr rendering into the contents HWND. (Actually, it looks - // like this creates a child HWND which is the same size as the contents, - // and draws into that. Thus, it doesn't resize properly.) - // TODO(devint): Fix this resizing issue. A few possibilities: - // 1) Restart the process a few seconds after a resize is completed. - // 2) Render into an invisible HWND and stretchblt to the current HWND. - virtual void OnCreate(const CRect& rect); - // Does nothing, but implementation is required by StatusView. - virtual void OnSize(const CRect& rect); - - private: - // Information about the pipes process, used to close the process when this - // view is destroyed. - ScopedHandle process_handle_; - - // Title of the page. - std::wstring title_; - - DISALLOW_EVIL_CONSTRUCTORS(AboutInternetsStatusView); -}; - -#endif // CHROME_BROWSER_ABOUT_INTERNETS_STATUS_VIEW_H__ - diff --git a/chrome/browser/alternate_nav_url_fetcher.cc b/chrome/browser/alternate_nav_url_fetcher.cc index 3f058c1..24e6a4b 100644 --- a/chrome/browser/alternate_nav_url_fetcher.cc +++ b/chrome/browser/alternate_nav_url_fetcher.cc @@ -4,9 +4,9 @@ #include "chrome/browser/alternate_nav_url_fetcher.h" -#include "chrome/browser/navigation_controller.h" -#include "chrome/browser/navigation_entry.h" -#include "chrome/browser/web_contents.h" +#include "chrome/browser/tab_contents/navigation_controller.h" +#include "chrome/browser/tab_contents/navigation_entry.h" +#include "chrome/browser/tab_contents/web_contents.h" #include "chrome/common/l10n_util.h" #include "chrome/common/resource_bundle.h" diff --git a/chrome/browser/alternate_nav_url_fetcher.h b/chrome/browser/alternate_nav_url_fetcher.h index 7e55af7..d02480c 100644 --- a/chrome/browser/alternate_nav_url_fetcher.h +++ b/chrome/browser/alternate_nav_url_fetcher.h @@ -7,7 +7,7 @@ #include -#include "chrome/browser/infobar_delegate.h" +#include "chrome/browser/tab_contents/infobar_delegate.h" #include "chrome/browser/url_fetcher.h" #include "chrome/common/notification_registrar.h" #include "chrome/common/notification_service.h" diff --git a/chrome/browser/autocomplete/autocomplete_edit.cc b/chrome/browser/autocomplete/autocomplete_edit.cc index 994315e..1cff5ee 100644 --- a/chrome/browser/autocomplete/autocomplete_edit.cc +++ b/chrome/browser/autocomplete/autocomplete_edit.cc @@ -21,7 +21,7 @@ #include "chrome/browser/controller.h" #include "chrome/browser/drag_utils.h" #include "chrome/browser/profile.h" -#include "chrome/browser/tab_contents.h" +#include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/browser/template_url.h" #include "chrome/browser/template_url_model.h" #include "chrome/browser/url_fixer_upper.h" diff --git a/chrome/browser/autofill_manager.cc b/chrome/browser/autofill_manager.cc index 9493992..65396a7 100644 --- a/chrome/browser/autofill_manager.cc +++ b/chrome/browser/autofill_manager.cc @@ -6,7 +6,7 @@ #include "base/string_util.h" #include "chrome/browser/profile.h" -#include "chrome/browser/web_contents.h" +#include "chrome/browser/tab_contents/web_contents.h" AutofillManager::AutofillManager(WebContents* web_contents) : web_contents_(web_contents), diff --git a/chrome/browser/automation/automation_constrained_window_tracker.h b/chrome/browser/automation/automation_constrained_window_tracker.h index 0ebd96e..093fb4f 100644 --- a/chrome/browser/automation/automation_constrained_window_tracker.h +++ b/chrome/browser/automation/automation_constrained_window_tracker.h @@ -8,7 +8,7 @@ #include "chrome/browser/automation/automation_resource_tracker.h" #include "chrome/browser/browser.h" #include "chrome/browser/browser_process.h" -#include "chrome/browser/constrained_window.h" +#include "chrome/browser/tab_contents/constrained_window.h" class AutomationConstrainedWindowTracker : public AutomationResourceTracker { diff --git a/chrome/browser/automation/automation_provider.cc b/chrome/browser/automation/automation_provider.cc index fcc43fa..0f12952 100644 --- a/chrome/browser/automation/automation_provider.cc +++ b/chrome/browser/automation/automation_provider.cc @@ -19,13 +19,13 @@ #include "chrome/browser/external_tab_container.h" #include "chrome/browser/find_notification_details.h" #include "chrome/browser/login_prompt.h" -#include "chrome/browser/navigation_entry.h" #include "chrome/browser/printing/print_job.h" #include "chrome/browser/render_view_host.h" #include "chrome/browser/ssl_manager.h" #include "chrome/browser/ssl_blocking_page.h" -#include "chrome/browser/web_contents.h" -#include "chrome/browser/web_contents_view.h" +#include "chrome/browser/tab_contents/navigation_entry.h" +#include "chrome/browser/tab_contents/web_contents.h" +#include "chrome/browser/tab_contents/web_contents_view.h" #include "chrome/browser/views/bookmark_bar_view.h" #include "chrome/browser/views/location_bar_view.h" #include "chrome/common/chrome_paths.h" diff --git a/chrome/browser/automation/automation_tab_tracker.h b/chrome/browser/automation/automation_tab_tracker.h index 1033ad0..a221ae4 100644 --- a/chrome/browser/automation/automation_tab_tracker.h +++ b/chrome/browser/automation/automation_tab_tracker.h @@ -8,7 +8,7 @@ #include "chrome/browser/automation/automation_resource_tracker.h" #include "chrome/browser/browser.h" #include "chrome/browser/browser_process.h" -#include "chrome/browser/navigation_controller.h" +#include "chrome/browser/tab_contents/navigation_controller.h" #include "chrome/common/notification_registrar.h" class AutomationTabTracker diff --git a/chrome/browser/back_forward_menu_model.cc b/chrome/browser/back_forward_menu_model.cc index 76a6e61..2acd52e 100644 --- a/chrome/browser/back_forward_menu_model.cc +++ b/chrome/browser/back_forward_menu_model.cc @@ -6,9 +6,9 @@ #include "chrome/browser/browser.h" #include "chrome/browser/history_tab_ui.h" -#include "chrome/browser/navigation_controller.h" -#include "chrome/browser/navigation_entry.h" -#include "chrome/browser/tab_contents.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/user_metrics.h" #include "chrome/common/l10n_util.h" #include "net/base/registry_controlled_domain.h" diff --git a/chrome/browser/back_forward_menu_model_unittest.cc b/chrome/browser/back_forward_menu_model_unittest.cc index e194480..dbf4e4c 100644 --- a/chrome/browser/back_forward_menu_model_unittest.cc +++ b/chrome/browser/back_forward_menu_model_unittest.cc @@ -6,11 +6,11 @@ #include "base/file_util.h" #include "base/path_service.h" -#include "chrome/browser/navigation_controller.h" -#include "chrome/browser/navigation_entry.h" #include "chrome/browser/profile_manager.h" -#include "chrome/browser/tab_contents.h" -#include "chrome/browser/tab_contents_factory.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_factory.h" #include "testing/gtest/include/gtest/gtest.h" const TabContentsType kHTTPTabContentsType = diff --git a/chrome/browser/bookmarks/bookmark_context_menu.cc b/chrome/browser/bookmarks/bookmark_context_menu.cc index 51797ad..1d1e589 100644 --- a/chrome/browser/bookmarks/bookmark_context_menu.cc +++ b/chrome/browser/bookmarks/bookmark_context_menu.cc @@ -8,9 +8,9 @@ #include "chrome/browser/bookmarks/bookmark_utils.h" #include "chrome/browser/browser.h" #include "chrome/browser/browser_list.h" -#include "chrome/browser/page_navigator.h" #include "chrome/browser/profile.h" -#include "chrome/browser/tab_contents.h" +#include "chrome/browser/tab_contents/page_navigator.h" +#include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/browser/user_metrics.h" #include "chrome/browser/views/bookmark_bar_view.h" #include "chrome/browser/views/bookmark_editor_view.h" diff --git a/chrome/browser/bookmarks/bookmark_context_menu_test.cc b/chrome/browser/bookmarks/bookmark_context_menu_test.cc index 3f0e063..0bec1ca 100644 --- a/chrome/browser/bookmarks/bookmark_context_menu_test.cc +++ b/chrome/browser/bookmarks/bookmark_context_menu_test.cc @@ -9,7 +9,7 @@ #include "chrome/browser/views/bookmark_bar_view.h" #include "chrome/common/pref_names.h" #include "chrome/common/pref_service.h" -#include "chrome/browser/page_navigator.h" +#include "chrome/browser/tab_contents/page_navigator.h" #include "chrome/test/testing_profile.h" #include "testing/gtest/include/gtest/gtest.h" diff --git a/chrome/browser/bookmarks/bookmark_utils.cc b/chrome/browser/bookmarks/bookmark_utils.cc index b24b9b7..7184f3c 100644 --- a/chrome/browser/bookmarks/bookmark_utils.cc +++ b/chrome/browser/bookmarks/bookmark_utils.cc @@ -11,8 +11,8 @@ #include "chrome/browser/browser.h" #include "chrome/browser/browser_list.h" #include "chrome/browser/history/query_parser.h" -#include "chrome/browser/page_navigator.h" -#include "chrome/browser/tab_contents.h" +#include "chrome/browser/tab_contents/page_navigator.h" +#include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/common/drag_drop_types.h" #include "chrome/common/l10n_util.h" #include "chrome/common/os_exchange_data.h" diff --git a/chrome/browser/browser.cc b/chrome/browser/browser.cc index 0f0a099..a3cd5dd 100644 --- a/chrome/browser/browser.cc +++ b/chrome/browser/browser.cc @@ -26,16 +26,17 @@ #include "chrome/browser/dom_ui/new_tab_ui.h" #include "chrome/browser/download/save_package.h" #include "chrome/browser/history_tab_ui.h" -#include "chrome/browser/interstitial_page.h" -#include "chrome/browser/navigation_controller.h" -#include "chrome/browser/navigation_entry.h" #include "chrome/browser/options_window.h" #include "chrome/browser/plugin_process_host.h" #include "chrome/browser/plugin_service.h" #include "chrome/browser/profile.h" #include "chrome/browser/sessions/session_service.h" #include "chrome/browser/ssl_error_info.h" -#include "chrome/browser/site_instance.h" +#include "chrome/browser/tab_contents/interstitial_page.h" +#include "chrome/browser/tab_contents/navigation_controller.h" +#include "chrome/browser/tab_contents/navigation_entry.h" +#include "chrome/browser/tab_contents/site_instance.h" +#include "chrome/browser/tab_contents/web_contents_view.h" #include "chrome/browser/task_manager.h" #include "chrome/browser/url_fixer_upper.h" #include "chrome/browser/user_data_manager.h" @@ -48,7 +49,6 @@ #include "chrome/browser/views/select_profile_dialog.h" #include "chrome/browser/views/status_bubble.h" #include "chrome/browser/views/toolbar_star_toggle.h" -#include "chrome/browser/web_contents_view.h" #include "chrome/browser/window_sizer.h" #include "chrome/common/chrome_constants.h" #include "chrome/common/chrome_switches.h" diff --git a/chrome/browser/browser.h b/chrome/browser/browser.h index fa3927d..aba16c3 100644 --- a/chrome/browser/browser.h +++ b/chrome/browser/browser.h @@ -12,8 +12,8 @@ #include "chrome/browser/shell_dialogs.h" #include "chrome/browser/browser_window.h" #include "chrome/browser/sessions/session_id.h" -#include "chrome/browser/tab_contents.h" -#include "chrome/browser/tab_contents_delegate.h" +#include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/tab_contents/tab_contents_delegate.h" #include "chrome/browser/tabs/tab_strip_model.h" #include "chrome/browser/toolbar_model.h" #include "chrome/common/notification_service.h" diff --git a/chrome/browser/browser.scons b/chrome/browser/browser.scons index 60b5e3d..e937d99 100644 --- a/chrome/browser/browser.scons +++ b/chrome/browser/browser.scons @@ -99,7 +99,7 @@ if not env.Bit('mac'): 'printing/page_range.cc', 'printing/page_setup.cc', 'printing/units.cc', - 'provisional_load_details.cc', + 'tab_contents/provisional_load_details.cc', 'renderer_host/async_resource_handler.cc', 'renderer_host/buffered_resource_handler.cc', 'renderer_host/download_resource_handler.cc', @@ -134,7 +134,6 @@ if env.Bit('windows'): # TODO: Port these. input_files.extend([ 'autofill_manager.cc', - 'about_internets_status_view.cc', 'alternate_nav_url_fetcher.cc', 'app_modal_dialog_queue.cc', 'autocomplete/autocomplete.cc', @@ -216,9 +215,6 @@ if env.Bit('windows'): 'importer/ie_importer.cc', 'importer/importer.cc', 'importer/toolbar_importer.cc', - 'infobar_delegate.cc', - 'interstitial_page.cc', - 'ipc_status_view.cc', 'jankometer.cc', 'js_before_unload_handler.cc', 'jsmessage_box_handler.cc', @@ -226,13 +222,9 @@ if env.Bit('windows'): 'memory_details.cc', 'metrics_service.cc', 'modal_html_dialog_delegate.cc', - 'native_ui_contents.cc', - 'navigation_controller.cc', - 'navigation_entry.cc', 'net/dns_global.cc', 'net/dns_master.cc', 'net/dns_slave.cc', - 'network_status_view.cc', 'google_update.cc', 'password_form_manager.cc', 'password_manager.cc', @@ -274,14 +266,27 @@ if env.Bit('windows'): 'sessions/session_types.cc', 'sessions/tab_restore_service.cc', 'shell_integration.cc', - 'site_instance.cc', 'ssl_blocking_page.cc', 'ssl_manager.cc', 'ssl_policy.cc', - 'status_view.cc', - 'tab_contents.cc', - 'tab_contents_factory.cc', - 'tab_util.cc', + 'tab_contents/about_internets_status_view.cc', + 'tab_contents/infobar_delegate.cc', + 'tab_contents/interstitial_page.cc', + 'tab_contents/ipc_status_view.cc', + 'tab_contents/native_ui_contents.cc', + 'tab_contents/navigation_controller.cc', + 'tab_contents/navigation_entry.cc', + 'tab_contents/network_status_view.cc', + 'tab_contents/site_instance.cc', + 'tab_contents/status_view.cc', + 'tab_contents/tab_contents.cc', + 'tab_contents/tab_contents_factory.cc', + 'tab_contents/tab_util.cc', + 'tab_contents/view_source_contents.cc', + 'tab_contents/web_contents.cc', + 'tab_contents/web_contents_view.cc', + 'tab_contents/web_drag_source.cc', + 'tab_contents/web_drop_target.cc', 'tabs/tab_strip_model.cc', 'tabs/tab_strip_model_order_controller.cc', 'task_manager.cc', @@ -291,15 +296,10 @@ if env.Bit('windows'): 'toolbar_model.cc', 'url_fixer_upper.cc', 'user_data_manager.cc', - 'view_source_contents.cc', 'visitedlink_master.cc', 'web_app.cc', 'web_app_icon_manager.cc', 'web_app_launcher.cc', - 'web_contents.cc', - 'web_contents_view.cc', - 'web_drag_source.cc', - 'web_drop_target.cc', 'webdata/web_data_service.cc', 'window_sizer.cc', ]) @@ -310,7 +310,7 @@ if env.Bit('windows'): 'browser_main_win.cc', 'importer/firefox_profile_lock_win.cc', 'render_widget_host_view_win.cc', - 'web_contents_view_win.cc', + 'tab_contents/web_contents_view_win.cc', 'webdata/web_database_win.cc', ]) diff --git a/chrome/browser/browser.vcproj b/chrome/browser/browser.vcproj index 811986b..3b0348b 100644 --- a/chrome/browser/browser.vcproj +++ b/chrome/browser/browser.vcproj @@ -586,14 +586,6 @@ > - - - - @@ -803,49 +795,9 @@ - - - - - - - - - - - - - - - - - - - - @@ -889,70 +841,6 @@ RelativePath=".\ssl_manager.h" > - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -1653,22 +1517,6 @@ RelativePath=".\drag_utils.h" > - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -2429,14 +2593,6 @@ > - - - - diff --git a/chrome/browser/browser_about_handler.cc b/chrome/browser/browser_about_handler.cc index 0687e4f..0f4326b 100644 --- a/chrome/browser/browser_about_handler.cc +++ b/chrome/browser/browser_about_handler.cc @@ -21,7 +21,6 @@ #include "chrome/browser/browser_process.h" #include "chrome/browser/browser_resources.h" #include "chrome/browser/dom_ui/chrome_url_data_manager.h" -#include "chrome/browser/ipc_status_view.h" #include "chrome/browser/memory_details.h" #include "chrome/browser/net/dns_global.h" #include "chrome/browser/plugin_process_host.h" @@ -30,6 +29,7 @@ #include "chrome/browser/profile_manager.h" #include "chrome/browser/render_process_host.h" #include "chrome/browser/render_view_host.h" +#include "chrome/browser/tab_contents/ipc_status_view.h" #include "chrome/common/jstemplate_builder.h" #include "chrome/common/l10n_util.h" #include "chrome/common/pref_names.h" diff --git a/chrome/browser/browser_about_handler.h b/chrome/browser/browser_about_handler.h index 8e6cf76..1d41547 100644 --- a/chrome/browser/browser_about_handler.h +++ b/chrome/browser/browser_about_handler.h @@ -11,7 +11,7 @@ #include "base/basictypes.h" #include "base/image_util.h" -#include "chrome/browser/web_contents.h" +#include "chrome/browser/tab_contents/web_contents.h" #include "chrome/browser/dom_ui/chrome_url_data_manager.h" class GURL; diff --git a/chrome/browser/browser_commands_unittest.cc b/chrome/browser/browser_commands_unittest.cc index 13aa318..6029577 100644 --- a/chrome/browser/browser_commands_unittest.cc +++ b/chrome/browser/browser_commands_unittest.cc @@ -5,8 +5,8 @@ #include "chrome/app/chrome_dll_resource.h" #include "chrome/browser/browser.h" #include "chrome/browser/browser_list.h" -#include "chrome/browser/navigation_controller.h" -#include "chrome/browser/navigation_entry.h" +#include "chrome/browser/tab_contents/navigation_controller.h" +#include "chrome/browser/tab_contents/navigation_entry.h" #include "chrome/test/browser_with_test_window_test.h" typedef BrowserWithTestWindowTest BrowserCommandsTest; diff --git a/chrome/browser/browser_init.cc b/chrome/browser/browser_init.cc index 0d6d128..24a77f2 100644 --- a/chrome/browser/browser_init.cc +++ b/chrome/browser/browser_init.cc @@ -24,11 +24,11 @@ #include "chrome/browser/dom_ui/new_tab_ui.h" #include "chrome/browser/extensions/extensions_service.h" #include "chrome/browser/first_run.h" -#include "chrome/browser/infobar_delegate.h" -#include "chrome/browser/navigation_controller.h" #include "chrome/browser/net/dns_global.h" #include "chrome/browser/session_startup_pref.h" #include "chrome/browser/sessions/session_restore.h" +#include "chrome/browser/tab_contents/infobar_delegate.h" +#include "chrome/browser/tab_contents/navigation_controller.h" #include "chrome/browser/tabs/tab_strip_model.h" #include "chrome/browser/url_fixer_upper.h" #include "chrome/browser/web_app_launcher.h" diff --git a/chrome/browser/browser_list.cc b/chrome/browser/browser_list.cc index 2665daa..7a09d96 100644 --- a/chrome/browser/browser_list.cc +++ b/chrome/browser/browser_list.cc @@ -12,7 +12,7 @@ #include "chrome/browser/browser_window.h" #include "chrome/browser/profile.h" #include "chrome/browser/profile_manager.h" -#include "chrome/browser/web_contents.h" +#include "chrome/browser/tab_contents/web_contents.h" #include "chrome/common/notification_service.h" #include "chrome/views/window.h" diff --git a/chrome/browser/browser_prefs.cc b/chrome/browser/browser_prefs.cc index a982561..6946fa8 100644 --- a/chrome/browser/browser_prefs.cc +++ b/chrome/browser/browser_prefs.cc @@ -26,7 +26,7 @@ #include "chrome/browser/views/frame/browser_view.h" #include "chrome/browser/views/keyword_editor_view.h" #include "chrome/browser/views/page_info_window.h" -#include "chrome/browser/web_contents.h" +#include "chrome/browser/tab_contents/web_contents.h" namespace browser { diff --git a/chrome/browser/browsing_instance.cc b/chrome/browser/browsing_instance.cc index 542b4c0..527feb1a 100644 --- a/chrome/browser/browsing_instance.cc +++ b/chrome/browser/browsing_instance.cc @@ -5,7 +5,7 @@ #include "chrome/browser/browsing_instance.h" #include "base/command_line.h" -#include "chrome/browser/site_instance.h" +#include "chrome/browser/tab_contents/site_instance.h" #include "chrome/common/chrome_switches.h" /*static*/ diff --git a/chrome/browser/cert_store.cc b/chrome/browser/cert_store.cc index 542b3d8..035fc66 100644 --- a/chrome/browser/cert_store.cc +++ b/chrome/browser/cert_store.cc @@ -8,7 +8,7 @@ #include #include "chrome/browser/render_view_host.h" -#include "chrome/browser/web_contents.h" +#include "chrome/browser/tab_contents/web_contents.h" #include "chrome/common/stl_util-inl.h" template diff --git a/chrome/browser/constrained_window.h b/chrome/browser/constrained_window.h deleted file mode 100644 index d703ad2..0000000 --- a/chrome/browser/constrained_window.h +++ /dev/null @@ -1,68 +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. - -#ifndef CHROME_BROWSER_CONSTRAINED_WINDOW_H__ -#define CHROME_BROWSER_CONSTRAINED_WINDOW_H__ - -#include "chrome/common/page_transition_types.h" -#include "webkit/glue/window_open_disposition.h" - -class ConstrainedWindow; -namespace views { -class View; -class WindowDelegate; -} -namespace gfx { -class Point; -class Rect; -} -class GURL; -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 views::View subclass - // that provides the client area. Typical uses include the HTTP Basic Auth - // prompt. The caller must provide an object implementing - // views::WindowDelegate so that the Constrained Window can be properly - // configured. If |initial_bounds| is empty, the dialog will be centered - // within the constraining TabContents. - static ConstrainedWindow* CreateConstrainedDialog( - TabContents* owner, - const gfx::Rect& initial_bounds, - views::View* contents_view, - views::WindowDelegate* window_delegate); - - // Closes the Constrained Window. - virtual void CloseConstrainedWindow() = 0; - - // Repositions the Constrained Window so that the lower right corner - // of the titlebar is at the passed in |anchor_point|. - virtual void RepositionConstrainedWindowTo( - const gfx::Point& anchor_point) = 0; - - // Tells the Constrained Window that the constraining TabContents was hidden, - // e.g. via a tab switch. - virtual void WasHidden() = 0; - - // Tells the Constrained Window that the constraining TabContents became - // visible, e.g. via a tab switch. - virtual void DidBecomeSelected() = 0; - - // Returns the title of the Constrained Window. - virtual std::wstring GetWindowTitle() const = 0; - - // Returns the current display rectangle (relative to its - // parent). This method is only called from the unit tests to check - // the location/size of a constrained window. - virtual const gfx::Rect& GetCurrentBounds() const = 0; -}; - -#endif // #ifndef CHROME_BROWSER_CONSTRAINED_WINDOW_H__ diff --git a/chrome/browser/debugger/debugger_host_impl.cpp b/chrome/browser/debugger/debugger_host_impl.cpp index 32c13fd..0d39964 100644 --- a/chrome/browser/debugger/debugger_host_impl.cpp +++ b/chrome/browser/debugger/debugger_host_impl.cpp @@ -9,7 +9,7 @@ #include "chrome/browser/debugger/debugger_io.h" #include "chrome/browser/debugger/debugger_wrapper.h" #include "chrome/browser/render_view_host.h" -#include "chrome/browser/web_contents.h" +#include "chrome/browser/tab_contents/web_contents.h" #include "chrome/common/notification_service.h" class TabContentsReference : public NotificationObserver { diff --git a/chrome/browser/debugger/debugger_node.cc b/chrome/browser/debugger/debugger_node.cc index de5d3a6..32e7afd 100644 --- a/chrome/browser/debugger/debugger_node.cc +++ b/chrome/browser/debugger/debugger_node.cc @@ -11,7 +11,7 @@ #include "chrome/browser/browser_process.h" #include "chrome/browser/render_process_host.h" #include "chrome/browser/render_view_host.h" -#include "chrome/browser/web_contents.h" +#include "chrome/browser/tab_contents/web_contents.h" #include "chrome/browser/debugger/debugger_shell.h" DebuggerNode::DebuggerNode() : valid_(true), observing_(false), data_(NULL) { diff --git a/chrome/browser/debugger/debugger_shell.cc b/chrome/browser/debugger/debugger_shell.cc index 9858613..b64f083 100644 --- a/chrome/browser/debugger/debugger_shell.cc +++ b/chrome/browser/debugger/debugger_shell.cc @@ -15,7 +15,7 @@ #include "chrome/browser/debugger/debugger_node.h" #include "chrome/browser/debugger/resources/debugger_resources.h" #include "chrome/browser/render_process_host.h" -#include "chrome/browser/tab_contents.h" +#include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/resource_bundle.h" diff --git a/chrome/browser/debugger/debugger_view.cc b/chrome/browser/debugger/debugger_view.cc index 530ffbf..97cb229 100644 --- a/chrome/browser/debugger/debugger_view.cc +++ b/chrome/browser/debugger/debugger_view.cc @@ -16,11 +16,11 @@ #include "chrome/browser/debugger/debugger_wrapper.h" #include "chrome/browser/dom_ui/chrome_url_data_manager.h" #include "chrome/browser/render_view_host.h" -#include "chrome/browser/tab_contents.h" +#include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/browser/view_ids.h" #include "chrome/browser/views/standard_layout.h" #include "chrome/browser/views/tab_contents_container_view.h" -#include "chrome/browser/web_contents.h" +#include "chrome/browser/tab_contents/web_contents.h" #include "chrome/common/gfx/chrome_canvas.h" #include "chrome/common/resource_bundle.h" #include "chrome/views/grid_layout.h" diff --git a/chrome/browser/debugger/debugger_view.h b/chrome/browser/debugger/debugger_view.h index 9603777..6c6457e 100644 --- a/chrome/browser/debugger/debugger_view.h +++ b/chrome/browser/debugger/debugger_view.h @@ -11,7 +11,7 @@ #define CHROME_BROWSER_DEBUGGER_DEBUGGER_VIEW_H__ #include "base/gfx/size.h" -#include "chrome/browser/tab_contents_delegate.h" +#include "chrome/browser/tab_contents/tab_contents_delegate.h" #include "chrome/views/view.h" #include "chrome/views/text_field.h" diff --git a/chrome/browser/debugger/debugger_window.cc b/chrome/browser/debugger/debugger_window.cc index e340bff..36ebf69 100644 --- a/chrome/browser/debugger/debugger_window.cc +++ b/chrome/browser/debugger/debugger_window.cc @@ -4,12 +4,12 @@ #include "base/string_util.h" #include "chrome/browser/browser_process.h" -#include "chrome/browser/constrained_window.h" #include "chrome/browser/debugger/debugger_host_impl.h" #include "chrome/browser/debugger/debugger_view.h" #include "chrome/browser/debugger/debugger_window.h" #include "chrome/browser/debugger/debugger_wrapper.h" -#include "chrome/browser/tab_contents.h" +#include "chrome/browser/tab_contents/constrained_window.h" +#include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/common/l10n_util.h" #include "generated_resources.h" diff --git a/chrome/browser/dom_ui/dom_ui_contents.cc b/chrome/browser/dom_ui/dom_ui_contents.cc index 3001c9e..1f6f220 100644 --- a/chrome/browser/dom_ui/dom_ui_contents.cc +++ b/chrome/browser/dom_ui/dom_ui_contents.cc @@ -6,8 +6,8 @@ #include "chrome/browser/dom_ui/dom_ui.h" #include "chrome/browser/dom_ui/history_ui.h" -#include "chrome/browser/navigation_entry.h" #include "chrome/browser/render_view_host.h" +#include "chrome/browser/tab_contents/navigation_entry.h" #include "chrome/common/resource_bundle.h" // The scheme used for DOMUIContentses diff --git a/chrome/browser/dom_ui/dom_ui_contents.h b/chrome/browser/dom_ui/dom_ui_contents.h index c347c07..4712552 100644 --- a/chrome/browser/dom_ui/dom_ui_contents.h +++ b/chrome/browser/dom_ui/dom_ui_contents.h @@ -8,7 +8,7 @@ #define CHROME_BROWSER_DOM_UI_CONTENTS_H__ #include "chrome/browser/dom_ui/chrome_url_data_manager.h" -#include "chrome/browser/web_contents.h" +#include "chrome/browser/tab_contents/web_contents.h" #include "webkit/glue/webpreferences.h" class DOMUI; diff --git a/chrome/browser/dom_ui/dom_ui_host.cc b/chrome/browser/dom_ui/dom_ui_host.cc index ff2ca1e..91ba5f5 100644 --- a/chrome/browser/dom_ui/dom_ui_host.cc +++ b/chrome/browser/dom_ui/dom_ui_host.cc @@ -7,8 +7,8 @@ #include "base/json_reader.h" #include "base/json_writer.h" #include "chrome/browser/browser.h" -#include "chrome/browser/navigation_entry.h" -#include "chrome/browser/tab_contents_type.h" +#include "chrome/browser/tab_contents/navigation_entry.h" +#include "chrome/browser/tab_contents/tab_contents_type.h" #include "chrome/browser/render_view_host.h" DOMUIHost::DOMUIHost(Profile* profile, diff --git a/chrome/browser/dom_ui/dom_ui_host.h b/chrome/browser/dom_ui/dom_ui_host.h index 408e62c..4ae5e86 100644 --- a/chrome/browser/dom_ui/dom_ui_host.h +++ b/chrome/browser/dom_ui/dom_ui_host.h @@ -12,7 +12,7 @@ #ifndef CHROME_BROWSER_DOM_UI_DOM_UI_HOST_H__ #define CHROME_BROWSER_DOM_UI_DOM_UI_HOST_H__ -#include "chrome/browser/web_contents.h" +#include "chrome/browser/tab_contents/web_contents.h" #include "webkit/glue/webpreferences.h" class DOMMessageDispatcher; diff --git a/chrome/browser/dom_ui/new_tab_ui.cc b/chrome/browser/dom_ui/new_tab_ui.cc index d47bdaa..9b7107a 100644 --- a/chrome/browser/dom_ui/new_tab_ui.cc +++ b/chrome/browser/dom_ui/new_tab_ui.cc @@ -14,10 +14,10 @@ #include "chrome/browser/dom_ui/dom_ui_contents.h" #include "chrome/browser/history_tab_ui.h" #include "chrome/browser/history/page_usage_data.h" -#include "chrome/browser/navigation_entry.h" #include "chrome/browser/profile.h" #include "chrome/browser/render_view_host.h" #include "chrome/browser/sessions/session_types.h" +#include "chrome/browser/tab_contents/navigation_entry.h" #include "chrome/browser/template_url.h" #include "chrome/browser/user_data_manager.h" #include "chrome/browser/user_metrics.h" diff --git a/chrome/browser/download/download_file.cc b/chrome/browser/download/download_file.cc index da4c3b1..70d733d 100644 --- a/chrome/browser/download/download_file.cc +++ b/chrome/browser/download/download_file.cc @@ -16,8 +16,8 @@ #include "chrome/browser/download/download_manager.h" #include "chrome/browser/profile.h" #include "chrome/browser/renderer_host/resource_dispatcher_host.h" -#include "chrome/browser/tab_util.h" -#include "chrome/browser/web_contents.h" +#include "chrome/browser/tab_contents/tab_util.h" +#include "chrome/browser/tab_contents/web_contents.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/stl_util-inl.h" #include "chrome/common/win_util.h" diff --git a/chrome/browser/download/download_manager.cc b/chrome/browser/download/download_manager.cc index 199b8df..1abfb87 100644 --- a/chrome/browser/download/download_manager.cc +++ b/chrome/browser/download/download_manager.cc @@ -25,8 +25,8 @@ #include "chrome/browser/render_process_host.h" #include "chrome/browser/render_view_host.h" #include "chrome/browser/renderer_host/resource_dispatcher_host.h" -#include "chrome/browser/tab_util.h" -#include "chrome/browser/web_contents.h" +#include "chrome/browser/tab_contents/tab_util.h" +#include "chrome/browser/tab_contents/web_contents.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/l10n_util.h" #include "chrome/common/notification_service.h" diff --git a/chrome/browser/download/download_request_manager.cc b/chrome/browser/download/download_request_manager.cc index ac4cdb5..9410cd3 100644 --- a/chrome/browser/download/download_request_manager.cc +++ b/chrome/browser/download/download_request_manager.cc @@ -6,12 +6,12 @@ #include "base/message_loop.h" #include "base/thread.h" -#include "chrome/browser/navigation_controller.h" -#include "chrome/browser/navigation_entry.h" -#include "chrome/browser/constrained_window.h" -#include "chrome/browser/tab_contents_delegate.h" -#include "chrome/browser/tab_util.h" -#include "chrome/browser/web_contents.h" +#include "chrome/browser/tab_contents/constrained_window.h" +#include "chrome/browser/tab_contents/navigation_controller.h" +#include "chrome/browser/tab_contents/navigation_entry.h" +#include "chrome/browser/tab_contents/tab_contents_delegate.h" +#include "chrome/browser/tab_contents/tab_util.h" +#include "chrome/browser/tab_contents/web_contents.h" #include "chrome/common/l10n_util.h" #include "chrome/common/notification_registrar.h" #include "chrome/common/notification_service.h" diff --git a/chrome/browser/download/download_request_manager_unittest.cc b/chrome/browser/download/download_request_manager_unittest.cc index 14ba6be..61da19e 100644 --- a/chrome/browser/download/download_request_manager_unittest.cc +++ b/chrome/browser/download/download_request_manager_unittest.cc @@ -3,7 +3,7 @@ // found in the LICENSE file. #include "chrome/browser/download/download_request_manager.h" -#include "chrome/browser/navigation_controller.h" +#include "chrome/browser/tab_contents/navigation_controller.h" #include "chrome/test/test_tab_contents.h" #include "chrome/test/testing_profile.h" #include "testing/gtest/include/gtest/gtest.h" diff --git a/chrome/browser/download/save_file_manager.cc b/chrome/browser/download/save_file_manager.cc index 41607ea..fbf5782 100644 --- a/chrome/browser/download/save_file_manager.cc +++ b/chrome/browser/download/save_file_manager.cc @@ -16,9 +16,9 @@ #include "chrome/browser/download/save_file.h" #include "chrome/browser/download/save_package.h" #include "chrome/browser/renderer_host/resource_dispatcher_host.h" -#include "chrome/browser/tab_contents.h" -#include "chrome/browser/tab_util.h" -#include "chrome/browser/web_contents.h" +#include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/tab_contents/tab_util.h" +#include "chrome/browser/tab_contents/web_contents.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/stl_util-inl.h" #include "chrome/common/win_util.h" diff --git a/chrome/browser/download/save_package.cc b/chrome/browser/download/save_package.cc index f8b85af..c32c5ca 100644 --- a/chrome/browser/download/save_package.cc +++ b/chrome/browser/download/save_package.cc @@ -22,8 +22,8 @@ #include "chrome/browser/render_view_host.h" #include "chrome/browser/render_view_host_delegate.h" #include "chrome/browser/renderer_host/resource_dispatcher_host.h" -#include "chrome/browser/tab_util.h" -#include "chrome/browser/web_contents.h" +#include "chrome/browser/tab_contents/tab_util.h" +#include "chrome/browser/tab_contents/web_contents.h" #include "chrome/browser/views/download_shelf_view.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/l10n_util.h" diff --git a/chrome/browser/encoding_menu_controller_delegate.cc b/chrome/browser/encoding_menu_controller_delegate.cc index db81e93..20c8424 100644 --- a/chrome/browser/encoding_menu_controller_delegate.cc +++ b/chrome/browser/encoding_menu_controller_delegate.cc @@ -9,7 +9,7 @@ #include "chrome/browser/browser_process.h" #include "chrome/browser/character_encoding.h" #include "chrome/browser/profile.h" -#include "chrome/browser/web_contents.h" +#include "chrome/browser/tab_contents/web_contents.h" #include "chrome/common/l10n_util.h" #include "chrome/common/pref_names.h" #include "chrome/common/pref_service.h" diff --git a/chrome/browser/external_tab_container.cc b/chrome/browser/external_tab_container.cc index b074746..bc40c4f 100644 --- a/chrome/browser/external_tab_container.cc +++ b/chrome/browser/external_tab_container.cc @@ -8,9 +8,9 @@ #include "base/win_util.h" #include "chrome/browser/automation/automation_provider.h" #include "chrome/browser/profile.h" -#include "chrome/browser/tab_contents.h" +#include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/browser/views/tab_contents_container_view.h" -#include "chrome/browser/web_contents.h" +#include "chrome/browser/tab_contents/web_contents.h" #include "chrome/common/chrome_constants.h" #include "chrome/common/win_util.h" // Included for SetRootViewForHWND. diff --git a/chrome/browser/external_tab_container.h b/chrome/browser/external_tab_container.h index bd9ab4c..b335f13 100644 --- a/chrome/browser/external_tab_container.h +++ b/chrome/browser/external_tab_container.h @@ -11,7 +11,7 @@ #include #include "base/basictypes.h" -#include "chrome/browser/tab_contents_delegate.h" +#include "chrome/browser/tab_contents/tab_contents_delegate.h" #include "chrome/common/chrome_constants.h" #include "chrome/common/notification_registrar.h" #include "chrome/common/notification_service.h" diff --git a/chrome/browser/fav_icon_helper.cc b/chrome/browser/fav_icon_helper.cc index 63f39e3..2f5bd97 100644 --- a/chrome/browser/fav_icon_helper.cc +++ b/chrome/browser/fav_icon_helper.cc @@ -6,11 +6,11 @@ #include "base/gfx/png_decoder.h" #include "base/gfx/png_encoder.h" -#include "chrome/browser/navigation_entry.h" -#include "chrome/browser/navigation_controller.h" -#include "chrome/browser/tab_contents_delegate.h" #include "chrome/browser/render_view_host.h" -#include "chrome/browser/web_contents.h" +#include "chrome/browser/tab_contents/navigation_entry.h" +#include "chrome/browser/tab_contents/navigation_controller.h" +#include "chrome/browser/tab_contents/tab_contents_delegate.h" +#include "chrome/browser/tab_contents/web_contents.h" #include "chrome/common/gfx/favicon_size.h" #include "skia/ext/image_operations.h" diff --git a/chrome/browser/history_tab_ui.h b/chrome/browser/history_tab_ui.h index a99039e..927ad5b 100644 --- a/chrome/browser/history_tab_ui.h +++ b/chrome/browser/history_tab_ui.h @@ -5,7 +5,7 @@ #ifndef CHROME_BROWSER_HISTORY_TAB_UI_H__ #define CHROME_BROWSER_HISTORY_TAB_UI_H__ -#include "chrome/browser/native_ui_contents.h" +#include "chrome/browser/tab_contents/native_ui_contents.h" class BaseHistoryModel; class HistoryView; diff --git a/chrome/browser/history_view.cc b/chrome/browser/history_view.cc index c382226..15274a5 100644 --- a/chrome/browser/history_view.cc +++ b/chrome/browser/history_view.cc @@ -9,8 +9,8 @@ #include "base/word_iterator.h" #include "chrome/browser/browsing_data_remover.h" #include "chrome/browser/drag_utils.h" -#include "chrome/browser/native_ui_contents.h" -#include "chrome/browser/page_navigator.h" +#include "chrome/browser/tab_contents/native_ui_contents.h" +#include "chrome/browser/tab_contents/page_navigator.h" #include "chrome/browser/user_metrics.h" #include "chrome/browser/views/bookmark_bubble_view.h" #include "chrome/browser/views/event_utils.h" diff --git a/chrome/browser/infobar_delegate.cc b/chrome/browser/infobar_delegate.cc deleted file mode 100644 index 44e9cc4..0000000 --- a/chrome/browser/infobar_delegate.cc +++ /dev/null @@ -1,93 +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/infobar_delegate.h" - -#include "base/logging.h" -#include "chrome/browser/navigation_entry.h" -#include "chrome/browser/navigation_controller.h" -#include "chrome/browser/tab_contents.h" -#include "chrome/common/l10n_util.h" - -#include "generated_resources.h" - -// InfoBarDelegate: ------------------------------------------------------------ - -bool InfoBarDelegate::ShouldExpire( - const NavigationController::LoadCommittedDetails& details) const { - bool is_reload = - PageTransition::StripQualifier(details.entry->transition_type()) == - PageTransition::RELOAD; - return is_reload || (contents_unique_id_ != details.entry->unique_id()); -} - -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; -} - -// AlertInfoBarDelegate: ------------------------------------------------------- - -bool AlertInfoBarDelegate::EqualsDelegate(InfoBarDelegate* delegate) const { - AlertInfoBarDelegate* alert_delegate = delegate->AsAlertInfoBarDelegate(); - if (!alert_delegate) - return false; - - return alert_delegate->GetMessageText() == GetMessageText(); -} - -AlertInfoBarDelegate::AlertInfoBarDelegate(TabContents* contents) - : InfoBarDelegate(contents) { -} - -// LinkInfoBarDelegate: -------------------------------------------------------- - -LinkInfoBarDelegate::LinkInfoBarDelegate(TabContents* contents) - : InfoBarDelegate(contents) { -} - -// ConfirmInfoBarDelegate: ----------------------------------------------------- - -std::wstring ConfirmInfoBarDelegate::GetButtonLabel( - InfoBarButton button) const { - if (button == BUTTON_OK) - return l10n_util::GetString(IDS_OK); - if (button == BUTTON_CANCEL) - return l10n_util::GetString(IDS_CANCEL); - NOTREACHED(); - return std::wstring(); -} - -ConfirmInfoBarDelegate::ConfirmInfoBarDelegate(TabContents* contents) - : AlertInfoBarDelegate(contents) { -} - -// SimpleAlertInfoBarDelegate: ------------------------------------------------- - -SimpleAlertInfoBarDelegate::SimpleAlertInfoBarDelegate( - TabContents* contents, - const std::wstring& message, - SkBitmap* icon) - : AlertInfoBarDelegate(contents), - message_(message), - icon_(icon) { -} - -std::wstring SimpleAlertInfoBarDelegate::GetMessageText() const { - return message_; -} - -SkBitmap* SimpleAlertInfoBarDelegate::GetIcon() const { - return icon_; -} - -void SimpleAlertInfoBarDelegate::InfoBarClosed() { - delete this; -} diff --git a/chrome/browser/infobar_delegate.h b/chrome/browser/infobar_delegate.h deleted file mode 100644 index 523bc20..0000000 --- a/chrome/browser/infobar_delegate.h +++ /dev/null @@ -1,206 +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. - -#ifndef CHROME_BROWSER_INFOBAR_DELEGATE_H_ -#define CHROME_BROWSER_INFOBAR_DELEGATE_H_ - -#include - -#include "base/basictypes.h" -#include "chrome/browser/navigation_controller.h" -#include "skia/include/SkBitmap.h" - -class AlertInfoBarDelegate; -class ConfirmInfoBarDelegate; -class InfoBar; -class LinkInfoBarDelegate; - -// 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 -// AlertInfoBarDelegate or ConfirmInfoBarDelegate, or override with your own -// delegate for your own InfoBar variety. -class InfoBarDelegate { - public: - // 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 { - return false; - } - - // 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 after the InfoBar is closed. The delegate is free to delete itself - // at this point. - virtual void InfoBarClosed() {} - - // Called to create the InfoBar. Implementation of this method is - // platform-specific. - virtual InfoBar* CreateInfoBar() = 0; - - // Returns a pointer to the AlertInfoBarDelegate interface, if implemented. - virtual AlertInfoBarDelegate* AsAlertInfoBarDelegate() { - return NULL; - } - - // Returns a pointer to the LinkInfoBarDelegate interface, if implemented. - virtual LinkInfoBarDelegate* AsLinkInfoBarDelegate() { - return NULL; - } - - // Returns a pointer to the ConfirmInfoBarDelegate interface, if implemented. - virtual ConfirmInfoBarDelegate* AsConfirmInfoBarDelegate() { - return NULL; - } - - 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 taht we were - // opened for. Used to help expire on navigations. - int contents_unique_id_; - - DISALLOW_COPY_AND_ASSIGN(InfoBarDelegate); -}; - -// An interface derived from InfoBarDelegate implemented by objects wishing to -// control an AlertInfoBar. -class AlertInfoBarDelegate : public InfoBarDelegate { - public: - // Returns the message string to be displayed for the InfoBar. - virtual std::wstring GetMessageText() const = 0; - - // Return the icon to be shown for this InfoBar. If the returned bitmap is - // NULL, no icon is shown. - virtual SkBitmap* GetIcon() const { return NULL; } - - // Overridden from InfoBarDelegate: - virtual bool EqualsDelegate(InfoBarDelegate* delegate) const; - virtual InfoBar* CreateInfoBar(); - virtual AlertInfoBarDelegate* AsAlertInfoBarDelegate() { return this; } - - protected: - explicit AlertInfoBarDelegate(TabContents* contents); - - DISALLOW_COPY_AND_ASSIGN(AlertInfoBarDelegate); -}; - -// An interface derived from InfoBarDelegate implemented by objects wishing to -// control a LinkInfoBar. -class LinkInfoBarDelegate : public InfoBarDelegate { - public: - // Returns the message string to be displayed in the InfoBar. |link_offset| - // is the position where the link should be inserted. If |link_offset| is set - // to std::wstring::npos (it is by default), the link is right aligned within - // the InfoBar rather than being embedded in the message text. - virtual std::wstring GetMessageTextWithOffset(size_t* link_offset) const { - *link_offset = std::wstring::npos; - return std::wstring(); - } - - // Returns the text of the link to be displayed. - virtual std::wstring GetLinkText() const = 0; - - // Returns the icon that should be shown for this InfoBar, or NULL if there is - // none. - virtual SkBitmap* GetIcon() const { return NULL; } - - // Called when the Link is clicked. The |disposition| specifies how the - // resulting document should be loaded (based on the event flags present when - // the link was clicked). This function returns true if the InfoBar should be - // closed now or false if it should remain until the user explicitly closes - // it. - virtual bool LinkClicked(WindowOpenDisposition disposition) { - return true; - } - - // Overridden from InfoBarDelegate: - virtual InfoBar* CreateInfoBar(); - virtual LinkInfoBarDelegate* AsLinkInfoBarDelegate() { - return this; - } - - protected: - explicit LinkInfoBarDelegate(TabContents* contents); - - DISALLOW_COPY_AND_ASSIGN(LinkInfoBarDelegate); -}; - -// An interface derived from InfoBarDelegate implemented by objects wishing to -// control a ConfirmInfoBar. -class ConfirmInfoBarDelegate : public AlertInfoBarDelegate { - public: - enum InfoBarButton { - BUTTON_NONE = 0, - BUTTON_OK, - BUTTON_CANCEL - }; - - // Return the buttons to be shown for this InfoBar. - virtual int GetButtons() const { - return BUTTON_NONE; - } - - // Return the label for the specified button. The default implementation - // returns "OK" for the OK button and "Cancel" for the Cancel button. - virtual std::wstring GetButtonLabel(InfoBarButton button) const; - - // Called when the OK button is pressed. If the function returns true, the - // InfoBarDelegate should be removed from the associated TabContents. - virtual bool Accept() { return true; } - - // Called when the Cancel button is pressed. If the function returns true, - // the InfoBarDelegate should be removed from the associated TabContents. - virtual bool Cancel() { return true; } - - // Overridden from InfoBarDelegate: - virtual InfoBar* CreateInfoBar(); - virtual ConfirmInfoBarDelegate* AsConfirmInfoBarDelegate() { - return this; - } - - protected: - explicit ConfirmInfoBarDelegate(TabContents* contents); - - DISALLOW_COPY_AND_ASSIGN(ConfirmInfoBarDelegate); -}; - -// Simple implementations for common use cases --------------------------------- - -class SimpleAlertInfoBarDelegate : public AlertInfoBarDelegate { - public: - SimpleAlertInfoBarDelegate(TabContents* contents, - const std::wstring& message, - SkBitmap* icon); - - // Overridden from AlertInfoBarDelegate: - virtual std::wstring GetMessageText() const; - virtual SkBitmap* GetIcon() const; - virtual void InfoBarClosed(); - - private: - std::wstring message_; - SkBitmap* icon_; - - DISALLOW_COPY_AND_ASSIGN(SimpleAlertInfoBarDelegate); -}; - -#endif // #ifndef CHROME_BROWSER_INFOBAR_DELEGATE_H_ diff --git a/chrome/browser/interstitial_page.cc b/chrome/browser/interstitial_page.cc deleted file mode 100644 index fb69929..0000000 --- a/chrome/browser/interstitial_page.cc +++ /dev/null @@ -1,362 +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/interstitial_page.h" - -#include "chrome/browser/browser.h" -#include "chrome/browser/browser_list.h" -#include "chrome/browser/browser_resources.h" -#include "chrome/browser/dom_operation_notification_details.h" -#include "chrome/browser/navigation_controller.h" -#include "chrome/browser/navigation_entry.h" -#include "chrome/browser/render_widget_host_view_win.h" -#include "chrome/browser/web_contents.h" -#include "chrome/browser/web_contents_view_win.h" -#include "chrome/views/window.h" -#include "chrome/views/window_delegate.h" -#include "net/base/escape.h" - -enum ResourceRequestAction { - BLOCK, - RESUME, - CANCEL -}; - -namespace { - -class ResourceRequestTask : public Task { - public: - ResourceRequestTask(RenderViewHost* render_view_host, - ResourceRequestAction action) - : action_(action), - process_id_(render_view_host->process()->host_id()), - render_view_host_id_(render_view_host->routing_id()), - resource_dispatcher_host_( - g_browser_process->resource_dispatcher_host()) { - } - - virtual void Run() { - switch (action_) { - case BLOCK: - resource_dispatcher_host_->BlockRequestsForRenderView( - process_id_, render_view_host_id_); - break; - case RESUME: - resource_dispatcher_host_->ResumeBlockedRequestsForRenderView( - process_id_, render_view_host_id_); - break; - case CANCEL: - resource_dispatcher_host_->CancelBlockedRequestsForRenderView( - 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 - -// static -InterstitialPage::InterstitialPageMap* - InterstitialPage::tab_to_interstitial_page_ = NULL; - -InterstitialPage::InterstitialPage(WebContents* tab, - bool new_navigation, - const GURL& url) - : tab_(tab), - url_(url), - action_taken_(false), - enabled_(true), - new_navigation_(new_navigation), - render_view_host_(NULL), - should_revert_tab_title_(false), - ui_loop_(MessageLoop::current()) { - 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()->GetPendingEntry()); -} - -InterstitialPage::~InterstitialPage() { - InterstitialPageMap::iterator iter = tab_to_interstitial_page_->find(tab_); - DCHECK(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, close it before showing the new one. - if (tab_->interstitial_page()) - tab_->interstitial_page()->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, NOTIFY_RENDER_WIDGET_HOST_DESTROYED, - Source(tab_->render_view_host())); - - // Update the tab_to_interstitial_page_ map. - InterstitialPageMap::const_iterator 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(TAB_CONTENTS_WEB); - entry->set_url(url_); - entry->set_display_url(url_); - entry->set_page_type(NavigationEntry::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(); - - std::string data_url = "data:text/html;charset=utf-8," + - EscapePath(GetHTMLContents()); - render_view_host_->NavigateToURL(GURL(data_url)); - - notification_registrar_.Add(this, NOTIFY_TAB_CONTENTS_DESTROYED, - Source(tab_)); - notification_registrar_.Add(this, NOTIFY_NAV_ENTRY_COMMITTED, - Source(tab_->controller())); - notification_registrar_.Add(this, NOTIFY_NAV_ENTRY_PENDING, - Source(tab_->controller())); -} - -void InterstitialPage::Hide() { - 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(original_tab_title_); - tab_->NotifyNavigationStateChanged(TabContents::INVALIDATE_TITLE); - } - delete this; -} - -void InterstitialPage::Observe(NotificationType type, - const NotificationSource& source, - const NotificationDetails& details) { - switch (type) { - case NOTIFY_NAV_ENTRY_PENDING: - // We are navigating away from the interstitial. Make sure clicking on - // the interstitial will have no effect. - Disable(); - break; - case NOTIFY_RENDER_WIDGET_HOST_DESTROYED: - if (!action_taken_) { - // The RenderViewHost is being destroyed (as part of the tab being - // closed), make sure we clear the blocked requests. - DCHECK(Source(source).ptr() == - tab_->render_view_host()); - TakeActionOnResourceDispatcher(CANCEL); - } - break; - case NOTIFY_TAB_CONTENTS_DESTROYED: - case NOTIFY_NAV_ENTRY_COMMITTED: - if (!action_taken_) { - // 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(); - } -} - -RenderViewHost* InterstitialPage::CreateRenderViewHost() { - RenderViewHost* render_view_host = new RenderViewHost( - SiteInstance::CreateSiteInstance(tab()->profile()), - this, MSG_ROUTING_NONE, NULL); - RenderWidgetHostViewWin* view = - new RenderWidgetHostViewWin(render_view_host); - render_view_host->set_view(view); - view->Create(tab_->GetContentHWND()); - view->set_parent_hwnd(tab_->GetContentHWND()); - WebContentsViewWin* web_contents_view = - static_cast(tab_->view()); - render_view_host->CreateRenderView(); - // SetSize must be called after CreateRenderView or the HWND won't show. - view->SetSize(web_contents_view->GetContainerSize()); - - render_view_host->AllowDomAutomationBindings(); - return render_view_host; -} - -void InterstitialPage::Proceed() { - DCHECK(!action_taken_); - Disable(); - action_taken_ = true; - - // 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! - } -} - -void InterstitialPage::DontProceed() { - DCHECK(!action_taken_); - Disable(); - action_taken_ = true; - - // 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 (new_navigation_) { - // 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(); - } - - Hide(); - // WARNING: we are now deleted! -} - -void InterstitialPage::SetSize(const gfx::Size& size) { - render_view_host_->view()->SetSize(size); -} - -Profile* InterstitialPage::GetProfile() const { - return tab_->profile(); -} - -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); - - // 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::RendererGone(RenderViewHost* render_view_host) { - // Our renderer died. This should not happen in normal cases. - // Just dismiss the interstitial. - DontProceed(); -} - -void InterstitialPage::DomOperationResponse(const std::string& json_string, - int automation_id) { - if (enabled_) - CommandReceived(json_string); -} - -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 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_ = entry->title(); - should_revert_tab_title_ = true; - } - entry->set_title(title); - tab_->NotifyNavigationStateChanged(TabContents::INVALIDATE_TITLE); -} - -void InterstitialPage::Disable() { - enabled_ = false; -} - -void InterstitialPage::TakeActionOnResourceDispatcher( - ResourceRequestAction action) { - DCHECK(MessageLoop::current() == ui_loop_) << - "TakeActionOnResourceDispatcher should be called on the main thread."; - // 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 an IO thread, as when unit-tests we don't - // have one. - if (tab_->render_view_host() && g_browser_process->io_thread()) { - g_browser_process->io_thread()->message_loop()->PostTask( - FROM_HERE, new ResourceRequestTask(tab_->render_view_host(), action)); - } -} - -// static -void InterstitialPage::InitInterstitialPageMap() { - if (!tab_to_interstitial_page_) - tab_to_interstitial_page_ = new InterstitialPageMap; -} - -// static -InterstitialPage* InterstitialPage::GetInterstitialPage( - WebContents* web_contents) { - InitInterstitialPageMap(); - InterstitialPageMap::const_iterator iter = - tab_to_interstitial_page_->find(web_contents); - if (iter == tab_to_interstitial_page_->end()) - return NULL; - - return iter->second; -} diff --git a/chrome/browser/interstitial_page.h b/chrome/browser/interstitial_page.h deleted file mode 100644 index 6c2c76f5..0000000 --- a/chrome/browser/interstitial_page.h +++ /dev/null @@ -1,168 +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. - -#ifndef CHROME_BROWSER_INTERSTITIAL_PAGE_H_ -#define CHROME_BROWSER_INTERSTITIAL_PAGE_H_ - -#include - -#include "chrome/browser/render_view_host_delegate.h" -#include "chrome/common/notification_registrar.h" -#include "googleurl/src/gurl.h" - -class NavigationEntry; -class WebContents; - -// 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 WebContents closing them or the tab containing them -// being closed. - -enum ResourceRequestAction; - -class InterstitialPage : public NotificationObserver, - public RenderViewHostDelegate { - public: - // 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(WebContents* 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(WebContents* web_contents); - - // Sub-classes should return the HTML that should be displayed in the page. - virtual std::string GetHTMLContents() { return std::string(); } - - // 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: 'this' has been 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(); - - // Sizes the RenderViewHost showing the actual interstitial page contents. - void SetSize(const gfx::Size& size); - - protected: - // NotificationObserver method: - virtual void Observe(NotificationType type, - const NotificationSource& source, - const NotificationDetails& details); - - // RenderViewHostDelegate implementation: - virtual Profile* GetProfile() const; - virtual WebPreferences GetWebkitPrefs() { - return WebPreferences(); - } - virtual void DidNavigate(RenderViewHost* render_view_host, - const ViewHostMsg_FrameNavigate_Params& params); - virtual void RendererGone(RenderViewHost* render_view_host); - virtual void DomOperationResponse(const std::string& json_string, - int automation_id); - virtual void UpdateTitle(RenderViewHost* render_view_host, - int32 page_id, - const std::wstring& title); - - // 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) { } - - WebContents* tab() const { return tab_; } - const GURL& url() const { return url_; } - RenderViewHost* render_view_host() const { return render_view_host_; } - - // Creates and shows the RenderViewHost containing the interstitial content. - // Overriden in unit tests. - virtual RenderViewHost* CreateRenderViewHost(); - - private: - // AutomationProvider needs access to Proceed and DontProceed to simulate - // user actions. - friend class AutomationProvider; - - // 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. - WebContents* 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 this interstitial is enabled. See Disable() for more info. - bool enabled_; - - // Whether the Proceed or DontProceed have been called yet. - bool action_taken_; - - // Notification magic. - NotificationRegistrar notification_registrar_; - - // The RenderViewHost displaying the interstitial contents. - RenderViewHost* render_view_host_; - - // 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_; - - // The original title of the tab that should be reverted to when the - // interstitial is hidden. - std::wstring original_tab_title_; - - MessageLoop* ui_loop_; - - // We keep a map of the various blocking pages shown as the UI tests need to - // be able to retrieve them. - typedef std::map InterstitialPageMap; - static InterstitialPageMap* tab_to_interstitial_page_; - - DISALLOW_COPY_AND_ASSIGN(InterstitialPage); -}; - -#endif // #ifndef CHROME_BROWSER_INTERSTITIAL_PAGE_H_ - diff --git a/chrome/browser/ipc_status_view.cc b/chrome/browser/ipc_status_view.cc deleted file mode 100644 index 4e0e2a5..0000000 --- a/chrome/browser/ipc_status_view.cc +++ /dev/null @@ -1,370 +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/ipc_status_view.h" - -#include - -#include "base/logging.h" -#include "base/string_util.h" -#include "chrome/app/chrome_dll_resource.h" -#include "chrome/common/chrome_constants.h" -#include "chrome/common/ipc_logging.h" -#include "chrome/common/plugin_messages.h" -#include "chrome/common/pref_names.h" -#include "chrome/common/pref_service.h" -#include "chrome/common/render_messages.h" - -#ifdef IPC_MESSAGE_LOG_ENABLED - -using base::Time; - -namespace { -const wchar_t kTitleMsg[] = L"IPC Messages"; - -const wchar_t kStartLoggingMsg[] = L"Start IPC Logging"; -const wchar_t kStopLoggingMsg[] = L"Stop IPC Logging"; -const wchar_t kClearMsg[] = L"Clear"; -const wchar_t kSettingsMsg[] = L"Filter"; - -enum { - kTimeColumn = 0, - kChannelColumn, - kMessageColumn, - kFlagsColumn, - kDispatchColumn, - kProcessColumn, - kParamsColumn, -}; - -// This class ensures that we have a link dependency on render_messages.cc and -// plugin_messages.cc, and at the same time sets up the message logger function -// mappings. -class RegisterLoggerFuncs { - public: - RegisterLoggerFuncs() { - RenderMessagesInit(); - PluginMessagesInit(); - } -}; - -RegisterLoggerFuncs g_register_logger_funcs; - -} // namespace - -IPCStatusView* IPCStatusView::current_; - -IPCStatusView::IPCStatusView() - : StatusView(TAB_CONTENTS_IPC_STATUS_VIEW) { - DCHECK(!current_); - current_ = this; - settings_dialog_ = NULL; - init_done_ = false; - view_ = NULL; - view_host_ = NULL; - plugin_ = NULL; - plugin_host_ = NULL; - npobject_ = NULL; - plugin_process_ = NULL; - plugin_process_host_ = NULL; - - IPC::Logging::current()->SetConsumer(this); -} - -IPCStatusView::~IPCStatusView() { - current_ = NULL; - IPC::Logging::current()->SetConsumer(NULL); - - if (settings_dialog_ != NULL) - ::DestroyWindow(settings_dialog_); -} - -const std::wstring IPCStatusView::GetDefaultTitle() { - return kTitleMsg; -} - -void IPCStatusView::SetActive(bool active) { - StatusView::set_is_active(active); - - if (!disabled_messages_.empty() || !active) - return; - - Profile* current_profile = profile(); - if (!current_profile) - return; - PrefService* prefs = current_profile->GetPrefs(); - if (prefs->IsPrefRegistered(prefs::kIpcDisabledMessages)) - return; - prefs->RegisterListPref(prefs::kIpcDisabledMessages); - const ListValue* list = prefs->GetList(prefs::kIpcDisabledMessages); - if (!list) - return; - for (ListValue::const_iterator itr = list->begin(); - itr != list->end(); - ++itr) { - if (!(*itr)->IsType(Value::TYPE_INTEGER)) - continue; - int value = 0; - if (!(*itr)->GetAsInteger(&value)) - continue; - disabled_messages_.insert(value); - } -} - -void IPCStatusView::OnCreate(const CRect& rect) { - CreateButton(IDC_START_LOGGING, kStartLoggingMsg); - CreateButton(IDC_STOP_LOGGING, kStopLoggingMsg); - CreateButton(IDC_CLEAR, kClearMsg); - CreateButton(IDC_SETTINGS, kSettingsMsg); - - // Initialize the list view for messages. - // Don't worry about the size, we'll resize when we get WM_SIZE - message_list_.Create(GetContainerHWND(), const_cast(rect), NULL, - WS_CHILD | WS_VISIBLE | LVS_SORTASCENDING); - message_list_.SetViewType(LVS_REPORT); - message_list_.SetExtendedListViewStyle(LVS_EX_FULLROWSELECT); - - int column_index = 0; - message_list_.InsertColumn(kTimeColumn, L"time", LVCFMT_LEFT, 80); - message_list_.InsertColumn(kChannelColumn, L"channel", LVCFMT_LEFT, 110); - message_list_.InsertColumn(kMessageColumn, L"message", LVCFMT_LEFT, 240); - message_list_.InsertColumn(kFlagsColumn, L"flags", LVCFMT_LEFT, 50); - message_list_.InsertColumn(kDispatchColumn, L"dispatch (ms)", LVCFMT_RIGHT, 80); - message_list_.InsertColumn(kProcessColumn, L"process (ms)", LVCFMT_RIGHT, 80); - message_list_.InsertColumn(kParamsColumn, L"parameters", LVCFMT_LEFT, 500); -} - -void IPCStatusView::Log(const IPC::LogData& data) { - if (disabled_messages_.find(data.type) != disabled_messages_.end()) - return; // Message type is filtered out. - - Time sent = Time::FromInternalValue(data.sent); - Time::Exploded exploded; - sent.LocalExplode(&exploded); - if (exploded.hour > 12) - exploded.hour -= 12; - - std::wstring sent_str = StringPrintf(L"%02d:%02d:%02d.%03d", - exploded.hour, exploded.minute, exploded.second, exploded.millisecond); - - int count = message_list_.GetItemCount(); - int index = message_list_.InsertItem(count, sent_str.c_str()); - - message_list_.SetItemText(index, kTimeColumn, sent_str.c_str()); - message_list_.SetItemText(index, kChannelColumn, data.channel.c_str()); - - std::wstring message_name; - IPC::Logging::GetMessageText(data.type, &message_name, NULL, NULL); - message_list_.SetItemText(index, kMessageColumn, message_name.c_str()); - message_list_.SetItemText(index, kFlagsColumn, data.flags.c_str()); - - int64 time_to_send = (Time::FromInternalValue(data.receive) - - sent).InMilliseconds(); - // time can go backwards by a few ms (see Time), don't show that. - time_to_send = std::max(static_cast(time_to_send), 0); - std::wstring temp = StringPrintf(L"%d", time_to_send); - message_list_.SetItemText(index, kDispatchColumn, temp.c_str()); - - int64 time_to_process = (Time::FromInternalValue(data.dispatch) - - Time::FromInternalValue(data.receive)).InMilliseconds(); - time_to_process = std::max(static_cast(time_to_process), 0); - temp = StringPrintf(L"%d", time_to_process); - message_list_.SetItemText(index, kProcessColumn, temp.c_str()); - - message_list_.SetItemText(index, kParamsColumn, data.params.c_str()); - message_list_.EnsureVisible(index, FALSE); -} - -void IPCStatusView::OnSize(const CRect& rect) { - message_list_.MoveWindow(rect); -} - -void IPCStatusView::OnStartLogging(UINT code, int button_id, HWND hwnd) { - IPC::Logging::current()->Enable(); -} - -void IPCStatusView::OnStopLogging(UINT code, int button_id, HWND hwnd) { - IPC::Logging::current()->Disable(); -} - -void IPCStatusView::OnClear(UINT code, int button_id, HWND hwnd) { - message_list_.DeleteAllItems(); -} - -INT_PTR CALLBACK IPCStatusView::DialogProc( - HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { - switch (msg) { - case WM_INITDIALOG: - current()->InitDialog(hwnd); - return FALSE; // Don't set keyboard focus. - case WM_SYSCOMMAND: - if (wparam == SC_CLOSE) { - current()->CloseDialog(); - return FALSE; - } - break; - case WM_NOTIFY: { - NMLISTVIEW* info = reinterpret_cast(lparam); - if ((wparam == IDC_View || wparam == IDC_ViewHost || wparam == IDC_Plugin || - wparam == IDC_PluginHost || wparam == IDC_NPObject || - wparam == IDC_PluginProcess || wparam == IDC_PluginProcessHost) && - info->hdr.code == LVN_ITEMCHANGED) { - if (info->uChanged & LVIF_STATE) { - bool checked = (info->uNewState >> 12) == 2; - current()->OnCheck(static_cast(info->lParam), checked); - } - return FALSE; - } - break; - } - case WM_COMMAND: - if (HIWORD(wparam) == BN_CLICKED) - current()->OnButtonClick(LOWORD(wparam)); - - break; - } - return FALSE; -} - -void IPCStatusView::InitDialog(HWND hwnd) { - CreateColumn(ViewStart, ViewEnd, ::GetDlgItem(hwnd, IDC_View), &view_); - CreateColumn(ViewHostStart, ViewHostEnd, ::GetDlgItem(hwnd, IDC_ViewHost), - &view_host_); - CreateColumn(PluginStart, PluginEnd, ::GetDlgItem(hwnd, IDC_Plugin), &plugin_); - CreateColumn(PluginHostStart, PluginHostEnd, - ::GetDlgItem(hwnd, IDC_PluginHost), &plugin_host_); - CreateColumn(NPObjectStart, NPObjectEnd, ::GetDlgItem(hwnd, IDC_NPObject), - &npobject_); - CreateColumn(PluginProcessStart, PluginProcessEnd, - ::GetDlgItem(hwnd, IDC_PluginProcess), &plugin_process_); - CreateColumn(PluginProcessHostStart, PluginProcessHostEnd, - ::GetDlgItem(hwnd, IDC_PluginProcessHost), &plugin_process_host_); - init_done_ = true; -} - -void IPCStatusView::CreateColumn( - uint16 start, uint16 end, HWND hwnd, CListViewCtrl** control) { - DCHECK(*control == NULL); - *control = new CListViewCtrl(hwnd); - CListViewCtrl* control_ptr = *control; - control_ptr->SetViewType(LVS_REPORT); - control_ptr->SetExtendedListViewStyle(LVS_EX_CHECKBOXES); - control_ptr->ModifyStyle(0, LVS_SORTASCENDING | LVS_NOCOLUMNHEADER); - control_ptr->InsertColumn(0, L"id", LVCFMT_LEFT, 230); - - std::set* disabled_messages = ¤t()->disabled_messages_; - for (uint16 i = start; i < end; i++) { - std::wstring name; - IPC::Logging::GetMessageText(i, &name, NULL, NULL); - - int index = control_ptr->InsertItem( - LVIF_TEXT | LVIF_PARAM, 0, name.c_str(), 0, 0, 0, i); - - control_ptr->SetItemText(index, 0, name.c_str()); - - if (disabled_messages->find(i) == disabled_messages->end()) - control_ptr->SetCheckState(index, TRUE); - } -} - -void IPCStatusView::CloseDialog() { - delete view_; - delete view_host_; - delete plugin_host_; - delete npobject_; - delete plugin_process_; - delete plugin_process_host_; - view_ = NULL; - view_host_ = NULL; - plugin_ = NULL; - plugin_host_ = NULL; - npobject_ = NULL; - plugin_process_ = NULL; - plugin_process_host_ = NULL; - init_done_ = false; - - ::DestroyWindow(settings_dialog_); - settings_dialog_ = NULL; - - Profile* current_profile = profile(); - if (!current_profile) - return; - PrefService* prefs = current_profile->GetPrefs(); - if (!prefs->IsPrefRegistered(prefs::kIpcDisabledMessages)) - return; - ListValue* list = prefs->GetMutableList(prefs::kIpcDisabledMessages); - list->Clear(); - for (std::set::const_iterator itr = disabled_messages_.begin(); - itr != disabled_messages_.end(); - ++itr) { - list->Append(Value::CreateIntegerValue(*itr)); - } -} - -void IPCStatusView::OnCheck(int id, bool checked) { - if (!init_done_) - return; - - if (checked) { - disabled_messages_.erase(id); - } else { - disabled_messages_.insert(id); - } -} - -void IPCStatusView::OnButtonClick(int id) { - switch(id) { - case IDC_ViewAll: - CheckButtons(view_, true); - break; - case IDC_ViewNone: - CheckButtons(view_, false); - break; - case IDC_ViewHostAll: - CheckButtons(view_host_, true); - break; - case IDC_ViewHostNone: - CheckButtons(view_host_, false); - break; - case IDC_PluginAll: - CheckButtons(plugin_, true); - break; - case IDC_PluginNone: - CheckButtons(plugin_, false); - break; - case IDC_PluginHostAll: - CheckButtons(plugin_host_, true); - break; - case IDC_PluginHostNone: - CheckButtons(plugin_host_, false); - break; - case IDC_NPObjectAll: - CheckButtons(npobject_, true); - break; - case IDC_NPObjectNone: - CheckButtons(npobject_, false); - break; - } -} - -void IPCStatusView::CheckButtons(CListViewCtrl* control, bool check) { - int count = control->GetItemCount(); - for (int i = 0; i < count; ++i) - control->SetCheckState(i, check); -} - -void IPCStatusView::OnSettings(UINT code, int button_id, HWND hwnd) { - if (settings_dialog_ != NULL) - return; - - HINSTANCE module_handle = GetModuleHandle(chrome::kBrowserResourcesDll); - - settings_dialog_ = CreateDialog(module_handle, - MAKEINTRESOURCE(IDD_IPC_SETTINGS), - NULL, - IPCStatusView::DialogProc); - ::ShowWindow(settings_dialog_, SW_SHOW); -} - -#endif // IPC_MESSAGE_LOG_ENABLED diff --git a/chrome/browser/ipc_status_view.h b/chrome/browser/ipc_status_view.h deleted file mode 100644 index b2b7d5a..0000000 --- a/chrome/browser/ipc_status_view.h +++ /dev/null @@ -1,89 +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. - -#ifndef CHROME_BROWSER_IPC_STATUS_VIEW_H__ -#define CHROME_BROWSER_IPC_STATUS_VIEW_H__ - -#include - -#include "base/basictypes.h" -#include "chrome/browser/status_view.h" -#include "chrome/common/ipc_logging.h" -#include "chrome/common/ipc_message_utils.h" - -#ifdef IPC_MESSAGE_LOG_ENABLED - -class IPCStatusView : public StatusView, - public IPC::Logging::Consumer { - public: - // button types - enum { - IDC_START_LOGGING = 101, - IDC_STOP_LOGGING, - IDC_CLEAR, - IDC_SETTINGS, - }; - - IPCStatusView(); - virtual ~IPCStatusView(); - - static IPCStatusView* current() { return current_; } - void Log(const IPC::LogData& data); - - // TabContents overrides - virtual const std::wstring GetDefaultTitle(); - virtual void SetActive(bool active); - - // StatusView implementation - virtual void OnCreate(const CRect& rect); - virtual void OnSize(const CRect& rect); - - BEGIN_MSG_MAP(IPCStatusView) - COMMAND_HANDLER_EX(IDC_START_LOGGING, BN_CLICKED, OnStartLogging) - COMMAND_HANDLER_EX(IDC_STOP_LOGGING, BN_CLICKED, OnStopLogging) - COMMAND_HANDLER_EX(IDC_CLEAR, BN_CLICKED, OnClear) - COMMAND_HANDLER_EX(IDC_SETTINGS, BN_CLICKED, OnSettings) - CHAIN_MSG_MAP(StatusView); - END_MSG_MAP() - - static INT_PTR CALLBACK DialogProc( - HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam); - void InitDialog(HWND hwnd); - void CloseDialog(); - static void CreateColumn( - uint16 start, uint16 end, HWND hwnd, CListViewCtrl** control); - void OnCheck(int id, bool checked); - void OnButtonClick(int id); - static void CheckButtons(CListViewCtrl* control, bool check); - - private: - - // Event handlers - void OnStartLogging(UINT code, int button_id, HWND hwnd); - void OnStopLogging(UINT code, int button_id, HWND hwnd); - void OnClear(UINT code, int button_id, HWND hwnd); - void OnSettings(UINT code, int button_id, HWND hwnd); - - static IPCStatusView* current_; - CListViewCtrl message_list_; - - // Used for the filter dialog. - CListViewCtrl* view_; - CListViewCtrl* view_host_; - CListViewCtrl* plugin_; - CListViewCtrl* plugin_host_; - CListViewCtrl* npobject_; - CListViewCtrl* plugin_process_; - CListViewCtrl* plugin_process_host_; - bool init_done_; - HWND settings_dialog_; - std::set disabled_messages_; - - DISALLOW_EVIL_CONSTRUCTORS(IPCStatusView); -}; - -#endif // IPC_MESSAGE_LOG_ENABLED - -#endif // #ifndef CHROME_BROWSER_IPC_STATUS_VIEW_H__ - diff --git a/chrome/browser/jsmessage_box_handler.cc b/chrome/browser/jsmessage_box_handler.cc index 2a1d2fd..47b0998 100644 --- a/chrome/browser/jsmessage_box_handler.cc +++ b/chrome/browser/jsmessage_box_handler.cc @@ -6,7 +6,7 @@ #include "chrome/browser/app_modal_dialog_queue.h" #include "chrome/browser/browser_process.h" -#include "chrome/browser/web_contents.h" +#include "chrome/browser/tab_contents/web_contents.h" #include "chrome/common/gfx/text_elider.h" #include "chrome/common/l10n_util.h" #include "chrome/common/notification_service.h" diff --git a/chrome/browser/load_notification_details.h b/chrome/browser/load_notification_details.h index 6524399..7c46e87 100644 --- a/chrome/browser/load_notification_details.h +++ b/chrome/browser/load_notification_details.h @@ -11,7 +11,7 @@ #include "base/basictypes.h" #include "base/time.h" -#include "chrome/browser/navigation_controller.h" +#include "chrome/browser/tab_contents/navigation_controller.h" #include "chrome/common/page_transition_types.h" #include "googleurl/src/gurl.h" diff --git a/chrome/browser/login_prompt.cc b/chrome/browser/login_prompt.cc index 24fd24f..3910019 100644 --- a/chrome/browser/login_prompt.cc +++ b/chrome/browser/login_prompt.cc @@ -8,14 +8,14 @@ #include "base/lock.h" #include "base/message_loop.h" #include "chrome/browser/browser_process.h" -#include "chrome/browser/constrained_window.h" #include "chrome/browser/controller.h" -#include "chrome/browser/navigation_controller.h" #include "chrome/browser/password_manager.h" #include "chrome/browser/render_process_host.h" #include "chrome/browser/renderer_host/resource_dispatcher_host.h" -#include "chrome/browser/web_contents.h" -#include "chrome/browser/tab_util.h" +#include "chrome/browser/tab_contents/constrained_window.h" +#include "chrome/browser/tab_contents/navigation_controller.h" +#include "chrome/browser/tab_contents/tab_util.h" +#include "chrome/browser/tab_contents/web_contents.h" #include "chrome/browser/views/login_view.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/l10n_util.h" diff --git a/chrome/browser/memory_details.cc b/chrome/browser/memory_details.cc index 0ad784d..cc762f1 100644 --- a/chrome/browser/memory_details.cc +++ b/chrome/browser/memory_details.cc @@ -17,8 +17,8 @@ #include "chrome/browser/plugin_service.h" #include "chrome/browser/render_process_host.h" #include "chrome/browser/render_view_host.h" -#include "chrome/browser/tab_contents.h" -#include "chrome/browser/web_contents.h" +#include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/tab_contents/web_contents.h" class RenderViewHostDelegate; diff --git a/chrome/browser/native_ui_contents.cc b/chrome/browser/native_ui_contents.cc deleted file mode 100644 index d8098bb..0000000 --- a/chrome/browser/native_ui_contents.cc +++ /dev/null @@ -1,671 +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/native_ui_contents.h" - -#include "chrome/browser/browser.h" -#include "chrome/browser/history_tab_ui.h" -#include "chrome/browser/navigation_entry.h" -#include "chrome/browser/views/download_tab_view.h" -#include "chrome/common/drag_drop_types.h" -#include "chrome/common/gfx/chrome_canvas.h" -#include "chrome/common/gfx/chrome_font.h" -#include "chrome/common/l10n_util.h" -#include "chrome/common/os_exchange_data.h" -#include "chrome/common/resource_bundle.h" -#include "chrome/views/background.h" -#include "chrome/views/checkbox.h" -#include "chrome/views/grid_layout.h" -#include "chrome/views/image_view.h" -#include "chrome/views/root_view.h" -#include "chrome/views/scroll_view.h" -#include "chrome/views/throbber.h" -#include "chrome/views/widget_win.h" - -#include "generated_resources.h" - -using views::ColumnSet; -using views::GridLayout; - -//static -bool NativeUIContents::g_ui_factories_initialized = false; - -// The URL scheme currently used. -static const char kNativeUIContentsScheme[] = "chrome-nativeui"; - -// Unique page id generator. -static int g_next_page_id = 0; - -// The x-position of the title. -static const int kDestinationTitleOffset = 38; - -// The x-position of the search field. -static const int kDestinationSearchOffset = 128; - -// The width of the search field. -static const int kDestinationSearchWidth = 360; - -// Padding between columns -static const int kDestinationSmallerMargin = 8; - -// The background color. -static const SkColor kBackground = SkColorSetRGB(255, 255, 255); - -// The color of the bottom margin. -static const SkColor kBottomMarginColor = SkColorSetRGB(246, 249, 255); - -// The height of the bottom margin. -static const int kBottomMargin = 5; - -// The Chrome product logo. -static const SkBitmap* kProductLogo = NULL; - -// Padding around the product logo. -static const int kProductLogoPadding = 8; - -namespace { - -// NativeRootView -------------------------------------------------------------- - -// NativeRootView is a trivial RootView subclass that allows URL drops and -// forwards them to the NavigationController to open. - -class NativeRootView : public views::RootView { - public: - explicit NativeRootView(NativeUIContents* host) - : RootView(host), - host_(host) { } - - virtual ~NativeRootView() { } - - virtual bool CanDrop(const OSExchangeData& data) { - return data.HasURL(); - } - - virtual int OnDragUpdated(const views::DropTargetEvent& event) { - if (event.GetSourceOperations() & DragDropTypes::DRAG_COPY) - return DragDropTypes::DRAG_COPY; - if (event.GetSourceOperations() & DragDropTypes::DRAG_LINK) - return DragDropTypes::DRAG_LINK; - return DragDropTypes::DRAG_NONE; - } - - virtual int OnPerformDrop(const views::DropTargetEvent& event) { - GURL url; - std::wstring title; - if (!event.GetData().GetURLAndTitle(&url, &title) || !url.is_valid()) - return DragDropTypes::DRAG_NONE; - host_->controller()->LoadURL(url, GURL(), PageTransition::GENERATED); - return OnDragUpdated(event); - } - - private: - NativeUIContents* host_; - - DISALLOW_EVIL_CONSTRUCTORS(NativeRootView); -}; - -} // namespace - - -// Returns the end of the scheme and end of the host. This is temporary until -// bug 772411 is fixed. -static void GetSchemeAndHostEnd(const GURL& url, - size_t* scheme_end, - size_t* host_end) { - const std::string spec = url.spec(); - *scheme_end = spec.find("//"); - DCHECK(*scheme_end != std::string::npos); - - *host_end = spec.find('/', *scheme_end + 2); - if (*host_end == std::string::npos) - *host_end = spec.size(); -} - -NativeUIContents::NativeUIContents(Profile* profile) - : TabContents(TAB_CONTENTS_NATIVE_UI), - is_visible_(false), - current_ui_(NULL), - current_view_(NULL), - state_(new PageState()) { - if (!g_ui_factories_initialized) { - InitializeNativeUIFactories(); - g_ui_factories_initialized = true; - } -} - -NativeUIContents::~NativeUIContents() { - if (current_ui_) { - views::RootView* root_view = GetRootView(); - current_ui_->WillBecomeInvisible(this); - root_view->RemoveChildView(current_view_); - current_ui_ = NULL; - current_view_ = NULL; - } - - STLDeleteContainerPairSecondPointers(path_to_native_uis_.begin(), - path_to_native_uis_.end()); -} - -void NativeUIContents::CreateView() { - set_delete_on_destroy(false); - WidgetWin::Init(GetDesktopWindow(), gfx::Rect(), false); -} - -LRESULT NativeUIContents::OnCreate(LPCREATESTRUCT create_struct) { - // Set the view container initial size. - CRect tmp; - ::GetWindowRect(GetHWND(), &tmp); - tmp.right = tmp.Width(); - tmp.bottom = tmp.Height(); - tmp.left = tmp.top = 0; - - // Install the focus manager so we get notified of Tab key events. - views::FocusManager::InstallFocusSubclass(GetHWND(), NULL); - GetRootView()->set_background(new NativeUIBackground); - return 0; -} - -void NativeUIContents::OnDestroy() { - views::FocusManager::UninstallFocusSubclass(GetHWND()); -} - -void NativeUIContents::OnSize(UINT size_command, const CSize& new_size) { - Layout(); - ::RedrawWindow(GetHWND(), NULL, NULL, RDW_INVALIDATE | RDW_ALLCHILDREN); -} - -void NativeUIContents::OnWindowPosChanged(WINDOWPOS* position) { - // NOTE: this may be invoked even when the visbility didn't change, in which - // case hiding and showing are both false. - const bool hiding = (position->flags & SWP_HIDEWINDOW) == SWP_HIDEWINDOW; - const bool showing = (position->flags & SWP_SHOWWINDOW) == SWP_SHOWWINDOW; - if (hiding || showing) { - if (is_visible_ != showing) { - is_visible_ = showing; - if (current_ui_) { - if (is_visible_) - current_ui_->WillBecomeVisible(this); - else - current_ui_->WillBecomeInvisible(this); - } - } - } - ChangeSize(0, CSize(position->cx, position->cy)); - - SetMsgHandled(FALSE); -} - -void NativeUIContents::GetContainerBounds(gfx::Rect* out) const { - GetBounds(out, false); -} - -void NativeUIContents::SetPageState(PageState* page_state) { - if (!page_state) - page_state = new PageState(); - state_.reset(page_state); - NavigationController* ctrl = controller(); - if (ctrl) { - int ne_index = ctrl->GetLastCommittedEntryIndex(); - NavigationEntry* ne = ctrl->GetEntryAtIndex(ne_index); - if (ne) { - // NavigationEntry is null if we're being restored. - DCHECK(ne); - std::string rep; - state_->GetByteRepresentation(&rep); - ne->set_content_state(rep); - ctrl->NotifyEntryChanged(ne, ne_index); - } - } -} - -bool NativeUIContents::NavigateToPendingEntry(bool reload) { - views::RootView* root_view = GetRootView(); - DCHECK(root_view); - - if (current_ui_) { - current_ui_->WillBecomeInvisible(this); - root_view->RemoveChildView(current_view_); - current_ui_ = NULL; - current_view_ = NULL; - } - - NavigationEntry* pending_entry = controller()->GetPendingEntry(); - NativeUI* new_ui = GetNativeUIForURL(pending_entry->url()); - if (new_ui) { - current_ui_ = new_ui; - is_visible_ = true; - current_ui_->WillBecomeVisible(this); - current_view_ = new_ui->GetView(); - root_view->AddChildView(current_view_); - - std::string s = pending_entry->content_state(); - if (s.empty()) - state_->InitWithURL(pending_entry->url()); - else - state_->InitWithBytes(s); - - current_ui_->Navigate(*state_); - Layout(); - } - - // Commit the new load in the navigation controller. If the ID of the - // NavigationEntry we were given was -1, that means this is a new load, so - // we have to generate a new ID. - controller()->CommitPendingEntry(); - - // Populate the committed entry. - NavigationEntry* committed_entry = controller()->GetLastCommittedEntry(); - committed_entry->set_title(GetDefaultTitle()); - committed_entry->favicon().set_bitmap(GetFavIcon()); - committed_entry->favicon().set_is_valid(true); - if (new_ui) { - // Strip out the query params, they should have moved to state. - // TODO(sky): use GURL methods for replacements once bug is fixed. - size_t scheme_end, host_end; - GetSchemeAndHostEnd(committed_entry->url(), &scheme_end, &host_end); - committed_entry->set_url( - GURL(committed_entry->url().spec().substr(0, host_end))); - } - std::string content_state; - state_->GetByteRepresentation(&content_state); - committed_entry->set_content_state(content_state); - - // Broadcast the fact that we just updated all that crap. - controller()->NotifyEntryChanged( - committed_entry, - controller()->GetIndexOfEntry(committed_entry)); - return true; -} - -void NativeUIContents::Layout() { - if (current_view_) { - views::RootView* root_view = GetRootView(); - current_view_->SetBounds(0, 0, root_view->width(), - root_view->height()); - current_view_->Layout(); - } -} - -const std::wstring NativeUIContents::GetDefaultTitle() const { - if (current_ui_) - return current_ui_->GetTitle(); - else - return std::wstring(); -} - -SkBitmap NativeUIContents::GetFavIcon() const { - int icon_id; - - if (current_ui_) - icon_id = current_ui_->GetFavIconID(); - else - icon_id = IDR_DEFAULT_FAVICON; - - return *ResourceBundle::GetSharedInstance().GetBitmapNamed(icon_id); -} - -void NativeUIContents::DidBecomeSelected() { - TabContents::DidBecomeSelected(); - Layout(); -} - -void NativeUIContents::SetInitialFocus() { - if (!current_ui_ || !current_ui_->SetInitialFocus()) { - int tab_index; - Browser* browser = Browser::GetBrowserForController( - this->controller(), &tab_index); - if (browser) - browser->FocusLocationBar(); - else - TabContents::SetInitialFocus(); // Will set focus to our HWND. - } -} - -void NativeUIContents::SetIsLoading(bool is_loading, - LoadNotificationDetails* details) { - TabContents::SetIsLoading(is_loading, details); -} - -// FocusTraversable Implementation -views::View* NativeUIContents::FindNextFocusableView( - views::View* starting_view, bool reverse, - views::FocusTraversable::Direction direction, bool dont_loop, - views::FocusTraversable** focus_traversable, - views::View** focus_traversable_view) { - return GetRootView()->FindNextFocusableView( - starting_view, reverse, direction, dont_loop, - focus_traversable, focus_traversable_view); -} - -//static -std::string NativeUIContents::GetScheme() { - return kNativeUIContentsScheme; -} - -//static -void NativeUIContents::InitializeNativeUIFactories() { - RegisterNativeUIFactory(DownloadTabUI::GetURL(), - DownloadTabUI::GetNativeUIFactory()); - RegisterNativeUIFactory(HistoryTabUI::GetURL(), - HistoryTabUI::GetNativeUIFactory()); -} - -// static -std::string NativeUIContents::GetFactoryKey(const GURL& url) { - size_t scheme_end; - size_t host_end; - GetSchemeAndHostEnd(url, &scheme_end, &host_end); - return url.spec().substr(scheme_end + 2, host_end - scheme_end - 2); -} - -typedef std::map PathToFactoryMap; - -static PathToFactoryMap* g_path_to_factory = NULL; - -//static -void NativeUIContents::RegisterNativeUIFactory(const GURL& url, - NativeUIFactory* factory) { - const std::string key = GetFactoryKey(url); - - if (!g_path_to_factory) - g_path_to_factory = new PathToFactoryMap; - - PathToFactoryMap::iterator i = g_path_to_factory->find(key); - if (i != g_path_to_factory->end()) { - delete i->second; - g_path_to_factory->erase(i); - } - (*g_path_to_factory)[key] = factory; -} - -views::RootView* NativeUIContents::CreateRootView() { - return new NativeRootView(this); -} - -//static -NativeUI* NativeUIContents::InstantiateNativeUIForURL( - const GURL& url, NativeUIContents* contents) { - if (!g_path_to_factory) - return NULL; - - const std::string key = GetFactoryKey(url); - - NativeUIFactory* factory = (*g_path_to_factory)[key]; - if (factory) - return factory->CreateNativeUIForURL(url, contents); - else - return NULL; -} - -NativeUI* NativeUIContents::GetNativeUIForURL(const GURL& url) { - const std::string key = GetFactoryKey(url); - - PathToUI::iterator i = path_to_native_uis_.find(key); - if (i != path_to_native_uis_.end()) - return i->second; - - NativeUI* ui = InstantiateNativeUIForURL(url, this); - if (ui) - path_to_native_uis_[key] = ui; - return ui; -} - - -//////////////////////////////////////////////////////////////////////////////// -// -// Standard NativeUI background implementation. -// -//////////////////////////////////////////////////////////////////////////////// -NativeUIBackground::NativeUIBackground() { -} - -NativeUIBackground::~NativeUIBackground() { -} - -void NativeUIBackground::Paint(ChromeCanvas* canvas, - views::View* view) const { - static const SkColor kBackground = SkColorSetRGB(255, 255, 255); - canvas->FillRectInt(kBackground, 0, 0, view->width(), view->height()); -} - -///////////////////////////////////////////////////////////////////////////// -// -// SearchableUIBackground -// A Background subclass to be used with SearchableUIContainer objects. -// Paint() is overridden to do nothing here; the background of the bar is -// painted in SearchableUIContainer::Paint. This class is necessary -// only for native controls to be able to get query the background -// brush. - -class SearchableUIBackground : public views::Background { - public: - explicit SearchableUIBackground(SkColor native_control_color) { - SetNativeControlColor(native_control_color); - } - virtual ~SearchableUIBackground() {}; - - // Empty implementation. - // The actual painting of the bar happens in SearchableUIContainer::Paint. - virtual void Paint(ChromeCanvas* canvas, views::View* view) const { } - - private: - DISALLOW_EVIL_CONSTRUCTORS(SearchableUIBackground); -}; - -///////////////////////////////////////////////////////////////////////////// -// -// SearchableUIContainer implementation. -// -///////////////////////////////////////////////////////////////////////////// - -SearchableUIContainer::SearchableUIContainer( - SearchableUIContainer::Delegate* delegate) - : delegate_(delegate), - search_field_(NULL), - title_link_(NULL), - title_image_(NULL), - scroll_view_(NULL) { - title_link_ = new views::Link; - ResourceBundle& resource_bundle = ResourceBundle::GetSharedInstance(); - ChromeFont title_font(resource_bundle - .GetFont(ResourceBundle::WebFont).DeriveFont(2)); - title_link_->SetFont(title_font); - title_link_->SetHorizontalAlignment(views::Label::ALIGN_LEFT); - title_link_->SetController(this); - - title_image_ = new views::ImageView(); - title_image_->SetVisible(false); - - // Get the product logo - if (!kProductLogo) { - kProductLogo = resource_bundle.GetBitmapNamed(IDR_PRODUCT_LOGO); - } - - product_logo_ = new views::ImageView(); - product_logo_->SetVisible(true); - product_logo_->SetImage(*kProductLogo); - AddChildView(product_logo_); - - search_field_ = new views::TextField; - search_field_->SetFont(ResourceBundle::GetSharedInstance().GetFont( - ResourceBundle::WebFont)); - search_field_->SetController(this); - - scroll_view_ = new views::ScrollView; - scroll_view_->set_background( - views::Background::CreateSolidBackground(kBackground)); - - // Set background class so that native controls can get a color. - set_background(new SearchableUIBackground(kBackground)); - - throbber_ = new views::SmoothedThrobber(50); - - GridLayout* layout = new GridLayout(this); - // View owns the LayoutManager and will delete it along with all the columns - // we create here. - SetLayoutManager(layout); - - search_button_ = - new views::NativeButton(std::wstring()); - search_button_->SetFont(resource_bundle.GetFont(ResourceBundle::WebFont)); - search_button_->SetListener(this); - - // Set a background color for the search button. If SearchableUIContainer - // provided a background, then the search button could inherit that instead. - search_button_->set_background(new SearchableUIBackground(kBackground)); - - // For the first row (icon, title/text field, search button and throbber). - ColumnSet* column_set = layout->AddColumnSet(0); - column_set->AddPaddingColumn(0, kDestinationTitleOffset); - - // Add the icon column. - column_set->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 0, - GridLayout::USE_PREF, - kDestinationSearchOffset - kDestinationTitleOffset - - kDestinationSmallerMargin, - kDestinationSearchOffset - kDestinationTitleOffset - - kDestinationSmallerMargin); - column_set->AddPaddingColumn(0, kDestinationSmallerMargin); - - // Add the title/search field column. - column_set->AddColumn(GridLayout::FILL, GridLayout::CENTER, 0, - GridLayout::USE_PREF, kDestinationSearchWidth, - kDestinationSearchWidth); - column_set->AddPaddingColumn(0, kDestinationSmallerMargin); - - // Add the search button column. - column_set->AddColumn(GridLayout::CENTER, GridLayout::CENTER, 0, - GridLayout::USE_PREF, 0, 0); - column_set->AddPaddingColumn(0, kDestinationSmallerMargin); - - // Add the throbber column. - column_set->AddColumn(GridLayout::CENTER, GridLayout::CENTER, 0, - GridLayout::USE_PREF, 0, 0); - - // For the scroll view. - column_set = layout->AddColumnSet(1); - column_set->AddPaddingColumn(0, 1); - column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1, - GridLayout::USE_PREF, 0, 0); - - layout->AddPaddingRow(0, kDestinationSmallerMargin); - layout->StartRow(0, 0); - layout->AddView(title_image_, 1, 2); - layout->AddView(title_link_); - - layout->StartRow(0, 0); - layout->SkipColumns(1); - layout->AddView(search_field_); - layout->AddView(search_button_); - layout->AddView(throbber_); - - layout->AddPaddingRow(0, kDestinationSmallerMargin); - layout->StartRow(1, 1); - layout->AddView(scroll_view_); -} - -SearchableUIContainer::~SearchableUIContainer() { -} - -void SearchableUIContainer::SetContents(views::View* contents) { - // The column view will resize to accomodate long titles. - title_link_->SetText(delegate_->GetTitle()); - - int section_icon_id = delegate_->GetSectionIconID(); - if (section_icon_id != 0) { - title_image_->SetImage(*ResourceBundle::GetSharedInstance(). - GetBitmapNamed(section_icon_id)); - title_image_->SetVisible(true); - } - - search_button_->SetLabel(delegate_->GetSearchButtonText()); - scroll_view_->SetContents(contents); -} - -views::View* SearchableUIContainer::GetContents() { - return scroll_view_->GetContents(); -} - -void SearchableUIContainer::Layout() { - View::Layout(); - - gfx::Size search_button_size = search_button_->GetPreferredSize(); - gfx::Size product_logo_size = product_logo_->GetPreferredSize(); - - int field_width = kDestinationSearchOffset + - kDestinationSearchWidth + - kDestinationSmallerMargin + - static_cast(search_button_size.width()) + - kDestinationSmallerMargin; - - product_logo_->SetBounds(std::max(width() - kProductLogo->width() - - kProductLogoPadding, - field_width), - kProductLogoPadding, - product_logo_size.width(), - product_logo_size.height()); -} - -void SearchableUIContainer::Paint(ChromeCanvas* canvas) { - SkColor top_color(kBackground); - canvas->FillRectInt(top_color, 0, 0, - width(), scroll_view_->y()); - - canvas->FillRectInt(kBottomMarginColor, 0, scroll_view_->y() - - kBottomMargin, width(), kBottomMargin); - - canvas->FillRectInt(SkColorSetRGB(196, 196, 196), - 0, scroll_view_->y() - 1, width(), 1); -} - -views::TextField* SearchableUIContainer::GetSearchField() const { - return search_field_; -} - -views::ScrollView* SearchableUIContainer::GetScrollView() const { - return scroll_view_; -} - -void SearchableUIContainer::SetSearchEnabled(bool enabled) { - search_field_->SetReadOnly(!enabled); - search_button_->SetEnabled(enabled); -} - -void SearchableUIContainer::StartThrobber() { - throbber_->Start(); -} - -void SearchableUIContainer::StopThrobber() { - throbber_->Stop(); -} - -void SearchableUIContainer::ButtonPressed(views::NativeButton* sender) { - DoSearch(); -} - -void SearchableUIContainer::LinkActivated(views::Link *link, - int event_flags) { - if (link == title_link_) { - search_field_->SetText(std::wstring()); - DoSearch(); - } -} - -void SearchableUIContainer::HandleKeystroke(views::TextField* sender, - UINT message, - TCHAR key, - UINT repeat_count, - UINT flags) { - if (key == VK_RETURN) - DoSearch(); -} - -void SearchableUIContainer::DoSearch() { - if (delegate_) - delegate_->DoSearch(search_field_->GetText()); - - scroll_view_->ScrollToPosition(scroll_view_->vertical_scroll_bar(), 0); -} - diff --git a/chrome/browser/native_ui_contents.h b/chrome/browser/native_ui_contents.h deleted file mode 100644 index 09c9750..0000000 --- a/chrome/browser/native_ui_contents.h +++ /dev/null @@ -1,295 +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. - -#ifndef CHROME_BROWSER_NATIVE_UI_CONTENTS_H__ -#define CHROME_BROWSER_NATIVE_UI_CONTENTS_H__ - -#include "chrome/browser/page_state.h" -#include "chrome/browser/tab_contents.h" -#include "chrome/views/background.h" -#include "chrome/views/link.h" -#include "chrome/views/native_button.h" -#include "chrome/views/text_field.h" -#include "chrome/views/widget_win.h" - -namespace views { -class CheckBox; -class FocusTraversable; -class ImageView; -class ScrollView; -class Throbber; -} - -class NativeUIFactory; -class NativeUI; - -//////////////////////////////////////////////////////////////////////////////// -// -// NativeUIContents -// -// NativeUIContents is a TabContents that is used to show some pages made with -// some native user interface elements. NativeUIContents maintains a list of URL -// path mapping to specific NativeUI implementations. -// -//////////////////////////////////////////////////////////////////////////////// -class NativeUIContents : public TabContents, - public views::WidgetWin { - public: - explicit NativeUIContents(Profile* profile); - - virtual void CreateView(); - virtual HWND GetContainerHWND() const { return GetHWND(); } - virtual void GetContainerBounds(gfx::Rect* out) const; - - // Sets the page state. NativeUIContents takes ownership of the supplied - // PageState. Use a value of NULL to set the state to empty. - void SetPageState(PageState* page_state); - - // Returns the page state. This is intended for UIs that want to store page - // state. - const PageState& page_state() const { return *state_; } - - // - // TabContents implementation - // - virtual bool NavigateToPendingEntry(bool reload); - virtual const std::wstring GetDefaultTitle() const; - virtual SkBitmap GetFavIcon() const; - virtual bool ShouldDisplayURL() { return false; } - virtual bool ShouldDisplayFavIcon() { return true; } - virtual void DidBecomeSelected(); - virtual void SetInitialFocus(); - - // Sets the current loading state. This is public for NativeUIs to update. - void SetIsLoading(bool is_loading, LoadNotificationDetails* details); - - // FocusTraversable Implementation - virtual views::View* FindNextFocusableView( - views::View* starting_view, - bool reverse, - views::FocusTraversable::Direction direction, - bool dont_loop, - views::FocusTraversable** focus_traversable, - views::View** focus_traversable_view); - virtual views::RootView* GetContentsRootView() { return GetRootView(); } - - // Return the scheme used. We currently use chrome-nativeui: - static std::string GetScheme(); - - // Register a NativeUIFactory for a given path. - static void RegisterNativeUIFactory(const GURL& url, - NativeUIFactory* factory); - - protected: - // Should be deleted via CloseContents. - virtual ~NativeUIContents(); - - // Overridden to create a view that that handles drag and drop. - virtual views::RootView* CreateRootView(); - - private: - // Initialize the factories. This is called the first time a NativeUIContents - // object is created. If you add a new factory, you need to add a line in this - // method. - static void InitializeNativeUIFactories(); - - // Instantiates a native UI for the provided URL. This is done by using the - // native factories which have been registered. - static NativeUI* InstantiateNativeUIForURL(const GURL& url, - NativeUIContents* contents); - - // Returns the key to use based on the TabUI's url. - static std::string GetFactoryKey(const GURL& url); - - // Size the current UI if any. - void Layout(); - - // Return the Native UI for the provided URL. The NativeUIs are returned from - // a cache. Returns NULL if no such UI exists. - NativeUI* GetNativeUIForURL(const GURL& url); - - // Windows message handlers. - virtual LRESULT OnCreate(LPCREATESTRUCT create_struct); - virtual void OnDestroy(); - virtual void OnSize(UINT size_command, const CSize& new_size); - virtual void OnWindowPosChanged(WINDOWPOS* position); - - // Whether this contents is visible. - bool is_visible_; - - // Path to NativeUI map. We keep reusing the same UIs. - typedef std::map PathToUI; - PathToUI path_to_native_uis_; - - // The current UI. - NativeUI* current_ui_; - - // The current view for the current UI. We don't ask again just in case the - // UI implementation keeps allocating new uis. - views::View* current_view_; - - // The current page state for the native contents. - scoped_ptr state_; - - // Whether factories have been initialized. - static bool g_ui_factories_initialized; - - DISALLOW_EVIL_CONSTRUCTORS(NativeUIContents); -}; - -///////////////////////////////////////////////////////////////////////////// -// -// A native UI needs to implement the following interface to work with the -// NativeUIContents. -// -///////////////////////////////////////////////////////////////////////////// -class NativeUI { - public: - virtual ~NativeUI() {} - - // Return the title for this user interface. The title is used as a tab title. - virtual const std::wstring GetTitle() const = 0; - - // Return the favicon id for this user interface. - virtual const int GetFavIconID () const = 0; - - // Return the view that should be used to render this user interface. - virtual views::View* GetView() = 0; - - // Inform the view that it is about to become visible. - virtual void WillBecomeVisible(NativeUIContents* parent) = 0; - - // Inform the view that it is about to become invisible. - virtual void WillBecomeInvisible(NativeUIContents* parent) = 0; - - // Inform the view that it should recreate the provided state. The state - // should be updated as needed by using the current navigation entry of - // the provided tab contents. - virtual void Navigate(const PageState& state) = 0; - - // Requests the contents set the initial focus. A return value of true - // indicates the contents wants focus and requested focus. A return value of - // false indicates the contents does not want focus, and that focus should - // go to the location bar. - virtual bool SetInitialFocus() = 0; -}; - -///////////////////////////////////////////////////////////////////////////// -// -// NativeUIFactory defines the method necessary to instantiate a NativeUI -// object. Typically, each NativeUI implementation registers an object that -// can instantiate NativeUI objects given the necessary path. -// -///////////////////////////////////////////////////////////////////////////// -class NativeUIFactory { - public: - virtual ~NativeUIFactory() {} - - // Request the factory to instantiate a NativeUI object given the provided - // url. The url is a nativeui: URL which contains the path for which this - // factory was registered. - // - // See NativeUIContents::RegisterNativeUI(). - virtual NativeUI* CreateNativeUIForURL(const GURL& url, - NativeUIContents* contents) = 0; -}; - - -//////////////////////////////////////////////////////////////////////////////// -// -// A standard background for native UIs. -// -//////////////////////////////////////////////////////////////////////////////// -class NativeUIBackground : public views::Background { - public: - NativeUIBackground(); - virtual ~NativeUIBackground(); - - virtual void Paint(ChromeCanvas* canvas, views::View* view) const; - - private: - - DISALLOW_EVIL_CONSTRUCTORS(NativeUIBackground); -}; - -//////////////////////////////////////////////////////////////////////////////// -// -// A view subclass used to implement native uis that feature a search field. -// This view contains a search field and a ScrollView for the contents. It -// implements a consistent look for these UIs. -// -//////////////////////////////////////////////////////////////////////////////// -class SearchableUIContainer : public views::View, - public views::NativeButton::Listener, - public views::LinkController, - public views::TextField::Controller { - public: - // The Delegate is notified when the user clicks the search button. - class Delegate { - public: - virtual void DoSearch(const std::wstring& text) = 0; - virtual const std::wstring GetTitle() const = 0; - virtual const int GetSectionIconID() const = 0; - virtual const std::wstring GetSearchButtonText() const = 0; - }; - - // Create a new SearchableUIContainer given a delegate. - explicit SearchableUIContainer(Delegate* delegate); - - virtual ~SearchableUIContainer(); - - // Add the view as the contents of the container. - void SetContents(views::View* contents); - views::View* GetContents(); - - virtual void Layout(); - - // Overriden to paint the container. - virtual void Paint(ChromeCanvas* canvas); - - // Provide the mode access to various UI elements. - views::TextField* GetSearchField() const; - views::ScrollView* GetScrollView() const; - - // Enable/disable the search text-field/button. - void SetSearchEnabled(bool enabled); - - // Start and stop the throbber. - void StartThrobber(); - void StopThrobber(); - - private: - // Invoked when the user presses the search button. - virtual void ButtonPressed(views::NativeButton* sender); - - // TextField method, does nothing. - virtual void ContentsChanged(views::TextField* sender, - const std::wstring& new_contents) {} - - // Textfield method, if key is the return key the search is updated. - virtual void HandleKeystroke(views::TextField* sender, - UINT message, - TCHAR key, - UINT repeat_count, - UINT flags); - - // Notifies the delegate to update the search. - void DoSearch(); - - void LinkActivated(views::Link* link, int event_flags); - - Delegate* delegate_; - views::Link* title_link_; - views::ImageView* title_image_; - views::ImageView* product_logo_; - views::TextField* search_field_; - views::NativeButton* search_button_; - views::ScrollView* scroll_view_; - views::Throbber* throbber_; - - DISALLOW_EVIL_CONSTRUCTORS(SearchableUIContainer); -}; - -#endif // CHROME_BROWSER_NATIVE_UI_CONTENTS_H__ - diff --git a/chrome/browser/navigation_controller.cc b/chrome/browser/navigation_controller.cc deleted file mode 100644 index c5373aa..0000000 --- a/chrome/browser/navigation_controller.cc +++ /dev/null @@ -1,1233 +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/navigation_controller.h" - -#include "base/command_line.h" -#include "base/file_util.h" -#include "base/logging.h" -#include "base/string_util.h" -#include "chrome/browser/browser_process.h" -#include "chrome/browser/dom_ui/dom_ui_host.h" -#include "chrome/browser/navigation_entry.h" -#include "chrome/browser/profile.h" -#include "chrome/browser/repost_form_warning_dialog.h" -#include "chrome/browser/sessions/session_types.h" -#include "chrome/browser/site_instance.h" -#include "chrome/browser/tab_contents.h" -#include "chrome/browser/tab_contents_delegate.h" -#include "chrome/common/chrome_switches.h" -#include "chrome/common/navigation_types.h" -#include "chrome/common/resource_bundle.h" -#include "chrome/common/scoped_vector.h" -#include "net/base/net_util.h" -#include "webkit/glue/webkit_glue.h" - -namespace { - -// 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( - NOTIFY_NAV_LIST_PRUNED, - Source(nav_controller), - Details(&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->tab_type() == TAB_CONTENTS_WEB || - entry->tab_type() == TAB_CONTENTS_NEW_TAB_UI || - entry->tab_type() == TAB_CONTENTS_ABOUT_UI || - entry->tab_type() == TAB_CONTENTS_HTML_DIALOG || - entry->tab_type() == TAB_CONTENTS_VIEW_SOURCE)) { - 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 >* entries) { - 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_restored(true); - // 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()) - return false; - - url_canon::Replacements replacements; - replacements.ClearRef(); - return existing_url.ReplaceComponents(replacements) == - new_url.ReplaceComponents(replacements); -} - -} // namespace - -// TabContentsCollector --------------------------------------------------- - -// We never destroy a TabContents synchronously because there are some -// complex code path that cause the current TabContents to be in the call -// stack. So instead, we use a TabContentsCollector which either destroys -// the TabContents or does nothing if it has been cancelled. -class TabContentsCollector : public Task { - public: - TabContentsCollector(NavigationController* target, - TabContentsType target_type) - : target_(target), - target_type_(target_type) { - } - - void Cancel() { - target_ = NULL; - } - - virtual void Run() { - if (target_) { - // Note: this will cancel this task as a side effect so target_ is - // now null. - TabContents* tc = target_->GetTabContents(target_type_); - tc->Destroy(); - } - } - - private: - // The NavigationController we are acting on. - NavigationController* target_; - - // The TabContentsType that needs to be collected. - TabContentsType target_type_; - - DISALLOW_EVIL_CONSTRUCTORS(TabContentsCollector); -}; - -// NavigationController --------------------------------------------------- - -// static -size_t NavigationController::max_entry_count_ = 50; - -// static -bool NavigationController::check_for_repost_ = true; - -// Creates a new NavigationEntry for each TabNavigation in navigations, adding -// the NavigationEntry to entries. This is used during session restore. -static void CreateNavigationEntriesFromTabNavigations( - const std::vector& navigations, - std::vector >* entries) { - // Create a NavigationEntry for each of the navigations. - int page_id = 0; - for (std::vector::const_iterator i = - navigations.begin(); i != navigations.end(); ++i, ++page_id) { - entries->push_back( - linked_ptr(i->ToNavigationEntry(page_id))); - } -} - -NavigationController::NavigationController(TabContents* contents, - Profile* profile) - : profile_(profile), - pending_entry_(NULL), - last_committed_entry_index_(-1), - pending_entry_index_(-1), - transient_entry_index_(-1), - active_contents_(contents), - max_restored_page_id_(-1), - ssl_manager_(this, NULL), - needs_reload_(false), - load_pending_entry_when_active_(false) { - if (contents) - RegisterTabContents(contents); - DCHECK(profile_); -} - -NavigationController::NavigationController( - Profile* profile, - const std::vector& navigations, - int selected_navigation) - : profile_(profile), - pending_entry_(NULL), - last_committed_entry_index_(-1), - pending_entry_index_(-1), - transient_entry_index_(-1), - active_contents_(NULL), - max_restored_page_id_(-1), - ssl_manager_(this, NULL), - needs_reload_(true), - load_pending_entry_when_active_(false) { - DCHECK(profile_); - DCHECK(selected_navigation >= 0 && - selected_navigation < static_cast(navigations.size())); - - // Populate entries_ from the supplied TabNavigations. - CreateNavigationEntriesFromTabNavigations(navigations, &entries_); - - // And finish the restore. - FinishRestore(selected_navigation); -} - -NavigationController::~NavigationController() { - DCHECK(tab_contents_map_.empty()); - DCHECK(tab_contents_collector_map_.empty()); - - DiscardNonCommittedEntriesInternal(); - - NotificationService::current()->Notify(NOTIFY_TAB_CLOSED, - Source(this), - NotificationService::NoDetails()); -} - -TabContents* NavigationController::GetTabContents(TabContentsType t) { - // Make sure the TabContents is no longer scheduled for collection. - CancelTabContentsCollection(t); - return tab_contents_map_[t]; -} - -void NavigationController::Reload(bool check_for_repost) { - // Reloading a transient entry does nothing. - if (transient_entry_index_ != -1) - return; - - DiscardNonCommittedEntriesInternal(); - int current_index = GetCurrentEntryIndex(); - if (check_for_repost_ && check_for_repost && current_index != -1 && - 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, RepostFormWarningDialog calls us - // back with ReloadDontCheckForRepost. - active_contents_->Activate(); - RepostFormWarningDialog::RunRepostFormWarningDialog(this); - } else { - // Base the navigation on where we are now... - 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; - - DiscardNonCommittedEntriesInternal(); - - pending_entry_index_ = current_index; - entries_[pending_entry_index_]->set_transition_type(PageTransition::RELOAD); - NavigateToPendingEntry(true); - } -} - -NavigationEntry* NavigationController::GetEntryWithPageID( - TabContentsType type, SiteInstance* instance, int32 page_id) const { - int index = GetEntryIndexWithPageID(type, instance, page_id); - return (index != -1) ? entries_[index].get() : NULL; -} - -void NavigationController::LoadEntry(NavigationEntry* entry) { - // 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( - NOTIFY_NAV_ENTRY_PENDING, - Source(this), - NotificationService::NoDetails()); - NavigateToPendingEntry(false); -} - -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(); -} - -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 >= GetEntryCount()) - 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(entries_.size()) - 1); -} - -void NavigationController::GoBack() { - if (!CanGoBack()) { - NOTREACHED(); - return; - } - - // Base the navigation on where we are now... - int current_index = GetCurrentEntryIndex(); - - DiscardNonCommittedEntries(); - - pending_entry_index_ = current_index - 1; - NavigateToPendingEntry(false); -} - -void NavigationController::GoForward() { - if (!CanGoForward()) { - NOTREACHED(); - return; - } - - 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_++; - - NavigateToPendingEntry(false); -} - -void NavigationController::GoToIndex(int index) { - if (index < 0 || index >= static_cast(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--; - } - } - - DiscardNonCommittedEntries(); - - pending_entry_index_ = index; - NavigateToPendingEntry(false); -} - -void NavigationController::GoToOffset(int offset) { - int index = (transient_entry_index_ != -1) ? - transient_entry_index_ + offset : - last_committed_entry_index_ + offset; - if (index < 0 || index >= GetEntryCount()) - return; - - GoToIndex(index); -} - -void NavigationController::RemoveEntryAtIndex(int index, - const GURL& default_url) { - int size = static_cast(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(false); - } 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::Destroy() { - // Close all tab contents owned by this controller. We make a list on the - // stack because they are removed from the map as they are Destroyed - // (invalidating the iterators), which may or may not occur synchronously. - // We also keep track of any NULL entries in the map so that we can clean - // them out. - std::list tabs_to_destroy; - std::list tab_types_to_erase; - for (TabContentsMap::iterator i = tab_contents_map_.begin(); - i != tab_contents_map_.end(); ++i) { - if (i->second) - tabs_to_destroy.push_back(i->second); - else - tab_types_to_erase.push_back(i->first); - } - - // Clean out all NULL entries in the map so that we know empty map means all - // tabs destroyed. This is needed since TabContentsWasDestroyed() won't get - // called for types that are in our map with a NULL contents. (We don't do - // this by iterating over TAB_CONTENTS_NUM_TYPES because some tests create - // additional types.) - for (std::list::iterator i = tab_types_to_erase.begin(); - i != tab_types_to_erase.end(); ++i) { - TabContentsMap::iterator map_iterator = tab_contents_map_.find(*i); - if (map_iterator != tab_contents_map_.end()) { - DCHECK(!map_iterator->second); - tab_contents_map_.erase(map_iterator); - } - } - - // Cancel all the TabContentsCollectors. - for (TabContentsCollectorMap::iterator i = - tab_contents_collector_map_.begin(); - i != tab_contents_collector_map_.end(); ++i) { - DCHECK(i->second); - i->second->Cancel(); - } - tab_contents_collector_map_.clear(); - - - // Finally destroy all the tab contents. - for (std::list::iterator i = tabs_to_destroy.begin(); - i != tabs_to_destroy.end(); ++i) { - (*i)->Destroy(); - } - // We are deleted at this point. -} - -void NavigationController::TabContentsWasDestroyed(TabContentsType type) { - TabContentsMap::iterator i = tab_contents_map_.find(type); - DCHECK(i != tab_contents_map_.end()); - tab_contents_map_.erase(i); - - // Make sure we cancel any collector for that TabContents. - CancelTabContentsCollection(type); - - // If that was the last tab to be destroyed, delete ourselves. - if (tab_contents_map_.empty()) - delete this; -} - -NavigationEntry* NavigationController::CreateNavigationEntry( - const GURL& url, const GURL& referrer, PageTransition::Type transition) { - GURL real_url = url; - TabContentsType type; - - // If the active contents supports |url|, use it. - // Note: in both cases, we give TabContents a chance to rewrite the URL. - TabContents* active = active_contents(); - if (active && active->SupportsURL(&real_url)) - type = active->type(); - else - type = TabContents::TypeForURL(&real_url); - - NavigationEntry* entry = new NavigationEntry(type, NULL, -1, real_url, - referrer, - std::wstring(), transition); - entry->set_display_url(url); - entry->set_user_typed_url(url); - if (url.SchemeIsFile()) { - entry->set_title(file_util::GetFilenameFromPath(UTF8ToWide(url.host() + - url.path()))); - } - return entry; -} - -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(entry)); - transient_entry_index_ = index; - active_contents_->NotifyNavigationStateChanged( - TabContents::INVALIDATE_EVERYTHING); -} - -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); - - LoadEntry(entry); -} - -void NavigationController::LoadURLLazily(const GURL& url, - const GURL& referrer, - PageTransition::Type type, - const std::wstring& title, - SkBitmap* icon) { - NavigationEntry* entry = CreateNavigationEntry(url, referrer, type); - entry->set_title(title); - if (icon) - entry->favicon().set_bitmap(*icon); - - DiscardNonCommittedEntriesInternal(); - pending_entry_ = entry; - load_pending_entry_when_active_ = true; -} - -bool NavigationController::LoadingURLLazily() { - return load_pending_entry_when_active_; -} - -const std::wstring& NavigationController::GetLazyTitle() const { - if (pending_entry_) - return pending_entry_->GetTitleForDisplay(); - else - return EmptyWString(); -} - -const SkBitmap& NavigationController::GetLazyFavIcon() const { - if (pending_entry_) { - return pending_entry_->favicon().bitmap(); - } else { - ResourceBundle &rb = ResourceBundle::GetSharedInstance(); - return *rb.GetBitmapNamed(IDR_DEFAULT_FAVICON); - } -} - -bool NavigationController::RendererDidNavigate( - const ViewHostMsg_FrameNavigate_Params& params, - LoadCommittedDetails* details) { - // Save the previous state before we clobber it. - if (GetLastCommittedEntry()) { - details->previous_url = GetLastCommittedEntry()->url(); - details->previous_entry_index = GetLastCommittedEntryIndex(); - } 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(active_contents_->GetSiteInstance()); - - // 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); - break; - case NavigationType::EXISTING_PAGE: - RendererDidNavigateToExistingPage(params); - break; - case NavigationType::SAME_PAGE: - RendererDidNavigateToSamePage(params); - break; - case NavigationType::IN_PAGE: - RendererDidNavigateInPage(params); - 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) && - !GetPendingEntry()) || - params.gesture == NavigationGestureAuto; - - // Now prep the rest of the details for the notification and broadcast. - details->entry = GetActiveEntry(); - details->is_in_page = IsURLInPageNavigation(params.url); - details->is_main_frame = PageTransition::IsMainFrame(params.transition); - details->serialized_security_info = params.security_info; - details->is_content_filtered = params.is_content_filtered; - NotifyNavigationEntryCommitted(details); - - // It is now a safe time to schedule collection for any tab contents of a - // different type, because a navigation is necessary to get back to them. - ScheduleTabContentsCollectionForInactiveTabs(); - return true; -} - -NavigationType::Type NavigationController::ClassifyNavigation( - const ViewHostMsg_FrameNavigate_Params& params) const { - // If a page makes a popup navigated to about blank, and then writes stuff - // like a subframe navigated to a real site, we'll get a notification with an - // invalid page ID. There's nothing we can do with these, so just ignore them. - if (params.page_id == -1) { - DCHECK(!GetActiveEntry()) << "Got an invalid page ID but we seem to be " - " navigated to a valid page. This should be impossible."; - return NavigationType::NAV_IGNORE; - } - - if (params.page_id > active_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( - active_contents_->type(), - active_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 (pending_entry_ && - pending_entry_->url() == params.url && - existing_entry != pending_entry_ && - pending_entry_->page_id() == -1 && - pending_entry_->url() == existing_entry->url()) { - // 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; - } - - 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; - } - - // 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; -} - -void NavigationController::RendererDidNavigateToNewPage( - const ViewHostMsg_FrameNavigate_Params& params) { - 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(NavigationEntry::NORMAL_PAGE); - } else { - new_entry = new NavigationEntry(active_contents_->type()); - } - - new_entry->set_url(params.url); - new_entry->set_page_id(params.page_id); - new_entry->set_transition_type(params.transition); - new_entry->set_site_instance(active_contents_->GetSiteInstance()); - new_entry->set_has_post_data(params.is_post); - - InsertEntry(new_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( - active_contents_->type(), - active_contents_->GetSiteInstance(), - params.page_id); - DCHECK(entry_index >= 0 && - entry_index < static_cast(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); - DCHECK(entry->site_instance() == NULL || - entry->site_instance() == active_contents_->GetSiteInstance()); - entry->set_site_instance(active_contents_->GetSiteInstance()); - - // 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(); - - last_committed_entry_index_ = entry_index; -} - -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( - active_contents_->type(), - active_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()); - - DiscardNonCommittedEntries(); -} - -void NavigationController::RendererDidNavigateInPage( - const ViewHostMsg_FrameNavigate_Params& params) { - 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( - active_contents_->type(), - active_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); - new_entry->set_url(params.url); - InsertEntry(new_entry); -} - -void NavigationController::RendererDidNavigateNewSubframe( - const ViewHostMsg_FrameNavigate_Params& params) { - // 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); - InsertEntry(new_entry); -} - -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( - active_contents_->type(), - active_contents_->GetSiteInstance(), - params.page_id); - if (entry_index < 0 || - entry_index >= static_cast(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; -} - -void NavigationController::CommitPendingEntry() { - DiscardTransientEntry(); - - if (!GetPendingEntry()) - 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 = GetLastCommittedEntryIndex(); - } 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 InsertEntry 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 WebContents, the IDs are generated by the - // renderer, so we can't do this. - details.type = NavigationType::NEW_PAGE; - pending_entry_->set_page_id(active_contents_->GetMaxPageID() + 1); - active_contents_->UpdateMaxPageID(pending_entry_->page_id()); - InsertEntry(new NavigationEntry(*pending_entry_)); - } - - // 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); -} - -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(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::DiscardNonCommittedEntries() { - bool transient = transient_entry_index_ != -1; - DiscardNonCommittedEntriesInternal(); - - // Synchronize the active_contents_ to the last committed entry. - NavigationEntry* last_entry = GetLastCommittedEntry(); - if (last_entry && last_entry->tab_type() != active_contents_->type()) { - TabContents* from_contents = active_contents_; - from_contents->set_is_active(false); - - // Switch back to the previous tab contents. - active_contents_ = GetTabContents(last_entry->tab_type()); - DCHECK(active_contents_); - - active_contents_->set_is_active(true); - - // If we are transitioning from two types of WebContents, we need to migrate - // the download shelf if it is visible. The download shelf may have been - // created before the error that caused us to discard the entry. - WebContents::MigrateShelfView(from_contents, active_contents_); - - if (from_contents->delegate()) { - from_contents->delegate()->ReplaceContents(from_contents, - active_contents_); - } - - // The entry we just discarded needed a different TabContents type. We no - // longer need it but we can't destroy it just yet because the TabContents - // is very likely involved in the current stack. - DCHECK(from_contents != active_contents_); - ScheduleTabContentsCollection(from_contents->type()); - } - - // If there was a transient entry, invalidate everything so the new active - // entry state is shown. - if (transient) { - active_contents_->NotifyNavigationStateChanged( - TabContents::INVALIDATE_EVERYTHING); - } -} - -void NavigationController::InsertEntry(NavigationEntry* entry) { - 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(entries_.size()); - - // Prune any entries which are in front of the current entry. - if (current_size > 0) { - int num_pruned = 0; - while (last_committed_entry_index_ < (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(entry)); - last_committed_entry_index_ = static_cast(entries_.size()) - 1; - - // This is a new page ID, so we need everybody to know about it. - active_contents_->UpdateMaxPageID(entry->page_id()); -} - -void NavigationController::SetWindowID(const SessionID& id) { - window_id_ = id; - NotificationService::current()->Notify(NOTIFY_TAB_PARENTED, - Source(this), - NotificationService::NoDetails()); -} - -void NavigationController::NavigateToPendingEntry(bool reload) { - TabContents* from_contents = active_contents_; - - // For session history navigations only the pending_entry_index_ is set. - if (!pending_entry_) { - DCHECK(pending_entry_index_ != -1); - pending_entry_ = entries_[pending_entry_index_].get(); - } - - // Reset the security states as any SSL error may have been resolved since we - // last visited that page. - pending_entry_->ssl() = NavigationEntry::SSLStatus(); - - if (from_contents && from_contents->type() != pending_entry_->tab_type()) - from_contents->set_is_active(false); - - TabContents* contents = GetTabContentsCreateIfNecessary(*pending_entry_); - - contents->set_is_active(true); - active_contents_ = contents; - - if (from_contents && from_contents != contents) { - if (from_contents->delegate()) - from_contents->delegate()->ReplaceContents(from_contents, contents); - - if (from_contents->type() != contents->type()) { - // The entry we just discarded needed a different TabContents type. We no - // longer need it but we can't destroy it just yet because the TabContents - // is very likely involved in the current stack. - ScheduleTabContentsCollection(from_contents->type()); - } - } - - NavigationEntry temp_entry(*pending_entry_); - if (!contents->NavigateToPendingEntry(reload)) - DiscardNonCommittedEntries(); -} - -void NavigationController::NotifyNavigationEntryCommitted( - LoadCommittedDetails* 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. - ssl_manager_.NavigationStateChanged(); - active_contents_->NotifyNavigationStateChanged( - TabContents::INVALIDATE_EVERYTHING); - - details->entry = GetActiveEntry(); - NotificationService::current()->Notify( - NOTIFY_NAV_ENTRY_COMMITTED, - Source(this), - Details(details)); -} - -TabContents* NavigationController::GetTabContentsCreateIfNecessary( - const NavigationEntry& entry) { - TabContents* contents = GetTabContents(entry.tab_type()); - if (!contents) { - contents = TabContents::CreateWithType(entry.tab_type(), profile_, - entry.site_instance()); - if (!contents->AsWebContents()) { - // Update the max page id, otherwise the newly created TabContents may - // have reset its max page id resulting in all new navigations. We only - // do this for non-WebContents as WebContents takes care of this via its - // SiteInstance. If this creation is the result of a restore, WebContents - // handles invoking ReservePageIDRange to make sure the renderer's - // max_page_id is updated to reflect the restored range of page ids. - int32 max_page_id = contents->GetMaxPageID(); - for (size_t i = 0; i < entries_.size(); ++i) { - if (entries_[i]->tab_type() == entry.tab_type()) - max_page_id = std::max(max_page_id, entries_[i]->page_id()); - } - contents->UpdateMaxPageID(max_page_id); - } - RegisterTabContents(contents); - } - - // We should not be trying to collect this tab contents. - DCHECK(tab_contents_collector_map_.find(contents->type()) == - tab_contents_collector_map_.end()); - - return contents; -} - -void NavigationController::RegisterTabContents(TabContents* some_contents) { - DCHECK(some_contents); - TabContentsType t = some_contents->type(); - TabContents* tc; - if ((tc = tab_contents_map_[t]) != some_contents) { - if (tc) { - NOTREACHED() << "Should not happen. Multiple contents for one type"; - } else { - tab_contents_map_[t] = some_contents; - some_contents->set_controller(this); - } - } - if (some_contents->AsDOMUIHost()) - some_contents->AsDOMUIHost()->AttachMessageHandlers(); -} - -// static -void NavigationController::DisablePromptOnRepost() { - check_for_repost_ = false; -} - -void NavigationController::SetActive(bool is_active) { - if (is_active) { - if (needs_reload_) { - LoadIfNecessary(); - } else if (load_pending_entry_when_active_) { - NavigateToPendingEntry(false); - load_pending_entry_when_active_ = false; - } - } -} - -void NavigationController::LoadIfNecessary() { - if (!needs_reload_) - return; - - needs_reload_ = false; - // 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(false); -} - -void NavigationController::NotifyEntryChanged(const NavigationEntry* entry, - int index) { - EntryChangedDetails det; - det.changed_entry = entry; - det.index = index; - NotificationService::current()->Notify(NOTIFY_NAV_ENTRY_CHANGED, - Source(this), - Details(&det)); -} - -NavigationController* NavigationController::Clone() { - NavigationController* nc = new NavigationController(NULL, profile_); - - if (GetEntryCount() == 0) - return nc; - - nc->needs_reload_ = true; - - nc->entries_.reserve(entries_.size()); - for (int i = 0, c = GetEntryCount(); i < c; ++i) { - nc->entries_.push_back(linked_ptr( - new NavigationEntry(*GetEntryAtIndex(i)))); - } - - nc->FinishRestore(last_committed_entry_index_); - - return nc; -} - -void NavigationController::ScheduleTabContentsCollectionForInactiveTabs() { - int index = GetCurrentEntryIndex(); - if (index < 0 || GetPendingEntryIndex() != -1) - return; - - TabContentsType active_type = GetEntryAtIndex(index)->tab_type(); - for (TabContentsMap::iterator i = tab_contents_map_.begin(); - i != tab_contents_map_.end(); ++i) { - if (i->first != active_type) - ScheduleTabContentsCollection(i->first); - } -} - -void NavigationController::ScheduleTabContentsCollection(TabContentsType t) { - TabContentsCollectorMap::const_iterator i = - tab_contents_collector_map_.find(t); - - // The tab contents is already scheduled for collection. - if (i != tab_contents_collector_map_.end()) - return; - - // If we currently don't have a TabContents for t, skip. - if (tab_contents_map_.find(t) == tab_contents_map_.end()) - return; - - // Create a collector and schedule it. - TabContentsCollector* tcc = new TabContentsCollector(this, t); - tab_contents_collector_map_[t] = tcc; - MessageLoop::current()->PostTask(FROM_HERE, tcc); -} - -void NavigationController::CancelTabContentsCollection(TabContentsType t) { - TabContentsCollectorMap::iterator i = tab_contents_collector_map_.find(t); - - if (i != tab_contents_collector_map_.end()) { - DCHECK(i->second); - i->second->Cancel(); - tab_contents_collector_map_.erase(i); - } -} - -void NavigationController::FinishRestore(int selected_index) { - DCHECK(selected_index >= 0 && selected_index < GetEntryCount()); - ConfigureEntriesForRestore(&entries_); - - set_max_restored_page_id(GetEntryCount()); - - last_committed_entry_index_ = selected_index; - - // Callers assume we have an active_contents after restoring, so set it now. - active_contents_ = GetTabContentsCreateIfNecessary(*entries_[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_ ); - transient_entry_index_ = -1; -} - -int NavigationController::GetEntryIndexWithPageID( - TabContentsType type, SiteInstance* instance, int32 page_id) const { - for (int i = static_cast(entries_.size()) - 1; i >= 0; --i) { - if ((entries_[i]->tab_type() == type) && - (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(); -} diff --git a/chrome/browser/navigation_controller.h b/chrome/browser/navigation_controller.h deleted file mode 100644 index ce5a20f..0000000 --- a/chrome/browser/navigation_controller.h +++ /dev/null @@ -1,550 +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. - -#ifndef CHROME_BROWSER_NAVIGATION_CONTROLLER_H_ -#define CHROME_BROWSER_NAVIGATION_CONTROLLER_H_ - -#include - -#include "base/linked_ptr.h" -#include "base/ref_counted.h" -#include "chrome/browser/sessions/session_id.h" -#include "chrome/browser/site_instance.h" -#include "chrome/browser/ssl_manager.h" -#include "chrome/browser/tab_contents_type.h" -#include "chrome/common/navigation_types.h" - -class GURL; -class Profile; -class TabContents; -class WebContents; -class TabContentsCollector; -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), - is_auto(false), - is_in_page(false), - is_main_frame(true) { - } - - // 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 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; - } - }; - - // 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; - }; - - // --------------------------------------------------------------------------- - - NavigationController(TabContents* initial_contents, Profile* profile); - - // Creates a NavigationController from the specified history. Processing - // for this is asynchronous and handled via the RestoreHelper (in - // navigation_controller.cc). - NavigationController( - Profile* profile, - const std::vector& navigations, - int selected_navigation); - ~NavigationController(); - - // Begin the destruction sequence for this NavigationController and all its - // registered tabs. The sequence is as follows: - // 1. All tabs are asked to Destroy themselves. - // 2. When each tab is finished Destroying, it will notify the controller. - // 3. Once all tabs are Destroyed, the NavigationController deletes itself. - // This ensures that all the TabContents outlive the NavigationController. - void Destroy(); - - // Clone the receiving navigation controller. Only the active tab contents is - // duplicated. - NavigationController* Clone(); - - // Returns the profile for this controller. It can never be NULL. - Profile* profile() const { - return profile_; - } - - // 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 the index of the last committed entry. - int GetLastCommittedEntryIndex() 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 GetEntryCount() const { - return static_cast(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 type, instance, and - // page_id, or -1 if not found. Use a NULL instance if the type is not - // TAB_CONTENTS_WEB. - int GetEntryIndexWithPageID(TabContentsType type, - SiteInstance* instance, - int32 page_id) const; - - // Return the entry with the corresponding type, instance, and page_id, or - // NULL if not found. Use a NULL instance if the type is not - // TAB_CONTENTS_WEB. - NavigationEntry* GetEntryWithPageID(TabContentsType type, - 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. Calling this may cause - // the active tab contents to switch if the current entry corresponds to a - // different tab contents type. - void DiscardNonCommittedEntries(); - - // Returns the pending entry corresponding to the navigation that is - // currently in progress, or null if there is none. - NavigationEntry* GetPendingEntry() 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 GetPendingEntryIndex() 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); - - // Load the specified URL the next time it becomes active. - void LoadURLLazily(const GURL& url, const GURL& referrer, - PageTransition::Type type, const std::wstring& title, - SkBitmap* icon); - - // 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); - - // 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 --------------------------------------------------------------- - - // Notifies the controller that a TabContents that it owns has been destroyed. - // This is part of the NavigationController's Destroy sequence. - void TabContentsWasDestroyed(TabContentsType type); - - // Returns the TabContents cached on this controller for the given type or - // NULL if there is none. - TabContents* GetTabContents(TabContentsType type); - - // Returns the currently-active TabContents associated with this controller. - // You should use GetActiveEntry instead of this in most cases. - TabContents* active_contents() const { - return active_contents_; - } - - // For use by TabContents ---------------------------------------------------- - - // Handles updating the navigation state after the renderer has navigated. - // This is used by the WebContents. 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. - bool RendererDidNavigate(const ViewHostMsg_FrameNavigate_Params& params, - 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; - - // Random data --------------------------------------------------------------- - - // Returns true if this NavigationController is is configured to load a URL - // lazily. If true, use GetLazyTitle() and GetLazyFavIcon() to discover the - // titles and favicons. Since no request was made, this is the only info - // we have about this page. This feature is used by web application clusters. - bool LoadingURLLazily(); - const std::wstring& GetLazyTitle() const; - const SkBitmap& GetLazyFavIcon() const; - - // 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_; } - - // Returns the largest restored page ID seen in this navigation controller, - // if it was restored from a previous session. (-1 otherwise) - int max_restored_page_id() const { return max_restored_page_id_; } - - // 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. - static void set_max_entry_count(size_t max_entry_count) { - max_entry_count_ = max_entry_count; - } - static size_t max_entry_count() { return max_entry_count_; } - - 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. - void RendererDidNavigateToNewPage( - const ViewHostMsg_FrameNavigate_Params& params); - void RendererDidNavigateToExistingPage( - const ViewHostMsg_FrameNavigate_Params& params); - void RendererDidNavigateToSamePage( - const ViewHostMsg_FrameNavigate_Params& params); - void RendererDidNavigateInPage( - const ViewHostMsg_FrameNavigate_Params& params); - void RendererDidNavigateNewSubframe( - const ViewHostMsg_FrameNavigate_Params& params); - bool RendererDidNavigateAutoSubframe( - const ViewHostMsg_FrameNavigate_Params& params); - - // Actually issues the navigation held in pending_entry. - void NavigateToPendingEntry(bool reload); - - // Allows the derived class to issue notifications that a load has been - // committed. This will fill in the active entry to the details structure. - void NotifyNavigationEntryCommitted(LoadCommittedDetails* details); - - // Returns the TabContents for the |entry|'s type. If the TabContents - // doesn't yet exist, it is created. If a new TabContents is created, its - // parent is |parent|. Becomes part of |entry|'s SiteInstance. - TabContents* GetTabContentsCreateIfNecessary(const NavigationEntry& entry); - - // Register the provided tab contents. This tab contents will be owned - // and deleted by this navigation controller - void RegisterTabContents(TabContents* some_contents); - - // Sets the max restored page ID this NavigationController has seen, if it - // was restored from a previous session. - void set_max_restored_page_id(int max_id) { max_restored_page_id_ = max_id; } - - NavigationEntry* CreateNavigationEntry(const GURL& url, const GURL& referrer, - PageTransition::Type transition); - - // Invokes ScheduleTabContentsCollection for all TabContents but the active - // one. - void ScheduleTabContentsCollectionForInactiveTabs(); - - // Schedule the TabContents currently allocated for |tc| for collection. - // The TabContents will be destroyed later from a different event. - void ScheduleTabContentsCollection(TabContentsType t); - - // Cancel the collection of the TabContents allocated for |tc|. This method - // is used when we keep using a TabContents because a provisional load failed. - void CancelTabContentsCollection(TabContentsType t); - - // 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. - void FinishRestore(int selected_index); - - // Inserts an entry after the current position, removing all entries after it. - // The new entry will become the active one. - void InsertEntry(NavigationEntry* entry); - - // Discards the pending and transient entries without updating - // active_contents_. - void DiscardNonCommittedEntriesInternal(); - - // Discards the transient entry without updating active_contents_. - void DiscardTransientEntry(); - - // --------------------------------------------------------------------------- - - // The user profile associated with this controller - Profile* profile_; - - // List of NavigationEntry for this tab - typedef std::vector > 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 poiting to an entry - // after the transient entry will become invalid if you navigate forward. - int transient_entry_index_; - - // Tab contents. One entry per type used. The tab controller owns - // every tab contents used. - typedef std::map TabContentsMap; - TabContentsMap tab_contents_map_; - - // A map of TabContentsType -> TabContentsCollector containing all the - // pending collectors. - typedef base::hash_map - TabContentsCollectorMap; - TabContentsCollectorMap tab_contents_collector_map_; - - // The tab contents that is currently active. - TabContents* active_contents_; - - // The max restored page ID in this controller, if it was restored. We must - // store this so that WebContents can tell any renderer in charge of one of - // the restored entries to update its max page ID. - int max_restored_page_id_; - - // Manages the SSL security UI - SSLManager ssl_manager_; - - // Whether we need to be reloaded when made active. - bool needs_reload_; - - // If true, the pending entry is lazy and should be loaded as soon as this - // controller becomes active. - bool load_pending_entry_when_active_; - - // 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. - const SessionID session_id_; - - // Unique identifier of the window we're in. Used by session restore. - SessionID window_id_; - - // 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_; - - DISALLOW_COPY_AND_ASSIGN(NavigationController); -}; - -#endif // CHROME_BROWSER_NAVIGATION_CONTROLLER_H_ diff --git a/chrome/browser/navigation_controller_unittest.cc b/chrome/browser/navigation_controller_unittest.cc index 8ffd331..09c93e6 100644 --- a/chrome/browser/navigation_controller_unittest.cc +++ b/chrome/browser/navigation_controller_unittest.cc @@ -5,16 +5,16 @@ #include "base/file_util.h" #include "base/path_service.h" #include "base/string_util.h" -#include "chrome/browser/navigation_controller.h" -#include "chrome/browser/navigation_entry.h" #include "chrome/browser/profile_manager.h" #include "chrome/browser/history/history.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.h" -#include "chrome/browser/tab_contents_delegate.h" -#include "chrome/browser/tab_contents_factory.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/tab_contents_factory.h" #include "chrome/common/notification_registrar.h" #include "chrome/common/notification_types.h" #include "chrome/common/stl_util-inl.h" diff --git a/chrome/browser/navigation_entry.cc b/chrome/browser/navigation_entry.cc deleted file mode 100644 index ca64e28..0000000 --- a/chrome/browser/navigation_entry.cc +++ /dev/null @@ -1,64 +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/navigation_entry.h" - -#include "chrome/common/resource_bundle.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), - content_status_(NORMAL_CONTENT) { -} - -NavigationEntry::FaviconStatus::FaviconStatus() : valid_(false) { - ResourceBundle &rb = ResourceBundle::GetSharedInstance(); - bitmap_ = *rb.GetBitmapNamed(IDR_DEFAULT_FAVICON); -} - -NavigationEntry::NavigationEntry(TabContentsType type) - : unique_id_(GetUniqueID()), - tab_type_(type), - site_instance_(NULL), - page_type_(NORMAL_PAGE), - page_id_(-1), - transition_type_(PageTransition::LINK), - has_post_data_(false), - restored_(false) { -} - -NavigationEntry::NavigationEntry(TabContentsType type, - SiteInstance* instance, - int page_id, - const GURL& url, - const GURL& referrer, - const std::wstring& title, - PageTransition::Type transition_type) - : unique_id_(GetUniqueID()), - tab_type_(type), - site_instance_(instance), - page_type_(NORMAL_PAGE), - url_(url), - referrer_(referrer), - title_(title), - page_id_(page_id), - transition_type_(transition_type), - has_post_data_(false), - restored_(false) { -} - -const std::wstring& NavigationEntry::GetTitleForDisplay() { - if (title_.empty()) - return display_url_as_string_; - return title_; -} diff --git a/chrome/browser/navigation_entry.h b/chrome/browser/navigation_entry.h deleted file mode 100644 index 8fc2738..0000000 --- a/chrome/browser/navigation_entry.h +++ /dev/null @@ -1,399 +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. - -#ifndef CHROME_BROWSER_NAVIGATION_ENTRY_H_ -#define CHROME_BROWSER_NAVIGATION_ENTRY_H_ - -#include "base/basictypes.h" -#include "base/scoped_ptr.h" -#include "chrome/app/theme/theme_resources.h" -#include "chrome/browser/security_style.h" -#include "chrome/browser/site_instance.h" -#include "chrome/browser/tab_contents_type.h" -#include "chrome/common/page_transition_types.h" -#include "googleurl/src/gurl.h" -#include "skia/include/SkBitmap.h" - -//////////////////////////////////////////////////////////////////////////////// -// -// 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 { - NORMAL_CONTENT = 0, // Neither of the 2 cases below. - MIXED_CONTENT = 1 << 0, // https page containing http resources. - UNSAFE_CONTENT = 1 << 1 // https page containing broken https resources. - }; - - SSLStatus(); - - 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_; - } - - // Mixed content means that this page which is served over https contains - // http sub-resources. - void set_has_mixed_content() { - content_status_ |= MIXED_CONTENT; - } - bool has_mixed_content() const { - return (content_status_ & MIXED_CONTENT) != 0; - } - - // Unsafe content means that this page is served over https but contains - // https sub-resources with cert errors. - void set_has_unsafe_content() { - content_status_ |= UNSAFE_CONTENT; - } - bool has_unsafe_content() const { - return (content_status_ & UNSAFE_CONTENT) != 0; - } - - // Raw accessors for all the content status flags. This contains a - // combination of any of the ContentStatusFlags defined above. It is used - // by the UI 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 content_status_; - - // Copy and assignment is explicitly allowed for this class. - }; - - // The type of the page an entry corresponds to. Used by ui tests. - enum PageType { - NORMAL_PAGE = 0, - ERROR_PAGE, - INTERSTITIAL_PAGE - }; - - // 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. - }; - - // --------------------------------------------------------------------------- - - explicit NavigationEntry(TabContentsType type); - NavigationEntry(TabContentsType type, - SiteInstance* instance, - int page_id, - const GURL& url, - const GURL& referrer, - const std::wstring& 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_; - } - - // Return the TabContents type required to display this entry. Immutable - // because a tab can never change its type. - TabContentsType tab_type() const { - return tab_type_; - } - - // 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) { - site_instance_ = 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 display_url() below for showing to - // the user. - void set_url(const GURL& url) { - url_ = url; - if (display_url_.is_empty()) { - // If there is no explicit display URL, then we'll display this URL. - display_url_as_string_ = UTF8ToWide(url_.spec()); - } - } - 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 display 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. - // - // display_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_display_url(const GURL& url) { - display_url_ = (url == url_) ? GURL() : url; - display_url_as_string_ = UTF8ToWide(url.spec()); - } - bool has_display_url() const { - return !display_url_.is_empty(); - } - const GURL& display_url() const { - return display_url_.is_empty() ? url_ : display_url_; - } - - // 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 std::wstring& title) { - title_ = title; - } - const std::wstring& 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 you write a custom TabContents and provide your own state make - // sure you have the ability to modify the format in the future while being - // 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_; - } - - // 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_; - } - - // Was this entry created from session/tab restore? If so this is true and - // gets set to false once we navigate to it. - // (See NavigationController::DidNavigateToEntry). - void set_restored(bool restored) { - restored_ = restored; - } - bool restored() const { - return restored_; - } - - // Returns the title to be displayed on the tab. This could be the title of - // the page if it is available or the URL. - const std::wstring& GetTitleForDisplay(); - - 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_; - TabContentsType tab_type_; - scoped_refptr site_instance_; - PageType page_type_; - GURL url_; - GURL referrer_; - - GURL display_url_; - - // We cache a copy of the display URL as a string so we don't have to - // convert the display URL to a wide string every time we paint. - std::wstring display_url_as_string_; - - std::wstring title_; - FaviconStatus favicon_; - std::string content_state_; - int32 page_id_; - SSLStatus ssl_; - PageTransition::Type transition_type_; - GURL user_typed_url_; - bool has_post_data_; - bool restored_; - - // Copy and assignment is explicitly allowed for this class. -}; - -#endif // CHROME_BROWSER_NAVIGATION_ENTRY_H_ diff --git a/chrome/browser/network_status_view.cc b/chrome/browser/network_status_view.cc deleted file mode 100644 index 74fff7f..0000000 --- a/chrome/browser/network_status_view.cc +++ /dev/null @@ -1,320 +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/network_status_view.h" - -#include - -#include "base/string_util.h" -#include "base/thread.h" -#include "chrome/browser/browser.h" -#include "chrome/browser/browser_process.h" -#include "chrome/browser/tab_contents_delegate.h" -#include "chrome/views/root_view.h" -#include "net/url_request/url_request.h" -#include "net/url_request/url_request_job.h" - -namespace { -const wchar_t kTitleMsg[] = L"Network Status"; -const wchar_t kStartTrackingMsg[] = L"Start I/O Tracking"; -const wchar_t kStopTrackingMsg[] = L"Stop I/O Tracking"; - -const wchar_t kShowIOStatusMsg[] = L"Show Current I/O Status"; -const wchar_t kClearOutputMsg[] = L"Clear Output"; - -// Returns a string representing the URL, handling the case where the spec -// is invalid. -std::wstring StringForURL(const GURL& url) { - if (url.is_valid()) - return UTF8ToWide(url.spec()); - return UTF8ToWide(url.possibly_invalid_spec()) + L" (invalid)"; -} - -std::wstring URLForJob(URLRequestJob* job) { - URLRequest* request = job->request(); - if (request) - return StringForURL(request->url()); - return std::wstring(L"(orphaned)"); -} - -} // namespace - -NetworkStatusView::NetworkStatusView() - : StatusView(TAB_CONTENTS_NETWORK_STATUS_VIEW) { - tracker_ = new JobTracker(this); -} - -NetworkStatusView::~NetworkStatusView() { - if (monospaced_font_) - DeleteObject(monospaced_font_); - - if (is_tracking_) { - tracker_->StopTracking(); - is_tracking_ = false; - } - - tracker_->DetachView(); -} - -const std::wstring NetworkStatusView::GetDefaultTitle() { - return kTitleMsg; -} - -void NetworkStatusView::OnCreate(const CRect& rect) { - CreateButton(IDC_CONFIG_TRACKING_BUTTON, kStartTrackingMsg); - CreateButton(IDC_CURRENT_STATUS_BUTTON, kShowIOStatusMsg); - CreateButton(IDC_CLEAR, kClearOutputMsg); - - is_tracking_ = false; - - // Initialize the text box for network tracking - // Don't worry about the size, we'll resize when we get WM_SIZE - text_area_.Create(m_hWnd, const_cast(rect), NULL, - WS_CHILD | WS_HSCROLL | WS_VSCROLL | - ES_MULTILINE | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0); - - // This raises the maximum number of chars from 32K to some large maximum, - // probably 2GB. 32K is not nearly enough for our use-case. - text_area_.SendMessageW(EM_SETLIMITTEXT, 0, 0); - - // make a monospaced font for the edit control - LOGFONT lf = {0}; - lf.lfHeight = 16; - wcscpy_s(lf.lfFaceName, LF_FACESIZE, L"Courier New"); - monospaced_font_ = CreateFontIndirect(&lf); - text_area_.SetFont(monospaced_font_); -} - -void NetworkStatusView::OnSize(const CRect& rect) { - // re-layout the edit control - text_area_.MoveWindow(rect); - - // re-layout the performance view - CRect new_rect(rect); - int list_width = rect.Width(); - int list_height = static_cast(rect.Height() / 5); - int page_width = rect.Width() / 2; - int page_height = static_cast(rect.Height() * 4 / 5); -} - -void NetworkStatusView::OnConfigTrackingClicked(UINT code, int button_id, - HWND hwnd) { - if (is_tracking_) { - tracker_->StopTracking(); - is_tracking_ = false; - - SetButtonText(IDC_CONFIG_TRACKING_BUTTON, kStartTrackingMsg); - } else { - tracker_->StartTracking(); - is_tracking_ = true; - - ClearTrackingResults(); - ShowTrackingResults(); - - SetButtonText(IDC_CONFIG_TRACKING_BUTTON, kStopTrackingMsg); - } -} - -void NetworkStatusView::OnCurrentStatusClicked(UINT code, int button_id, - HWND hwnd) { - ShowTrackingResults(); - if (is_tracking_) { - tracker_->ReportStatus(); - } -} - -void NetworkStatusView::OnClearClicked(UINT code, int button_id, HWND hwnd) { - ClearTrackingResults(); -} - -void NetworkStatusView::AppendText(const std::wstring& text) { - text_area_.AppendText(text.c_str()); -} - -void NetworkStatusView::HideTrackingResults() { - text_area_.ShowWindow(SW_HIDE); -} - -void NetworkStatusView::ShowTrackingResults() { - text_area_.ShowWindow(SW_SHOW); -} - -void NetworkStatusView::ClearTrackingResults() { - text_area_.SetSelAll(); - text_area_.Clear(); -} - -//----------------------------------------------------------------------------- - -// main thread: -NetworkStatusView::JobTracker::JobTracker(NetworkStatusView* view) - : view_(view), - view_message_loop_(MessageLoop::current()) { -} - -// main thread: -void NetworkStatusView::JobTracker::InvokeOnIOThread(void (JobTracker::*m)()) { - base::Thread* thread = g_browser_process->io_thread(); - if (!thread) - return; - thread->message_loop()->PostTask(FROM_HERE, NewRunnableMethod(this, m)); -} - -// main thread: -void NetworkStatusView::JobTracker::StartTracking() { - DCHECK(MessageLoop::current() == view_message_loop_); - DCHECK(view_); - InvokeOnIOThread(&JobTracker::OnStartTracking); -} - -// main thread: -void NetworkStatusView::JobTracker::StopTracking() { - DCHECK(MessageLoop::current() == view_message_loop_); - // The tracker should not be deleted before it is removed from observer - // list. - AddRef(); - InvokeOnIOThread(&JobTracker::OnStopTracking); -} - -// main thread: -void NetworkStatusView::JobTracker::ReportStatus() { - DCHECK(MessageLoop::current() == view_message_loop_); - InvokeOnIOThread(&JobTracker::OnReportStatus); -} - -// main thread: -void NetworkStatusView::JobTracker::OnAppendText(const std::wstring& text) { - DCHECK(MessageLoop::current() == view_message_loop_); - if (view_ && view_->is_tracking_) - view_->AppendText(text); -} - -// IO thread: -void NetworkStatusView::JobTracker::AppendText(const std::wstring& text) { - DCHECK(MessageLoop::current() != view_message_loop_); - view_message_loop_->PostTask(FROM_HERE, NewRunnableMethod( - this, &JobTracker::OnAppendText, text)); -} - -// IO thread: -void NetworkStatusView::JobTracker::OnStartTracking() { - DCHECK(MessageLoop::current() != view_message_loop_); - g_url_request_job_tracker.AddObserver(this); -} - -// IO thread: -void NetworkStatusView::JobTracker::OnStopTracking() { - DCHECK(MessageLoop::current() != view_message_loop_); - g_url_request_job_tracker.RemoveObserver(this); - // Balance the AddRef() in StopTracking() called in main thread. - Release(); -} - -// IO thread: -void NetworkStatusView::JobTracker::OnReportStatus() { - DCHECK(MessageLoop::current() != view_message_loop_); - - std::wstring text(L"\r\n===== Active Job Summary =====\r\n"); - - URLRequestJobTracker::JobIterator begin_job = - g_url_request_job_tracker.begin(); - URLRequestJobTracker::JobIterator end_job = g_url_request_job_tracker.end(); - int orphaned_count = 0; - int regular_count = 0; - for (URLRequestJobTracker::JobIterator cur = begin_job; - cur != end_job; ++cur) { - URLRequestJob* job = (*cur); - URLRequest* request = job->request(); - if (!request) { - orphaned_count++; - continue; - } - - regular_count++; - - // active state - if (job->is_done()) - text.append(L" Done: "); - else - text.append(L" Active: "); - - // URL - text.append(StringForURL(request->url())); - text.append(L"\r\n"); - } - - if (regular_count == 0) - text.append(L" (No active jobs)\r\n"); - - if (orphaned_count) { - wchar_t buf[64]; - swprintf(buf, arraysize(buf), L" %d orphaned jobs\r\n", orphaned_count); - text.append(buf); - } - - text.append(L"=====\r\n\r\n"); - AppendText(text); -} - -// IO thread: -void NetworkStatusView::JobTracker::OnJobAdded(URLRequestJob* job) { - DCHECK(MessageLoop::current() != view_message_loop_); - - std::wstring text(L"+ New job : "); - text.append(URLForJob(job)); - text.append(L"\r\n"); - AppendText(text); -} - -// IO thread: -void NetworkStatusView::JobTracker::OnJobRemoved(URLRequestJob* job) { - DCHECK(MessageLoop::current() != view_message_loop_); -} - -// IO thread: -void NetworkStatusView::JobTracker::OnJobDone(URLRequestJob* job, - const URLRequestStatus& status) { - DCHECK(MessageLoop::current() != view_message_loop_); - - std::wstring text; - if (status.is_success()) { - text.assign(L"- Complete: "); - } else if (status.status() == URLRequestStatus::CANCELED) { - text.assign(L"- Canceled: "); - } else if (status.status() == URLRequestStatus::HANDLED_EXTERNALLY) { - text.assign(L"- Handled externally: "); - } else { - wchar_t buf[32]; - swprintf(buf, arraysize(buf), L"Failed with %d: ", status.os_error()); - text.assign(buf); - } - - text.append(URLForJob(job)); - text.append(L"\r\n"); - AppendText(text); -} - -// IO thread: -void NetworkStatusView::JobTracker::OnJobRedirect(URLRequestJob* job, - const GURL& location, - int status_code) { - DCHECK(MessageLoop::current() != view_message_loop_); - - std::wstring text(L"- Redirect: "); - text.append(URLForJob(job)); - text.append(L"\r\n "); - - wchar_t buf[16]; - swprintf(buf, arraysize(buf), L"(%d) to: ", status_code); - text.append(buf); - - text.append(StringForURL(location)); - text.append(L"\r\n"); - AppendText(text); -} - -void NetworkStatusView::JobTracker::OnBytesRead(URLRequestJob* job, - int byte_count) { -} - diff --git a/chrome/browser/network_status_view.h b/chrome/browser/network_status_view.h deleted file mode 100644 index 2170f73..0000000 --- a/chrome/browser/network_status_view.h +++ /dev/null @@ -1,117 +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. - -#ifndef CHROME_BROWSER_NETWORK_STATUS_VIEW_H__ -#define CHROME_BROWSER_NETWORK_STATUS_VIEW_H__ - -#include "base/basictypes.h" -#include "base/ref_counted.h" -#include "base/scoped_ptr.h" -#include "chrome/common/render_messages.h" -#include "chrome/browser/status_view.h" -#include "net/url_request/url_request_job_tracker.h" - -class MessageLoop; -class RenderProcessHost; -class NavigationPerformanceViewer; -class PageLoadView; - -class NetworkStatusView : public StatusView { - public: - // button types - enum { - IDC_CONFIG_TRACKING_BUTTON = 101, - IDC_CURRENT_STATUS_BUTTON, - IDC_CLEAR, - }; - - NetworkStatusView(); - virtual ~NetworkStatusView(); - - // TabContents overrides - virtual const std::wstring GetDefaultTitle(); - - // StatusView implementation - virtual void OnCreate(const CRect& rect); - virtual void OnSize(const CRect& rect); - - BEGIN_MSG_MAP(NetworkStatusView) - COMMAND_HANDLER_EX(IDC_CONFIG_TRACKING_BUTTON, BN_CLICKED, OnConfigTrackingClicked) - COMMAND_HANDLER_EX(IDC_CURRENT_STATUS_BUTTON, BN_CLICKED, OnCurrentStatusClicked) - COMMAND_HANDLER_EX(IDC_CLEAR, BN_CLICKED, OnClearClicked) - CHAIN_MSG_MAP(StatusView); - END_MSG_MAP() - - bool is_tracking() const { return is_tracking_; } - - private: - - // Event handlers - void OnConfigTrackingClicked(UINT code, int button_id, HWND hwnd); - void OnCurrentStatusClicked(UINT code, int button_id, HWND hwnd); - void OnClearClicked(UINT code, int button_id, HWND hwnd); - - void AppendText(const std::wstring& text); - - // Hide/Show tracking output window - void HideTrackingResults(); - void ShowTrackingResults(); - - // Clear tracking output - void ClearTrackingResults(); - - // A JobTracker is allocated to monitor network jobs running on the IO - // thread. This allows the NetworkStatusView to remain single-threaded. - class JobTracker : public URLRequestJobTracker::JobObserver, - public base::RefCountedThreadSafe { - public: - JobTracker(NetworkStatusView* view); - - // Called by the NetworkStatusView on the main application thread. - void StartTracking(); - void StopTracking(); - void ReportStatus(); - - // URLRequestJobTracker::JobObserver methods (called on the IO thread): - virtual void OnJobAdded(URLRequestJob* job); - virtual void OnJobRemoved(URLRequestJob* job); - virtual void OnJobDone(URLRequestJob* job, const URLRequestStatus& status); - virtual void OnJobRedirect(URLRequestJob* job, const GURL& location, - int status_code); - virtual void OnBytesRead(URLRequestJob* job, int byte_count); - - // The JobTracker may be deleted after NetworkStatusView is deleted. - void DetachView() { view_ = NULL; } - - private: - void InvokeOnIOThread(void (JobTracker::*method)()); - - // Called on the IO thread - void OnStartTracking(); - void OnStopTracking(); - void OnReportStatus(); - void AppendText(const std::wstring& text); - - // Called on the main thread - void OnAppendText(const std::wstring& text); - - NetworkStatusView* view_; - MessageLoop* view_message_loop_; - }; - friend class JobTracker; - - scoped_refptr tracker_; - - bool is_tracking_; - - // Textual output of network tracking - CEdit text_area_; - - HFONT monospaced_font_; - - DISALLOW_COPY_AND_ASSIGN(NetworkStatusView); -}; - -#endif // #ifndef CHROME_BROWSER_NETWORK_STATUS_VIEW_H__ - diff --git a/chrome/browser/page_navigator.h b/chrome/browser/page_navigator.h deleted file mode 100644 index 0152d39..0000000 --- a/chrome/browser/page_navigator.h +++ /dev/null @@ -1,27 +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. - -// 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_PAGE_NAVIGATOR_H__ -#define CHROME_BROWSER_PAGE_NAVIGATOR_H__ - -#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; -}; - -#endif // CHROME_BROWSER_PAGE_NAVIGATOR_H__ - diff --git a/chrome/browser/password_manager.cc b/chrome/browser/password_manager.cc index 8779209..fa19f62 100644 --- a/chrome/browser/password_manager.cc +++ b/chrome/browser/password_manager.cc @@ -7,7 +7,7 @@ #include "base/string_util.h" #include "chrome/app/theme/theme_resources.h" #include "chrome/browser/profile.h" -#include "chrome/browser/web_contents.h" +#include "chrome/browser/tab_contents/web_contents.h" #include "chrome/common/l10n_util.h" #include "chrome/common/pref_names.h" #include "chrome/common/pref_service.h" diff --git a/chrome/browser/password_manager.h b/chrome/browser/password_manager.h index a1e28eb..dd9a953 100644 --- a/chrome/browser/password_manager.h +++ b/chrome/browser/password_manager.h @@ -6,8 +6,8 @@ #define CHROME_BROWSER_PASSWORD_MANAGER_H__ #include "base/scoped_ptr.h" -#include "chrome/browser/infobar_delegate.h" #include "chrome/browser/password_form_manager.h" +#include "chrome/browser/tab_contents/infobar_delegate.h" #include "chrome/browser/views/login_view.h" #include "chrome/common/pref_member.h" #include "chrome/common/stl_util-inl.h" diff --git a/chrome/browser/plugin_installer.cc b/chrome/browser/plugin_installer.cc index 683c77a..7d06128 100644 --- a/chrome/browser/plugin_installer.cc +++ b/chrome/browser/plugin_installer.cc @@ -6,7 +6,7 @@ #include "base/string_util.h" #include "chrome/app/theme/theme_resources.h" -#include "chrome/browser/web_contents.h" +#include "chrome/browser/tab_contents/web_contents.h" #include "chrome/common/l10n_util.h" #include "chrome/common/resource_bundle.h" #include "webkit/default_plugin/default_plugin_shared.h" diff --git a/chrome/browser/plugin_installer.h b/chrome/browser/plugin_installer.h index 2ba3424..9e11178 100644 --- a/chrome/browser/plugin_installer.h +++ b/chrome/browser/plugin_installer.h @@ -5,7 +5,7 @@ #ifndef CHROME_BROWSER_PLUGIN_INSTALLER_H_ #define CHROME_BROWSER_PLUGIN_INSTALLER_H_ -#include "chrome/browser/infobar_delegate.h" +#include "chrome/browser/tab_contents/infobar_delegate.h" class WebContents; diff --git a/chrome/browser/printing/print_view_manager.cc b/chrome/browser/printing/print_view_manager.cc index 9771389..9ae2efb 100644 --- a/chrome/browser/printing/print_view_manager.cc +++ b/chrome/browser/printing/print_view_manager.cc @@ -5,13 +5,13 @@ #include "chrome/browser/printing/print_view_manager.h" #include "chrome/browser/browser_process.h" -#include "chrome/browser/navigation_entry.h" #include "chrome/browser/printing/print_job.h" #include "chrome/browser/printing/print_job_manager.h" #include "chrome/browser/printing/printed_document.h" #include "chrome/browser/printing/printer_query.h" #include "chrome/browser/render_view_host.h" -#include "chrome/browser/web_contents.h" +#include "chrome/browser/tab_contents/navigation_entry.h" +#include "chrome/browser/tab_contents/web_contents.h" #include "chrome/common/gfx/emf.h" #include "chrome/common/l10n_util.h" diff --git a/chrome/browser/profile.cc b/chrome/browser/profile.cc index b1762f0..a849bf1 100644 --- a/chrome/browser/profile.cc +++ b/chrome/browser/profile.cc @@ -20,13 +20,13 @@ #include "chrome/browser/extensions/extensions_service.h" #include "chrome/browser/extensions/user_script_master.h" #include "chrome/browser/history/history.h" -#include "chrome/browser/navigation_controller.h" #include "chrome/browser/net/chrome_url_request_context.h" #include "chrome/browser/profile_manager.h" #include "chrome/browser/render_process_host.h" #include "chrome/browser/sessions/session_service.h" #include "chrome/browser/sessions/tab_restore_service.h" #include "chrome/browser/spellchecker.h" +#include "chrome/browser/tab_contents/navigation_controller.h" #include "chrome/browser/template_url_fetcher.h" #include "chrome/browser/template_url_model.h" #include "chrome/browser/visitedlink_master.h" diff --git a/chrome/browser/profile_manager.cc b/chrome/browser/profile_manager.cc index 23ad108..fab4dd45 100644 --- a/chrome/browser/profile_manager.cc +++ b/chrome/browser/profile_manager.cc @@ -14,7 +14,7 @@ #include "chrome/browser/browser.h" #include "chrome/browser/browser_list.h" #include "chrome/browser/browser_process.h" -#include "chrome/browser/navigation_controller.h" +#include "chrome/browser/tab_contents/navigation_controller.h" #include "chrome/common/chrome_constants.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/l10n_util.h" diff --git a/chrome/browser/provisional_load_details.cc b/chrome/browser/provisional_load_details.cc deleted file mode 100644 index fcd1558..0000000 --- a/chrome/browser/provisional_load_details.cc +++ /dev/null @@ -1,25 +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/provisional_load_details.h" - -#include "chrome/browser/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) - : error_code_(net::OK), - url_(url), - is_main_frame_(is_main_frame), - is_in_page_navigation_(is_in_page_navigation), - is_content_filtered_(is_content_filtered) { - SSLManager::DeserializeSecurityInfo(security_info, - &ssl_cert_id_, - &ssl_cert_status_, - &ssl_security_bits_); -} - diff --git a/chrome/browser/provisional_load_details.h b/chrome/browser/provisional_load_details.h deleted file mode 100644 index 5cb9501..0000000 --- a/chrome/browser/provisional_load_details.h +++ /dev/null @@ -1,60 +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. - -#ifndef CHROME_BROWSER_PROVISIONAL_LOAD_DETAILS_H_ -#define CHROME_BROWSER_PROVISIONAL_LOAD_DETAILS_H_ - -#include "base/basictypes.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); - virtual ~ProvisionalLoadDetails() { } - - void set_error_code(int error_code) { error_code_ = error_code; }; - int error_code() const { return error_code_; } - - 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_; } - - bool is_content_filtered() const { return is_content_filtered_; } - - private: - int error_code_; - GURL url_; - bool is_main_frame_; - bool is_in_page_navigation_; - int ssl_cert_id_; - int ssl_cert_status_; - int ssl_security_bits_; - bool is_content_filtered_; - - DISALLOW_COPY_AND_ASSIGN(ProvisionalLoadDetails); -}; - -#endif // CHROME_BROWSER_PROVISIONAL_LOAD_DETAILS_H_ - diff --git a/chrome/browser/render_process_host.cc b/chrome/browser/render_process_host.cc index 4adaff1..a0a8f8b 100644 --- a/chrome/browser/render_process_host.cc +++ b/chrome/browser/render_process_host.cc @@ -40,7 +40,7 @@ #include "chrome/browser/sandbox_policy.h" #include "chrome/browser/spellchecker.h" #include "chrome/browser/visitedlink_master.h" -#include "chrome/browser/web_contents.h" +#include "chrome/browser/tab_contents/web_contents.h" #include "chrome/common/chrome_constants.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/chrome_switches.h" diff --git a/chrome/browser/render_view_context_menu_controller.cc b/chrome/browser/render_view_context_menu_controller.cc index 522ebe0..7a75577 100644 --- a/chrome/browser/render_view_context_menu_controller.cc +++ b/chrome/browser/render_view_context_menu_controller.cc @@ -17,12 +17,12 @@ #include "chrome/browser/spellchecker.h" #include "chrome/browser/download/download_manager.h" #include "chrome/browser/download/save_package.h" -#include "chrome/browser/navigation_controller.h" -#include "chrome/browser/navigation_entry.h" #include "chrome/browser/profile.h" #include "chrome/browser/template_url_model.h" #include "chrome/browser/views/page_info_window.h" -#include "chrome/browser/web_contents.h" +#include "chrome/browser/tab_contents/navigation_controller.h" +#include "chrome/browser/tab_contents/navigation_entry.h" +#include "chrome/browser/tab_contents/web_contents.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/clipboard_service.h" #include "chrome/common/l10n_util.h" diff --git a/chrome/browser/render_view_host.cc b/chrome/browser/render_view_host.cc index 6fa62b8..5ace177 100644 --- a/chrome/browser/render_view_host.cc +++ b/chrome/browser/render_view_host.cc @@ -11,17 +11,17 @@ #include "chrome/app/result_codes.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/cross_site_request_manager.h" -#include "chrome/browser/navigation_entry.h" +#include "chrome/browser/debugger/debugger_wrapper.h" #include "chrome/browser/profile.h" #include "chrome/browser/render_process_host.h" #include "chrome/browser/render_widget_host.h" #include "chrome/browser/render_widget_host_view.h" #include "chrome/browser/render_view_host_delegate.h" #include "chrome/browser/renderer_security_policy.h" -#include "chrome/browser/debugger/debugger_wrapper.h" -#include "chrome/browser/site_instance.h" +#include "chrome/browser/tab_contents/navigation_entry.h" +#include "chrome/browser/tab_contents/site_instance.h" +#include "chrome/browser/tab_contents/web_contents.h" #include "chrome/browser/user_metrics.h" -#include "chrome/browser/web_contents.h" #include "chrome/common/resource_bundle.h" #include "chrome/common/thumbnail_score.h" #include "net/base/net_util.h" diff --git a/chrome/browser/render_view_host_manager.cc b/chrome/browser/render_view_host_manager.cc index c5e4d00..f7edacf 100644 --- a/chrome/browser/render_view_host_manager.cc +++ b/chrome/browser/render_view_host_manager.cc @@ -6,12 +6,12 @@ #include "base/command_line.h" #include "base/logging.h" -#include "chrome/browser/navigation_controller.h" -#include "chrome/browser/navigation_entry.h" #include "chrome/browser/render_widget_host_view.h" #include "chrome/browser/render_view_host.h" #include "chrome/browser/render_view_host_delegate.h" -#include "chrome/browser/site_instance.h" +#include "chrome/browser/tab_contents/navigation_controller.h" +#include "chrome/browser/tab_contents/navigation_entry.h" +#include "chrome/browser/tab_contents/site_instance.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/notification_service.h" diff --git a/chrome/browser/renderer_host/cross_site_resource_handler.cc b/chrome/browser/renderer_host/cross_site_resource_handler.cc index d597732..91695df 100644 --- a/chrome/browser/renderer_host/cross_site_resource_handler.cc +++ b/chrome/browser/renderer_host/cross_site_resource_handler.cc @@ -5,8 +5,8 @@ #include "chrome/browser/renderer_host/cross_site_resource_handler.h" #include "chrome/browser/render_view_host.h" -#include "chrome/browser/tab_util.h" -#include "chrome/browser/web_contents.h" +#include "chrome/browser/tab_contents/tab_util.h" +#include "chrome/browser/tab_contents/web_contents.h" namespace { // Task to notify the WebContents that a cross-site response has begun, so that diff --git a/chrome/browser/renderer_host/resource_dispatcher_host.cc b/chrome/browser/renderer_host/resource_dispatcher_host.cc index c591ee6..7c74420 100644 --- a/chrome/browser/renderer_host/resource_dispatcher_host.cc +++ b/chrome/browser/renderer_host/resource_dispatcher_host.cc @@ -32,8 +32,8 @@ #include "chrome/browser/renderer_security_policy.h" #include "chrome/browser/resource_request_details.h" #include "chrome/browser/safe_browsing/safe_browsing_service.h" -#include "chrome/browser/tab_util.h" -#include "chrome/browser/web_contents.h" +#include "chrome/browser/tab_contents/tab_util.h" +#include "chrome/browser/tab_contents/web_contents.h" #include "chrome/common/notification_source.h" #include "chrome/common/notification_types.h" #include "chrome/common/render_messages.h" diff --git a/chrome/browser/repost_form_warning_dialog.cc b/chrome/browser/repost_form_warning_dialog.cc index c030265..8a88a79 100644 --- a/chrome/browser/repost_form_warning_dialog.cc +++ b/chrome/browser/repost_form_warning_dialog.cc @@ -5,7 +5,7 @@ #include "chrome/browser/repost_form_warning_dialog.h" #include "chrome/browser/browser_list.h" -#include "chrome/browser/navigation_controller.h" +#include "chrome/browser/tab_contents/navigation_controller.h" #include "chrome/common/l10n_util.h" #include "chrome/views/message_box_view.h" #include "chrome/views/window.h" diff --git a/chrome/browser/safe_browsing/safe_browsing_blocking_page.cc b/chrome/browser/safe_browsing/safe_browsing_blocking_page.cc index 265e4c7..4d34450 100644 --- a/chrome/browser/safe_browsing/safe_browsing_blocking_page.cc +++ b/chrome/browser/safe_browsing/safe_browsing_blocking_page.cc @@ -12,11 +12,11 @@ #include "chrome/browser/dom_operation_notification_details.h" #include "chrome/browser/dom_ui/new_tab_ui.h" #include "chrome/browser/google_util.h" -#include "chrome/browser/navigation_controller.h" -#include "chrome/browser/navigation_entry.h" #include "chrome/browser/safe_browsing/safe_browsing_service.h" -#include "chrome/browser/tab_util.h" -#include "chrome/browser/web_contents.h" +#include "chrome/browser/tab_contents/navigation_controller.h" +#include "chrome/browser/tab_contents/navigation_entry.h" +#include "chrome/browser/tab_contents/tab_util.h" +#include "chrome/browser/tab_contents/web_contents.h" #include "chrome/common/jstemplate_builder.h" #include "chrome/common/l10n_util.h" #include "chrome/common/resource_bundle.h" diff --git a/chrome/browser/safe_browsing/safe_browsing_blocking_page.h b/chrome/browser/safe_browsing/safe_browsing_blocking_page.h index b0fa2ea..7b94290 100644 --- a/chrome/browser/safe_browsing/safe_browsing_blocking_page.h +++ b/chrome/browser/safe_browsing/safe_browsing_blocking_page.h @@ -22,7 +22,7 @@ #define CHROME_BROWSER_SAFE_BROWSING_SAFE_BROWSING_BLOCKING_PAGE_H_ #include "base/logging.h" -#include "chrome/browser/interstitial_page.h" +#include "chrome/browser/tab_contents/interstitial_page.h" #include "chrome/browser/safe_browsing/safe_browsing_service.h" #include "googleurl/src/gurl.h" diff --git a/chrome/browser/safe_browsing/safe_browsing_service.cc b/chrome/browser/safe_browsing/safe_browsing_service.cc index d86d219..60da2b5 100644 --- a/chrome/browser/safe_browsing/safe_browsing_service.cc +++ b/chrome/browser/safe_browsing/safe_browsing_service.cc @@ -17,7 +17,7 @@ #include "chrome/browser/safe_browsing/protocol_manager.h" #include "chrome/browser/safe_browsing/safe_browsing_blocking_page.h" #include "chrome/browser/safe_browsing/safe_browsing_database.h" -#include "chrome/browser/tab_util.h" +#include "chrome/browser/tab_contents/tab_util.h" #include "chrome/common/chrome_constants.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/chrome_switches.h" diff --git a/chrome/browser/sessions/base_session_service.cc b/chrome/browser/sessions/base_session_service.cc index b26f7e0..4bb9101 100644 --- a/chrome/browser/sessions/base_session_service.cc +++ b/chrome/browser/sessions/base_session_service.cc @@ -7,11 +7,11 @@ #include "base/pickle.h" #include "base/thread.h" #include "chrome/browser/browser_process.h" -#include "chrome/browser/navigation_entry.h" #include "chrome/browser/profile.h" #include "chrome/browser/sessions/session_backend.h" #include "chrome/browser/sessions/session_types.h" -#include "chrome/browser/tab_contents.h" +#include "chrome/browser/tab_contents/navigation_entry.h" +#include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/common/stl_util-inl.h" // InternalGetCommandsRequest ------------------------------------------------- diff --git a/chrome/browser/sessions/session_restore.cc b/chrome/browser/sessions/session_restore.cc index 8ffbac9..dfb5acd 100644 --- a/chrome/browser/sessions/session_restore.cc +++ b/chrome/browser/sessions/session_restore.cc @@ -10,11 +10,11 @@ #include "chrome/browser/browser.h" #include "chrome/browser/browser_list.h" #include "chrome/browser/browser_process.h" -#include "chrome/browser/navigation_controller.h" #include "chrome/browser/profile.h" #include "chrome/browser/sessions/session_service.h" #include "chrome/browser/sessions/session_types.h" -#include "chrome/browser/tab_contents.h" +#include "chrome/browser/tab_contents/navigation_controller.h" +#include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/common/notification_registrar.h" #include "chrome/common/notification_service.h" diff --git a/chrome/browser/sessions/session_service.cc b/chrome/browser/sessions/session_service.cc index 227c6ff..4f5861e 100644 --- a/chrome/browser/sessions/session_service.cc +++ b/chrome/browser/sessions/session_service.cc @@ -14,14 +14,14 @@ #include "chrome/browser/browser_list.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/browser_window.h" -#include "chrome/browser/navigation_controller.h" -#include "chrome/browser/navigation_entry.h" #include "chrome/browser/profile.h" #include "chrome/browser/session_startup_pref.h" #include "chrome/browser/sessions/session_backend.h" #include "chrome/browser/sessions/session_restore.h" #include "chrome/browser/sessions/session_types.h" -#include "chrome/browser/tab_contents.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/common/notification_details.h" #include "chrome/common/notification_service.h" #include "chrome/common/notification_types.h" diff --git a/chrome/browser/sessions/session_service_unittest.cc b/chrome/browser/sessions/session_service_unittest.cc index 1939c7e..059f307e 100644 --- a/chrome/browser/sessions/session_service_unittest.cc +++ b/chrome/browser/sessions/session_service_unittest.cc @@ -6,11 +6,11 @@ #include "base/file_util.h" #include "base/path_service.h" -#include "chrome/browser/navigation_entry.h" #include "chrome/browser/sessions/session_backend.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_entry.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/scoped_vector.h" #include "chrome/common/stl_util-inl.h" diff --git a/chrome/browser/sessions/session_types.cc b/chrome/browser/sessions/session_types.cc index 5c17454..a43f637 100644 --- a/chrome/browser/sessions/session_types.cc +++ b/chrome/browser/sessions/session_types.cc @@ -4,7 +4,7 @@ #include "chrome/browser/sessions/session_types.h" -#include "chrome/browser/navigation_entry.h" +#include "chrome/browser/tab_contents/navigation_entry.h" // TabNavigation -------------------------------------------------------------- diff --git a/chrome/browser/sessions/tab_restore_service.cc b/chrome/browser/sessions/tab_restore_service.cc index 13da68f..a6b3968 100644 --- a/chrome/browser/sessions/tab_restore_service.cc +++ b/chrome/browser/sessions/tab_restore_service.cc @@ -8,11 +8,11 @@ #include "chrome/browser/sessions/tab_restore_service.h" #include "chrome/browser/browser_list.h" -#include "chrome/browser/navigation_controller.h" -#include "chrome/browser/navigation_entry.h" #include "chrome/browser/profile.h" #include "chrome/browser/sessions/session_backend.h" #include "chrome/browser/sessions/session_service.h" +#include "chrome/browser/tab_contents/navigation_controller.h" +#include "chrome/browser/tab_contents/navigation_entry.h" #include "chrome/common/scoped_vector.h" #include "chrome/common/stl_util-inl.h" diff --git a/chrome/browser/sessions/tab_restore_service_unittest.cc b/chrome/browser/sessions/tab_restore_service_unittest.cc index 2f7d4ba..bc5aefc 100644 --- a/chrome/browser/sessions/tab_restore_service_unittest.cc +++ b/chrome/browser/sessions/tab_restore_service_unittest.cc @@ -2,9 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/navigation_entry.h" #include "chrome/browser/sessions/session_types.h" #include "chrome/browser/sessions/tab_restore_service.h" +#include "chrome/browser/tab_contents/navigation_entry.h" #include "chrome/test/test_tab_contents.h" #include "chrome/test/testing_profile.h" #include "testing/gtest/include/gtest/gtest.h" diff --git a/chrome/browser/site_instance.cc b/chrome/browser/site_instance.cc deleted file mode 100644 index ec1eaf1..0000000 --- a/chrome/browser/site_instance.cc +++ /dev/null @@ -1,145 +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/site_instance.h" - -#include "net/base/registry_controlled_domain.h" - -SiteInstance::~SiteInstance() { - // Now that no one is referencing us, we can safely remove ourselves from - // the BrowsingInstance. Any future visits to a page from this site - // (within the same BrowsingInstance) can safely create a new SiteInstance. - if (has_site_) - browsing_instance_->UnregisterSiteInstance(this); -} - -RenderProcessHost* SiteInstance::GetProcess() { - RenderProcessHost* process = NULL; - if (process_host_id_ != -1) - process = RenderProcessHost::FromID(process_host_id_); - - // Create a new process if ours went away or was reused. - if (!process) { - // See if we should reuse an old process - if (RenderProcessHost::ShouldTryToUseExistingProcessHost()) - process = RenderProcessHost::GetExistingProcessHost( - browsing_instance_->profile()); - - // Otherwise (or if that fails), create a new one. - if (!process) - process = new RenderProcessHost(browsing_instance_->profile()); - - // Update our host ID, so all pages in this SiteInstance will use - // the correct process. - process_host_id_ = process->host_id(); - - // Make sure the process starts at the right max_page_id - process->UpdateMaxPageID(max_page_id_); - } - DCHECK(process); - - return process; -} - -void SiteInstance::SetSite(const GURL& url) { - // A SiteInstance's site should not change. - // TODO(creis): When following links or script navigations, we can currently - // render pages from other sites in this SiteInstance. This will eventually - // be fixed, but until then, we should still not set the site of a - // SiteInstance more than once. - DCHECK(!has_site_); - - // Remember that this SiteInstance has been used to load a URL, even if the - // URL is invalid. - has_site_ = true; - site_ = GetSiteForURL(url); - - // Now that we have a site, register it with the BrowsingInstance. This - // ensures that we won't create another SiteInstance for this site within - // the same BrowsingInstance, because all same-site pages within a - // BrowsingInstance can script each other. - browsing_instance_->RegisterSiteInstance(this); -} - -bool SiteInstance::HasRelatedSiteInstance(const GURL& url) { - return browsing_instance_->HasSiteInstance(url); -} - -SiteInstance* SiteInstance::GetRelatedSiteInstance(const GURL& url) { - return browsing_instance_->GetSiteInstanceForURL(url); -} - -/*static*/ -SiteInstance* SiteInstance::CreateSiteInstance(Profile* profile) { - return new SiteInstance(new BrowsingInstance(profile)); -} - -/*static*/ -GURL SiteInstance::GetSiteForURL(const GURL& url) { - // URLs with no host should have an empty site. - GURL site; - - // TODO(creis): For many protocols, we should just treat the scheme as the - // site, since there is no host. e.g., file:, about:, chrome: - - // If the url has a host, then determine the site. - if (url.has_host()) { - // Only keep the scheme and registered domain as given by GetOrigin. This - // may also include a port, which we need to drop. - site = url.GetOrigin(); - - // Remove port, if any. - if (site.has_port()) { - GURL::Replacements rep; - rep.ClearPort(); - site = site.ReplaceComponents(rep); - } - - // If this URL has a registered domain, we only want to remember that part. - std::string domain = - net::RegistryControlledDomainService::GetDomainAndRegistry(url); - if (!domain.empty()) { - GURL::Replacements rep; - rep.SetHostStr(domain); - site = site.ReplaceComponents(rep); - } - } - return site; -} - -/*static*/ -bool SiteInstance::IsSameWebSite(const GURL& url1, const GURL& url2) { - // We infer web site boundaries based on the registered domain name of the - // top-level page and the scheme. We do not pay attention to the port if - // one is present, because pages served from different ports can still - // access each other if they change their document.domain variable. - - // We must treat javascript: URLs as part of the same site, regardless of - // the site. - if (url1.SchemeIs("javascript") || url2.SchemeIs("javascript")) - return true; - - // We treat about:crash, about:hang, and about:shorthang as the same site as - // any URL, since they are used as demos for crashing/hanging a process. - GURL about_crash = GURL("about:crash"); - GURL about_hang = GURL("about:hang"); - GURL about_shorthang = GURL("about:shorthang"); - if (url1 == about_crash || url2 == about_crash || - url1 == about_hang || url2 == about_hang || - url1 == about_shorthang || url2 == about_shorthang) - return true; - - // If either URL is invalid, they aren't part of the same site. - if (!url1.is_valid() || !url2.is_valid()) { - return false; - } - - // If the schemes differ, they aren't part of the same site. - if (url1.scheme() != url2.scheme()) { - return false; - } - - return net::RegistryControlledDomainService::SameDomainOrHost(url1, url2); -} - diff --git a/chrome/browser/site_instance.h b/chrome/browser/site_instance.h deleted file mode 100644 index 6759fe3..0000000 --- a/chrome/browser/site_instance.h +++ /dev/null @@ -1,156 +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. - -#ifndef CHROME_BROWSER_SITE_INSTANCE_H__ -#define CHROME_BROWSER_SITE_INSTANCE_H__ - -#include "chrome/browser/browsing_instance.h" -#include "chrome/browser/render_process_host.h" -#include "googleurl/src/gurl.h" - -/////////////////////////////////////////////////////////////////////////////// -// -// SiteInstance class -// -// A SiteInstance is a data structure that is associated with all pages in a -// given instance of a web site. Here, a web site is identified by its -// registered domain name and scheme. An instance includes all pages -// that are connected (i.e., either a user or a script navigated from one -// to the other). We represent instances using the BrowsingInstance class. -// -// In --process-per-tab, one SiteInstance is created for each tab (i.e., in the -// WebContents constructor), unless the tab is created by script (i.e., in -// WebContents::CreateNewView). This corresponds to one process per -// BrowsingInstance. -// -// In process-per-site-instance (the current default process model), -// SiteInstances are created (1) when the user manually creates a new tab -// (which also creates a new BrowsingInstance), and (2) when the user navigates -// across site boundaries (which uses the same BrowsingInstance). If the user -// navigates within a site, or opens links in new tabs within a site, the same -// SiteInstance is used. -// -// In --process-per-site, we consolidate all SiteInstances for a given site, -// throughout the entire profile. This ensures that only one process will be -// dedicated to each site. -// -// Each NavigationEntry for a WebContents points to the SiteInstance that -// rendered it. Each RenderViewHost also points to the SiteInstance that it is -// associated with. A SiteInstance keeps track of the number of these -// references and deletes itself when the count goes to zero. This means that -// a SiteInstance is only live as long as it is accessible, either from new -// tabs with no NavigationEntries or in NavigationEntries in the history. -// -/////////////////////////////////////////////////////////////////////////////// -class SiteInstance : public base::RefCounted { - public: - // Virtual to allow tests to extend it. - virtual ~SiteInstance(); - - // Get the BrowsingInstance to which this SiteInstance belongs. - BrowsingInstance* browsing_instance() { return browsing_instance_; } - - // Set / Get the host ID for this SiteInstance's current RenderProcessHost. - void set_process_host_id(int process_host_id) { - process_host_id_ = process_host_id; - } - int process_host_id() const { return process_host_id_; } - - // Update / Get the max page ID for this SiteInstance. - void UpdateMaxPageID(int32 page_id) { - if (page_id > max_page_id_) - max_page_id_ = page_id; - } - int32 max_page_id() const { return max_page_id_; } - - // Returns the current process being used to render pages in this - // SiteInstance. If the process has crashed or otherwise gone away, then - // this method will create a new process and update our host ID accordingly. - RenderProcessHost* GetProcess(); - - // Set / Get the web site that this SiteInstance is rendering pages for. - // This includes the scheme and registered domain, but not the port. If the - // URL does not have a valid registered domain, then the full hostname is - // stored. - void SetSite(const GURL& url); - const GURL& site() const { return site_; } - bool has_site() const { return has_site_; } - - // Returns whether there is currently a related SiteInstance (registered with - // BrowsingInstance) for the site of the given url. If so, we should try to - // avoid dedicating an unused SiteInstance to it (e.g., in a new tab). - bool HasRelatedSiteInstance(const GURL& url); - - // Gets a SiteInstance for the given URL that shares the current - // BrowsingInstance, creating a new SiteInstance if necessary. This ensures - // that a BrowsingInstance only has one SiteInstance per site, so that pages - // in a BrowsingInstance have the ability to script each other. Callers - // should ensure that this SiteInstance becomes ref counted, by storing it in - // a scoped_refptr. (By having this method, we can hide the BrowsingInstance - // class from the rest of the codebase.) - // TODO(creis): This may be an argument to build a pass_refptr class, as - // Darin suggests. - SiteInstance* GetRelatedSiteInstance(const GURL& url); - - // Factory method to create a new SiteInstance. This will create a new - // new BrowsingInstance, so it should only be used when creating a new tab - // from scratch (or similar circumstances). Callers should ensure that - // this SiteInstance becomes ref counted, by storing it in a scoped_refptr. - // TODO(creis): This may be an argument to build a pass_refptr class, as - // Darin suggests. - static SiteInstance* CreateSiteInstance(Profile* profile); - - // Returns the site for the given URL, which includes only the scheme and - // registered domain. Returns an empty GURL if the URL has no host. - static GURL GetSiteForURL(const GURL& url); - - // Return whether both URLs are part of the same web site, for the purpose of - // assigning them to processes accordingly. The decision is currently based - // on the registered domain of the URLs (google.com, bbc.co.uk), as well as - // the scheme (https, http). This ensures that two pages will be in - // the same process if they can communicate with other via JavaScript. - // (e.g., docs.google.com and mail.google.com have DOM access to each other - // if they both set their document.domain properties to google.com.) - static bool IsSameWebSite(const GURL& url1, const GURL& url2); - - protected: - friend class BrowsingInstance; - - // Create a new SiteInstance. Protected to give access to BrowsingInstance - // and tests; most callers should use CreateSiteInstance or - // GetRelatedSiteInstance instead. - SiteInstance(BrowsingInstance* browsing_instance) - : browsing_instance_(browsing_instance), - process_host_id_(-1), - max_page_id_(-1), - has_site_(false) { - DCHECK(browsing_instance); - } - - private: - // BrowsingInstance to which this SiteInstance belongs. - scoped_refptr browsing_instance_; - - // Current host ID for the RenderProcessHost that is rendering pages for this - // SiteInstance. If the rendering process dies, this host ID can be - // replaced when a new process is created, without losing the association - // between all pages in this SiteInstance. - int process_host_id_; - - // The current max_page_id in the SiteInstance's RenderProcessHost. If the - // rendering process dies, its replacement should start issuing page IDs that - // are larger than this value. - int32 max_page_id_; - - // The web site that this SiteInstance is rendering pages for. - GURL site_; - - // Whether SetSite has been called. - bool has_site_; - - DISALLOW_EVIL_CONSTRUCTORS(SiteInstance); -}; - -#endif // CHROME_BROWSER_SITE_INSTANCE_H__ - diff --git a/chrome/browser/site_instance_unittest.cc b/chrome/browser/site_instance_unittest.cc index dc0297e..16e6883 100644 --- a/chrome/browser/site_instance_unittest.cc +++ b/chrome/browser/site_instance_unittest.cc @@ -2,9 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/navigation_entry.h" #include "chrome/browser/render_view_host.h" -#include "chrome/browser/web_contents.h" +#include "chrome/browser/tab_contents/navigation_entry.h" +#include "chrome/browser/tab_contents/web_contents.h" #include "chrome/common/render_messages.h" #include "chrome/test/testing_profile.h" #include "testing/gtest/include/gtest/gtest.h" diff --git a/chrome/browser/ssl_blocking_page.cc b/chrome/browser/ssl_blocking_page.cc index 88b402c..67ea40a 100644 --- a/chrome/browser/ssl_blocking_page.cc +++ b/chrome/browser/ssl_blocking_page.cc @@ -9,10 +9,10 @@ #include "chrome/browser/browser_resources.h" #include "chrome/browser/cert_store.h" #include "chrome/browser/dom_operation_notification_details.h" -#include "chrome/browser/navigation_controller.h" -#include "chrome/browser/navigation_entry.h" #include "chrome/browser/ssl_error_info.h" -#include "chrome/browser/web_contents.h" +#include "chrome/browser/tab_contents/navigation_controller.h" +#include "chrome/browser/tab_contents/navigation_entry.h" +#include "chrome/browser/tab_contents/web_contents.h" #include "chrome/common/jstemplate_builder.h" #include "chrome/common/l10n_util.h" #include "chrome/common/pref_names.h" diff --git a/chrome/browser/ssl_blocking_page.h b/chrome/browser/ssl_blocking_page.h index 0b4e9c6..69472fa 100644 --- a/chrome/browser/ssl_blocking_page.h +++ b/chrome/browser/ssl_blocking_page.h @@ -7,7 +7,7 @@ #include -#include "chrome/browser/interstitial_page.h" +#include "chrome/browser/tab_contents/interstitial_page.h" #include "chrome/browser/ssl_manager.h" #include "chrome/views/decision.h" diff --git a/chrome/browser/ssl_manager.cc b/chrome/browser/ssl_manager.cc index 5ff8778..a91b248 100644 --- a/chrome/browser/ssl_manager.cc +++ b/chrome/browser/ssl_manager.cc @@ -8,19 +8,19 @@ #include "base/string_util.h" #include "chrome/app/theme/theme_resources.h" #include "chrome/browser/browser_process.h" -#include "chrome/browser/provisional_load_details.h" -#include "chrome/browser/infobar_delegate.h" #include "chrome/browser/load_notification_details.h" #include "chrome/browser/load_from_memory_cache_details.h" -#include "chrome/browser/navigation_controller.h" -#include "chrome/browser/navigation_entry.h" #include "chrome/browser/render_view_host.h" #include "chrome/browser/resource_request_details.h" #include "chrome/browser/ssl_error_info.h" #include "chrome/browser/ssl_policy.h" -#include "chrome/browser/tab_contents.h" -#include "chrome/browser/tab_util.h" -#include "chrome/browser/web_contents.h" +#include "chrome/browser/tab_contents/infobar_delegate.h" +#include "chrome/browser/tab_contents/navigation_controller.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.h" +#include "chrome/browser/tab_contents/tab_util.h" +#include "chrome/browser/tab_contents/web_contents.h" #include "chrome/common/l10n_util.h" #include "chrome/common/notification_service.h" #include "chrome/common/pref_names.h" diff --git a/chrome/browser/ssl_manager.h b/chrome/browser/ssl_manager.h index 9434a4b..e650b35 100644 --- a/chrome/browser/ssl_manager.h +++ b/chrome/browser/ssl_manager.h @@ -11,9 +11,9 @@ #include "base/basictypes.h" #include "base/observer_list.h" #include "base/ref_counted.h" -#include "chrome/browser/provisional_load_details.h" -#include "chrome/browser/security_style.h" #include "chrome/browser/renderer_host/resource_dispatcher_host.h" +#include "chrome/browser/security_style.h" +#include "chrome/browser/tab_contents/provisional_load_details.h" #include "chrome/common/notification_registrar.h" #include "chrome/common/notification_service.h" #include "chrome/common/render_messages.h" diff --git a/chrome/browser/ssl_policy.cc b/chrome/browser/ssl_policy.cc index f89cdcd..ea92e37 100644 --- a/chrome/browser/ssl_policy.cc +++ b/chrome/browser/ssl_policy.cc @@ -9,11 +9,11 @@ #include "base/string_util.h" #include "chrome/browser/browser_resources.h" #include "chrome/browser/cert_store.h" -#include "chrome/browser/navigation_entry.h" #include "chrome/browser/render_view_host.h" #include "chrome/browser/ssl_error_info.h" -#include "chrome/browser/tab_contents.h" -#include "chrome/browser/web_contents.h" +#include "chrome/browser/tab_contents/navigation_entry.h" +#include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/tab_contents/web_contents.h" #include "chrome/common/jstemplate_builder.h" #include "chrome/common/l10n_util.h" #include "chrome/common/notification_service.h" diff --git a/chrome/browser/status_view.cc b/chrome/browser/status_view.cc deleted file mode 100644 index 30395fc..0000000 --- a/chrome/browser/status_view.cc +++ /dev/null @@ -1,74 +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/status_view.h" - -const int StatusView::kLayoutPadding = 5; -const int StatusView::kButtonWidth = 200; -const int StatusView::kButtonHeight = 30; - -StatusView::StatusView(TabContentsType type) : TabContents(type) { -} - -StatusView::~StatusView() { - for (size_t i = 0; i < buttons_.size(); ++i) - delete buttons_[i].button; -} - -void StatusView::CreateView() { - Create(GetDesktopWindow()); -} - -LRESULT StatusView::OnCreate(LPCREATESTRUCT create_struct) { - CRect rect(kLayoutPadding, kButtonHeight + kLayoutPadding * 2, 200, 200); - OnCreate(rect); - return 0; -} - -void StatusView::OnSize(WPARAM wParam, const CSize& size) { - int start_x = kLayoutPadding; - int start_y = kButtonHeight + kLayoutPadding * 2; - int end_x = size.cx - kLayoutPadding; - int end_y = size.cy - kLayoutPadding; - CRect rect(start_x, start_y, end_x, end_y); - OnSize(rect); -} - -LRESULT StatusView::OnEraseBkgnd(HDC hdc) { - HBRUSH brush = GetSysColorBrush(COLOR_3DFACE); - HGDIOBJ old_brush = SelectObject(hdc, brush); - - RECT rc; - GetClientRect(&rc); - FillRect(hdc, &rc, brush); - - SelectObject(hdc, old_brush); - return 1; -} - -void StatusView::CreateButton(int id, const wchar_t* title) { - int button_count = static_cast(buttons_.size()); - int width_offset = - kLayoutPadding + button_count * (kButtonWidth + kLayoutPadding); - CRect rect(0, 0, kButtonWidth, kButtonHeight); - rect.OffsetRect(width_offset, kLayoutPadding); - ButtonInfo bi; - bi.button = new CButton(); - bi.id = id; - bi.button->Create(m_hWnd, rect, NULL, WS_CHILD | WS_VISIBLE, 0, bi.id); - bi.button->SetWindowText(title); - buttons_.push_back(bi); -} - -void StatusView::SetButtonText(int id, const wchar_t* title) { - for (size_t i = 0; i < buttons_.size(); ++i) { - if (buttons_[i].id == id) { - buttons_[i].button->SetWindowText(title); - return; - } - } - - DLOG(INFO) << "No button with id " << id << " to set title " << title; -} - diff --git a/chrome/browser/status_view.h b/chrome/browser/status_view.h deleted file mode 100644 index 7184ba5..0000000 --- a/chrome/browser/status_view.h +++ /dev/null @@ -1,84 +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. - -#ifndef CHROME_BROWSER_STATUS_VIEW_H__ -#define CHROME_BROWSER_STATUS_VIEW_H__ - -#include -#include -#include -#include -#include -#include - -#include "base/basictypes.h" -#include "chrome/browser/tab_contents.h" - -typedef CWinTraits - StatusViewTraits; - -// A base class for about:network, about:ipc etc. It handles creating a row of -// buttons at the top of the page. Derived classes get a rect of the remaining -// area and can create their own controls there. -class StatusView : public TabContents, - public CWindowImpl { - public: - StatusView(TabContentsType type); - - BEGIN_MSG_MAP(StatusView) - MSG_WM_CREATE(OnCreate) - MSG_WM_ERASEBKGND(OnEraseBkgnd) - MSG_WM_SIZE(OnSize) - END_MSG_MAP() - - virtual void CreateView(); - virtual HWND GetContainerHWND() const { return m_hWnd; } - - // Derived classes should implement the following functions - // TabContents override, to set the page title. - // virtual const std::wstring GetDefaultTitle() = 0; - // Gives a rect whose top left corner is after the buttons. The size of the - // controls that are added by derived classes will be set in the next OnSize, - // for now can use any height/width. - virtual void OnCreate(const CRect& rect) = 0; - virtual void OnSize(const CRect& rect) = 0; - - protected: - // Should be deleted via CloseContents. - virtual ~StatusView(); - - // Creates and adds a button to the top row of the page. Button ids should - // be unique and start at 101. - void CreateButton(int id, const wchar_t* title); - void SetButtonText(int id, const wchar_t* title); - - static const int kLayoutPadding; - static const int kButtonWidth; - static const int kButtonHeight; - - private: - // FocusTraversal Implementation - // TODO (jcampan): make focus traversal work - views::View* FindNextFocusableView(views::View* starting_view, bool reverse, - bool dont_loop) { - return NULL; - } - - // Event handlers - LRESULT OnCreate(LPCREATESTRUCT create_struct); - void OnSize(UINT size_command, const CSize& new_size); - LRESULT OnEraseBkgnd(HDC hdc); - - struct ButtonInfo { - CButton* button; - int id; - }; - - std::vector buttons_; - - DISALLOW_EVIL_CONSTRUCTORS(StatusView); -}; - -#endif // #ifndef CHROME_BROWSER_STATUS_VIEW_H__ - diff --git a/chrome/browser/tab_contents.cc b/chrome/browser/tab_contents.cc deleted file mode 100644 index 9507cd4..0000000 --- a/chrome/browser/tab_contents.cc +++ /dev/null @@ -1,605 +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.h" - -#include "chrome/browser/cert_store.h" -#include "chrome/browser/navigation_entry.h" -#include "chrome/browser/infobar_delegate.h" -#include "chrome/browser/views/download_shelf_view.h" -#include "chrome/browser/views/download_started_animation.h" -#include "chrome/browser/views/blocked_popup_container.h" -#include "chrome/browser/web_contents.h" -#include "chrome/browser/tab_contents_delegate.h" -#include "chrome/common/l10n_util.h" -#include "chrome/common/pref_names.h" -#include "chrome/common/pref_service.h" -#include "chrome/views/native_scroll_bar.h" -#include "chrome/views/root_view.h" -#include "chrome/views/view.h" -#include "chrome/views/view_storage.h" -#include "chrome/views/widget.h" - -#include "generated_resources.h" - -namespace { - -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; -} - -} // namespace - -TabContents::TabContents(TabContentsType type) - : type_(type), - delegate_(NULL), - controller_(NULL), - is_loading_(false), - is_active_(true), - is_crashed_(false), - waiting_for_response_(false), - shelf_visible_(false), - max_page_id_(-1), - blocked_popups_(NULL), - capturing_contents_(false), - is_being_destroyed_(false) { - last_focused_view_storage_id_ = - views::ViewStorage::GetSharedInstance()->CreateStorageID(); -} - -TabContents::~TabContents() { - // Makes sure to remove any stored view we may still have in the ViewStorage. - // - // It is possible the view went away before us, so we only do this if the - // view is registered. - views::ViewStorage* view_storage = views::ViewStorage::GetSharedInstance(); - if (view_storage->RetrieveView(last_focused_view_storage_id_) != NULL) - view_storage->RemoveView(last_focused_view_storage_id_); -} - -// static -void TabContents::RegisterUserPrefs(PrefService* prefs) { - prefs->RegisterBooleanPref(prefs::kBlockPopups, false); -} - -void TabContents::CloseContents() { - // Destroy our NavigationController, which will Destroy all tabs it owns. - controller_->Destroy(); - // Note that the controller may have deleted us at this point, - // so don't touch any member variables here. -} - -void TabContents::Destroy() { - DCHECK(!is_being_destroyed_); - is_being_destroyed_ = true; - - // 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. - int size = static_cast(child_windows_.size()); - for (int i = size - 1; i >= 0; --i) { - ConstrainedWindow* window = child_windows_[i]; - if (window) - window->CloseConstrainedWindow(); - } - - // Notify any observer that have a reference on this tab contents. - NotificationService::current()->Notify(NOTIFY_TAB_CONTENTS_DESTROYED, - Source(this), - NotificationService::NoDetails()); - - // If we still have a window handle, destroy it. GetContainerHWND can return - // NULL if this contents was part of a window that closed. - if (GetContainerHWND()) - ::DestroyWindow(GetContainerHWND()); - - // Notify our NavigationController. Make sure we are deleted first, so - // that the controller is the last to die. - NavigationController* controller = controller_; - TabContentsType type = this->type(); - - delete this; - - controller->TabContentsWasDestroyed(type); -} - -void TabContents::SetupController(Profile* profile) { - DCHECK(!controller_); - controller_ = new NavigationController(this, profile); -} - -bool TabContents::SupportsURL(GURL* url) { - GURL u(*url); - if (TabContents::TypeForURL(&u) == type()) { - *url = u; - return true; - } - return false; -} - -const GURL& TabContents::GetURL() const { - // We may not have a navigation entry yet - NavigationEntry* entry = controller_->GetActiveEntry(); - return entry ? entry->display_url() : GURL::EmptyGURL(); -} - -const std::wstring& TabContents::GetTitle() const { - // 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. - // The exception is with transient pages, for which we really want to use - // their title, as they are not committed. - NavigationEntry* entry = controller_->GetTransientEntry(); - if (entry) - return entry->GetTitleForDisplay(); - - entry = controller_->GetLastCommittedEntry(); - if (entry) - return entry->GetTitleForDisplay(); - else if (controller_->LoadingURLLazily()) - return controller_->GetLazyTitle(); - return EmptyWString(); -} - -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 WebContents will also have site instances, except during - // testing. - if (GetSiteInstance()) - GetSiteInstance()->UpdateMaxPageID(page_id); - - if (AsWebContents()) - AsWebContents()->process()->UpdateMaxPageID(page_id); - else - max_page_id_ = std::max(max_page_id_, page_id); -} - -const std::wstring TabContents::GetDefaultTitle() const { - return l10n_util::GetString(IDS_DEFAULT_TAB_TITLE); -} - -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(); - else if (controller_->LoadingURLLazily()) - return controller_->GetLazyFavIcon(); - return SkBitmap(); -} - -SecurityStyle TabContents::GetSecurityStyle() const { - // We may not have a navigation entry yet. - NavigationEntry* entry = controller_->GetActiveEntry(); - return entry ? entry->ssl().security_style() : SECURITY_STYLE_UNKNOWN; -} - -bool TabContents::GetSSLEVText(std::wstring* ev_text, - std::wstring* ev_tooltip_text) const { - DCHECK(ev_text && ev_tooltip_text); - ev_text->clear(); - ev_tooltip_text->clear(); - - NavigationEntry* entry = controller_->GetActiveEntry(); - if (!entry || - net::IsCertStatusError(entry->ssl().cert_status()) || - ((entry->ssl().cert_status() & net::CERT_STATUS_IS_EV) == 0)) - return false; - - scoped_refptr cert; - CertStore::GetSharedInstance()->RetrieveCert(entry->ssl().cert_id(), &cert); - if (!cert.get()) { - NOTREACHED(); - return false; - } - - return SSLManager::GetEVCertNames(*cert, ev_text, ev_tooltip_text); -} - -void TabContents::SetIsCrashed(bool state) { - if (state == is_crashed_) - return; - - is_crashed_ = state; - if (delegate_) - delegate_->ContentsStateChanged(this); -} - -void TabContents::NotifyNavigationStateChanged(unsigned changed_flags) { - if (delegate_) - delegate_->NavigationStateChanged(this, changed_flags); -} - -void TabContents::DidBecomeSelected() { - if (controller_) - controller_->SetActive(true); - - // Invalidate all descendants. (take care to exclude invalidating ourselves!) - EnumChildWindows(GetContainerHWND(), InvalidateWindow, 0); -} - -void TabContents::WasHidden() { - NotificationService::current()->Notify(NOTIFY_TAB_CONTENTS_HIDDEN, - Source(this), - NotificationService::NoDetails()); -} - -void TabContents::Activate() { - if (delegate_) - delegate_->ActivateContents(this); -} - -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(bool reload) { - // Our benavior is just to report that the entry was committed. - controller()->GetPendingEntry()->set_title(GetDefaultTitle()); - controller()->CommitPendingEntry(); - return true; -} - -ConstrainedWindow* TabContents::CreateConstrainedDialog( - views::WindowDelegate* window_delegate, - views::View* contents_view) { - ConstrainedWindow* window = - ConstrainedWindow::CreateConstrainedDialog( - this, gfx::Rect(), contents_view, window_delegate); - child_windows_.push_back(window); - return window; -} - -void TabContents::AddNewContents(TabContents* new_contents, - WindowOpenDisposition disposition, - const gfx::Rect& initial_pos, - bool user_gesture) { - if (!delegate_) - return; - - if ((disposition == NEW_POPUP) && !user_gesture) { - // Unrequested popups from normal pages are constrained. - TabContents* popup_owner = this; - TabContents* our_owner = delegate_->GetConstrainingContents(this); - if (our_owner) - popup_owner = our_owner; - popup_owner->AddConstrainedPopup(new_contents, initial_pos); - } else { - new_contents->DisassociateFromPopupCount(); - - delegate_->AddNewContents(this, new_contents, disposition, initial_pos, - user_gesture); - - PopupNotificationVisibilityChanged(ShowingBlockedPopupNotification()); - } -} - -void TabContents::AddConstrainedPopup(TabContents* new_contents, - const gfx::Rect& initial_pos) { - if (!blocked_popups_) { - CRect client_rect; - GetClientRect(GetContainerHWND(), &client_rect); - gfx::Point anchor_position( - client_rect.Width() - - views::NativeScrollBar::GetVerticalScrollBarWidth(), - client_rect.Height()); - - blocked_popups_ = BlockedPopupContainer::Create( - this, profile(), anchor_position); - child_windows_.push_back(blocked_popups_); - } - - blocked_popups_->AddTabContents(new_contents, initial_pos); - PopupNotificationVisibilityChanged(ShowingBlockedPopupNotification()); -} - -void TabContents::CloseAllSuppressedPopups() { - if (blocked_popups_) - blocked_popups_->CloseAllPopups(); -} - -void TabContents::Focus() { - HWND container_hwnd = GetContainerHWND(); - if (!container_hwnd) - return; - - views::FocusManager* focus_manager = - views::FocusManager::GetFocusManager(container_hwnd); - DCHECK(focus_manager); - views::View* v = focus_manager->GetViewForWindow(container_hwnd, true); - DCHECK(v); - if (v) - v->RequestFocus(); -} - -void TabContents::StoreFocus() { - views::ViewStorage* view_storage = - views::ViewStorage::GetSharedInstance(); - - if (view_storage->RetrieveView(last_focused_view_storage_id_) != NULL) - view_storage->RemoveView(last_focused_view_storage_id_); - - views::FocusManager* focus_manager = - views::FocusManager::GetFocusManager(GetContainerHWND()); - if (focus_manager) { - // |focus_manager| can be NULL if the tab has been detached but still - // exists. - views::View* focused_view = focus_manager->GetFocusedView(); - if (focused_view) - view_storage->StoreView(last_focused_view_storage_id_, focused_view); - - // If the focus was on the page, explicitly clear the focus so that we - // don't end up with the focused HWND not part of the window hierarchy. - // TODO(brettw) this should move to the view somehow. - HWND container_hwnd = GetContainerHWND(); - if (container_hwnd) { - views::View* focused_view = focus_manager->GetFocusedView(); - if (focused_view) { - HWND hwnd = focused_view->GetRootView()->GetWidget()->GetHWND(); - if (container_hwnd == hwnd || ::IsChild(container_hwnd, hwnd)) - focus_manager->ClearFocus(); - } - } - } -} - -void TabContents::RestoreFocus() { - views::ViewStorage* view_storage = - views::ViewStorage::GetSharedInstance(); - views::View* last_focused_view = - view_storage->RetrieveView(last_focused_view_storage_id_); - - if (!last_focused_view) { - SetInitialFocus(); - } else { - views::FocusManager* focus_manager = - views::FocusManager::GetFocusManager(GetContainerHWND()); - - // If you hit this DCHECK, please report it to Jay (jcampan). - DCHECK(focus_manager != NULL) << "No focus manager when restoring focus."; - - if (focus_manager && focus_manager->ContainsView(last_focused_view)) { - last_focused_view->RequestFocus(); - } else { - // The focused view may not belong to the same window hierarchy (for - // example if the location bar was focused and the tab is dragged out). - // In that case we default to the default focus. - SetInitialFocus(); - } - view_storage->RemoveView(last_focused_view_storage_id_); - } -} - -void TabContents::SetInitialFocus() { - ::SetFocus(GetContainerHWND()); -} - -void TabContents::AddInfoBar(InfoBarDelegate* delegate) { - // 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 (int i = 0; i < infobar_delegate_count(); ++i) { - if (GetInfoBarDelegateAt(i)->EqualsDelegate(delegate)) - return; - } - - infobar_delegates_.push_back(delegate); - NotificationService::current()->Notify(NOTIFY_TAB_CONTENTS_INFOBAR_ADDED, - Source(this), - Details(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) { - DCHECK(controller()); - registrar_.Add(this, NOTIFY_NAV_ENTRY_COMMITTED, - Source(controller())); - } -} - -void TabContents::RemoveInfoBar(InfoBarDelegate* delegate) { - std::vector::iterator it = - find(infobar_delegates_.begin(), infobar_delegates_.end(), delegate); - if (it != infobar_delegates_.end()) { - InfoBarDelegate* delegate = *it; - NotificationService::current()->Notify(NOTIFY_TAB_CONTENTS_INFOBAR_REMOVED, - Source(this), - Details(delegate)); - infobar_delegates_.erase(it); - - // Remove ourselves as an observer if we are tracking no more InfoBars. - if (infobar_delegates_.empty()) { - registrar_.Remove(this, NOTIFY_NAV_ENTRY_COMMITTED, - Source(controller())); - } - } -} - -void TabContents::SetDownloadShelfVisible(bool visible) { - if (shelf_visible_ != visible) { - if (visible) { - // Invoke GetDownloadShelfView to force the shelf to be created. - GetDownloadShelfView(); - } - shelf_visible_ = visible; - - if (delegate_) - delegate_->ContentsStateChanged(this); - } - - // SetShelfVisible can force-close the shelf, so make sure we lay out - // everything correctly, as if the animation had finished. This doesn't - // matter for showing the shelf, as the show animation will do it. - ToolbarSizeChanged(false); -} - -void TabContents::ToolbarSizeChanged(bool is_animating) { - TabContentsDelegate* d = delegate(); - if (d) - d->ToolbarSizeChanged(this, is_animating); -} - -void TabContents::OnStartDownload(DownloadItem* download) { - DCHECK(download); - TabContents* tab_contents = this; - - // Download in a constrained popup is shown in the tab that opened it. - TabContents* constraining_tab = delegate()->GetConstrainingContents(this); - if (constraining_tab) - tab_contents = constraining_tab; - - // GetDownloadShelfView creates the download shelf if it was not yet created. - tab_contents->GetDownloadShelfView()->AddDownload(download); - tab_contents->SetDownloadShelfVisible(true); - - // This animation will delete itself when it finishes, or if we become hidden - // or destroyed. - if (IsWindowVisible(GetContainerHWND())) { // For minimized windows, unit - // tests, etc. - new DownloadStartedAnimation(tab_contents); - } -} - -DownloadShelfView* TabContents::GetDownloadShelfView() { - if (!download_shelf_view_.get()) { - download_shelf_view_.reset(new DownloadShelfView(this)); - // The TabContents owns the download-shelf. - download_shelf_view_->SetParentOwned(false); - } - return download_shelf_view_.get(); -} - -void TabContents::MigrateShelfViewFrom(TabContents* tab_contents) { - download_shelf_view_.reset(tab_contents->GetDownloadShelfView()); - download_shelf_view_->ChangeTabContents(tab_contents, this); - tab_contents->ReleaseDownloadShelfView(); -} - -void TabContents::WillClose(ConstrainedWindow* window) { - ConstrainedWindowList::iterator it = - find(child_windows_.begin(), child_windows_.end(), window); - if (it != child_windows_.end()) - child_windows_.erase(it); - - if (window == blocked_popups_) - blocked_popups_ = NULL; - - if (::IsWindow(GetContainerHWND())) { - CRect client_rect; - GetClientRect(GetContainerHWND(), &client_rect); - RepositionSupressedPopupsToFit( - gfx::Size(client_rect.Width(), client_rect.Height())); - } -} - -void TabContents::DidMoveOrResize(ConstrainedWindow* window) { - UpdateWindow(GetContainerHWND()); -} - -void TabContents::Observe(NotificationType type, - const NotificationSource& source, - const NotificationDetails& details) { - DCHECK(type == NOTIFY_NAV_ENTRY_COMMITTED); - DCHECK(controller() == Source(source).ptr()); - - NavigationController::LoadCommittedDetails& committed_details = - *(Details(details).ptr()); - ExpireInfoBars(committed_details); -} - -// static -void TabContents::MigrateShelfView(TabContents* from, TabContents* to) { - bool was_shelf_visible = from->IsDownloadShelfVisible(); - if (was_shelf_visible) - to->MigrateShelfViewFrom(from); - to->SetDownloadShelfVisible(was_shelf_visible); -} - -void TabContents::SetIsLoading(bool is_loading, - LoadNotificationDetails* details) { - if (is_loading == is_loading_) - return; - - is_loading_ = is_loading; - waiting_for_response_ = is_loading; - - // Suppress notifications for this TabContents if we are not active. - if (!is_active_) - return; - - if (delegate_) - delegate_->LoadingStateChanged(this); - - NotificationService::current()-> - Notify((is_loading ? NOTIFY_LOAD_START : NOTIFY_LOAD_STOP), - Source(this->controller()), - details ? Details(details) : - NotificationService::NoDetails()); -} - -// TODO(brettw) This should be on the WebContentsView. -void TabContents::RepositionSupressedPopupsToFit(const gfx::Size& new_size) { - // TODO(erg): There's no way to detect whether scroll bars are - // visible, so for beta, we're just going to assume that the - // vertical scroll bar is visible, and not care about covering up - // the horizontal scroll bar. Fixing this is half of - // http://b/1118139. - gfx::Point anchor_position( - new_size.width() - - views::NativeScrollBar::GetVerticalScrollBarWidth(), - new_size.height()); - - if (blocked_popups_) - blocked_popups_->RepositionConstrainedWindowTo(anchor_position); -} - -void TabContents::ReleaseDownloadShelfView() { - download_shelf_view_.release(); -} - -bool TabContents::ShowingBlockedPopupNotification() const { - return blocked_popups_ != NULL && - blocked_popups_->GetTabContentsCount() != 0; -} - -namespace { -bool TransitionIsReload(PageTransition::Type transition) { - return PageTransition::StripQualifier(transition) == PageTransition::RELOAD; -} -} - -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; - - for (int i = infobar_delegate_count() - 1; i >= 0; --i) { - InfoBarDelegate* delegate = GetInfoBarDelegateAt(i); - if (delegate->ShouldExpire(details)) - RemoveInfoBar(delegate); - } -} diff --git a/chrome/browser/tab_contents.h b/chrome/browser/tab_contents.h deleted file mode 100644 index 833939b..0000000 --- a/chrome/browser/tab_contents.h +++ /dev/null @@ -1,560 +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. - -#ifndef CHROME_BROWSER_TAB_CONTENTS_H_ -#define CHROME_BROWSER_TAB_CONTENTS_H_ - -#include -#include - -#include "chrome/browser/autocomplete/autocomplete_edit.h" -#include "chrome/browser/constrained_window.h" -#include "chrome/browser/infobar_delegate.h" -#include "chrome/browser/navigation_controller.h" -#include "chrome/browser/page_navigator.h" -#include "chrome/browser/tab_contents_type.h" -#include "chrome/common/navigation_types.h" -#include "chrome/common/notification_registrar.h" -#include "chrome/common/property_bag.h" - -namespace gfx { -class Rect; -class Size; -} -namespace views { -class RootView; -class WindowDelegate; -} - -class BlockedPopupContainer; -class DOMUIHost; -class DownloadItem; -class DownloadShelfView; -class InfoBarView; -class LoadNotificationDetails; -class Profile; -class TabContentsDelegate; -class TabContentsFactory; -class SkBitmap; -class SiteInstance; -class WebContents; - -// Describes what goes in the main content area of a tab. For example, -// the WebContents is one such thing. -// -// When instantiating a new TabContents explicitly, the TabContents will not -// have an associated NavigationController. To setup a NavigationController -// for the TabContents, its SetupController method should be called. -// -// Once they reside within a NavigationController, TabContents objects are -// owned by that NavigationController. When the active TabContents within that -// NavigationController is closed, that TabContents destroys the -// NavigationController, which then destroys all of the TabContentses in it. -// -// NOTE: When the NavigationController is navigated to an URL corresponding to -// a different type of TabContents (see the TabContents::TypeForURL method), -// the NavigationController makes the active TabContents inactive, notifies the -// TabContentsDelegate that the TabContents is being replaced, and then -// activates the new TabContents. -class TabContents : public PageNavigator, - public NotificationObserver { - 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, // The URL has changed. - INVALIDATE_TITLE = 2, // The title has changed. - INVALIDATE_FAVICON = 4, // The favicon has changed. - INVALIDATE_LOAD = 8, // The loading state has changed - - // Helper for forcing a refresh. - INVALIDATE_EVERYTHING = 0xFFFFFFFF - }; - - static void RegisterUserPrefs(PrefService* prefs); - - // Factory ------------------------------------------------------------------- - // (implemented in tab_contents_factory.cc) - - // Creates a new TabContents of the given type. Will reuse the given - // instance's renderer, if it is not null. - static TabContents* CreateWithType(TabContentsType type, - Profile* profile, - SiteInstance* instance); - - // Returns the type of TabContents needed to handle the URL. |url| may - // end up being modified to contain the _real_ url being loaded if the - // parameter was an alias (such as about: urls and chrome- urls). - static TabContentsType TypeForURL(GURL* url); - - // This method can be used to register a new TabContents type dynamically, - // which can be very useful for unit testing. If factory is null, then the - // tab contents type is unregistered. Returns the previously registered - // factory for the given type or null if there was none. - static TabContentsFactory* RegisterFactory(TabContentsType type, - TabContentsFactory* factory); - - // Creation & destruction ---------------------------------------------------- - - // Request this tab to shut down. This kills the tab's NavigationController, - // which then Destroy()s all tabs it controls. - void CloseContents(); - - // Unregister/shut down any pending tasks involving this tab. - // This is called as the tab is shutting down, before the - // NavigationController (and consequently profile) are gone. - // - // If you override this, be sure to call this implementation at the end - // of yours. - // See also Close(). - virtual void Destroy(); - - // Intrinsic tab state ------------------------------------------------------- - - // Returns the type of tab this is. See also the As* functions following. - TabContentsType type() const { return type_; } - - // 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_; } - - // Returns this object as a WebContents if it is one, and NULL otherwise. - virtual WebContents* AsWebContents() { return NULL; } - - // Const version of above for situations where const TabContents*'s are used. - WebContents* AsWebContents() const { - return const_cast(this)->AsWebContents(); - } - - // Returns this object as a DOMUIHost if it is one, and NULL otherwise. - virtual DOMUIHost* AsDOMUIHost() { return NULL; } - - TabContentsDelegate* delegate() const { return delegate_; } - void set_delegate(TabContentsDelegate* d) { delegate_ = d; } - - // This can only be null if the TabContents has been created but - // SetupController has not been called. The controller should always outlive - // its TabContents. - NavigationController* controller() const { return controller_; } - void set_controller(NavigationController* c) { controller_ = c; } - - // Sets up a new NavigationController for this TabContents. - // |profile| is the user profile that should be associated with - // the new controller. - // - // TODO(brettw) this seems bogus and I couldn't find any legitimate need for - // it. I think it should be passed in the constructor. - void SetupController(Profile* profile); - - // Returns the user profile associated with this TabContents (via the - // NavigationController). This will return NULL if there isn't yet a - // NavigationController on this TabContents. - // TODO(darin): make it so that controller_ can never be null - Profile* profile() const { - return controller_ ? controller_->profile() : NULL; - } - - // Returns whether this tab contents supports the provided URL. By default, - // this method matches the tab contents type with the result of TypeForURL(). - // |url| points to the actual URL that will be used. It can be modified as - // needed. - // Override this method if your TabContents subclass supports various URL - // schemes but doesn't want to be the default handler for these schemes. - // For example, the NewTabUIContents overrides this method to support - // javascript: URLs. - virtual bool SupportsURL(GURL* url); - - // 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). - const GURL& GetURL() const; - virtual const std::wstring& GetTitle() const; - - // 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 - // WebContents, 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. WebContents overrides this to provide proper - // access to its site instance. - virtual SiteInstance* GetSiteInstance() const { return NULL; } - - // Initial title assigned to NavigationEntries from Navigate. - virtual const std::wstring GetDefaultTitle() 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() { return true; } - - // 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. - virtual SkBitmap GetFavIcon() 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() { return true; } - - // SSL related states. - SecurityStyle GetSecurityStyle() const; - - // Sets |ev_text| to the text that should be displayed in the EV label of - // the location bar and |ev_tooltip_text| to the tooltip for that label. - // Returns false and sets these strings to empty if the current page is either - // not served over HTTPS or if HTTPS does not use an EV cert. - bool GetSSLEVText(std::wstring* ev_text, std::wstring* ev_tooltip_text) const; - - // Returns a human-readable description the tab's loading state. - virtual std::wstring GetStatusText() const { return std::wstring(); } - - // 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_; } - - // 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 is_crashed_; } - void SetIsCrashed(bool state); - - // Set whether this tab contents is active. A tab content is active for a - // given tab if it is currently being used to display some contents. Note that - // this is different from whether a tab is selected. - bool is_active() const { return is_active_; } - void set_is_active(bool active) { is_active_ = active; } - - // 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(); - - // 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. - virtual void Activate(); - - // 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(bool reload); - - // Stop any pending navigation. - virtual void Stop() {} - - // TODO(erg): HACK ALERT! This was thrown together for beta and - // needs to be completely removed after we ship it. Right now, the - // cut/copy/paste menu items are always enabled and will send a - // cut/copy/paste command to the currently visible - // TabContents. Post-beta, this needs to be replaced with a unified - // interface for supporting cut/copy/paste, and managing who has - // cut/copy/paste focus. (http://b/1117225) - virtual void Cut() { } - virtual void Copy() { } - virtual void Paste() { } - - // Called on a TabContents when it isn't a popup, but a new window. - virtual void DisassociateFromPopupCount() { } - - // 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. The window - // is sized according to the preferred size of the content_view, and centered - // within the contents. - ConstrainedWindow* CreateConstrainedDialog( - views::WindowDelegate* window_delegate, - views::View* contents_view); - - // 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); - - // Builds a ConstrainedWindow* for the incoming |new_contents| and - // adds it to child_windows_. - void AddConstrainedPopup(TabContents* new_contents, - const gfx::Rect& initial_pos); - - // When a tab is closed, this method is called for all the remaining tabs. If - // they all return false or if no tabs are left, the window is closed. The - // default is to return true - virtual bool ShouldPreventWindowClose() { return true; } - - // Closes all constrained windows that represent web popups that have not yet - // been activated by the user and are as such auto-positioned in the bottom - // right of the screen. This is a quick way for users to "clean up" a flurry - // of unwanted popups. - void CloseAllSuppressedPopups(); - - // Called when the blocked popup notification is shown or hidden. - virtual void PopupNotificationVisibilityChanged(bool visible) { } - - // Views and focus ----------------------------------------------------------- - - // Returns the actual window that is focused when this TabContents is shown. - virtual HWND GetContentHWND() { - return GetContainerHWND(); - } - - // Tell the subclass to set up the view (e.g. create the container HWND if - // applicable) and any other create-time setup. - virtual void CreateView() {} - - // Returns the HWND associated with this TabContents. Outside of automation - // in the context of the UI, this is required to be implemented. - virtual HWND GetContainerHWND() const { return NULL; } - - // Returns the bounds of this TabContents in the screen coordinate system. - virtual void GetContainerBounds(gfx::Rect *out) const { - out->SetRect(0, 0, 0, 0); - } - - // Make the tab the focused window. - virtual void Focus(); - - // Stores the currently focused view. - virtual void StoreFocus(); - - // Restores focus to the last focus view. If StoreFocus has not yet been - // invoked, SetInitialFocus is invoked. - virtual void RestoreFocus(); - - // Invoked the first time this tab is getting the focus through TAB traversal. - // By default this does nothing, but is overridden to set the focus for the - // first element in the page. - // - // |reverse| indicates if the user is going forward or backward, so we know - // whether to set the first or last element focus. - // - // See also SetInitialFocus(no arg). - // FIXME(brettw) having two SetInitialFocus that do different things is silly. - virtual void SetInitialFocus(bool reverse) { } - - // TabContents that contain View hierarchy (such as NativeUIContents) should - // return their RootView. Other TabContents (such as WebContents) should - // return NULL. - // This is used by the focus manager to figure out what to focus when the tab - // is focused (when a tab with no view hierarchy is focused, the - // TabContentsContainerView is focused) and how to process tab events. If - // this returns NULL, the TabContents is supposed to know how to process TAB - // key events and is just sent the key messages. If this returns a RootView, - // the focus is passed to the RootView. - virtual views::RootView* GetContentsRootView() { return NULL; } - - // Infobars ------------------------------------------------------------------ - - // Adds an InfoBar for the specified |delegate|. - void AddInfoBar(InfoBarDelegate* delegate); - - // Removes the InfoBar for the specified |delegate|. - void RemoveInfoBar(InfoBarDelegate* delegate); - - // Enumeration and access functions. - int infobar_delegate_count() const { return infobar_delegates_.size(); } - InfoBarDelegate* GetInfoBarDelegateAt(int index) { - return infobar_delegates_.at(index); - } - - // Toolbars and such --------------------------------------------------------- - - // Returns whether the bookmark bar should be visible. - virtual bool IsBookmarkBarAlwaysVisible() { return false; } - - // Whether or not the shelf view is visible. - virtual void SetDownloadShelfVisible(bool visible); - bool IsDownloadShelfVisible() { return shelf_visible_; } - - // Notify our delegate that some of our content has animated. - void ToolbarSizeChanged(bool is_animating); - - // Displays the download shelf and animation when a download occurs. - void OnStartDownload(DownloadItem* download); - - // Returns the DownloadShelfView, creating it if necessary. - DownloadShelfView* GetDownloadShelfView(); - - // Transfer the shelf view from |tab_contents| to the receiving TabContents. - // |tab_contents| no longer owns the shelf after this call. The shelf is owned - // by the receiving TabContents. - void MigrateShelfViewFrom(TabContents* tab_contents); - - // Migrate the shelf view between 2 TabContents. This helper function is - // currently called by NavigationController::DiscardPendingEntry. We may - // want to generalize this if we need to migrate some other state. - static void MigrateShelfView(TabContents* from, TabContents* to); - - // Called when a ConstrainedWindow we own is about to be closed. - void WillClose(ConstrainedWindow* window); - - // Called when a ConstrainedWindow we own is moved or resized. - void DidMoveOrResize(ConstrainedWindow* window); - - protected: - // NotificationObserver implementation: - virtual void Observe(NotificationType type, - const NotificationSource& source, - const NotificationDetails& details); - - friend class NavigationController; - // Used to access the child_windows_ (ConstrainedWindowList) for testing - // automation purposes. - friend class AutomationProvider; - - explicit TabContents(TabContentsType type); - - // Some tab contents types need to override the type. - void set_type(TabContentsType type) { type_ = type; } - - // NOTE: the TabContents destructor can run after the NavigationController - // has gone away, so any complicated unregistering that expects the profile - // or other shared objects to still be around does not belong in a - // destructor. - // For those purposes, instead see Destroy(). - // Protected so that others don't try to delete this directly. - virtual ~TabContents(); - - // Sets focus to the tab contents window, but doesn't actuall set focus to - // a particular element in it (see also SetInitialFocus(bool) which does - // that in different circumstances). - // FIXME(brettw) having two SetInitialFocus that do different things is silly. - virtual void SetInitialFocus(); - - // 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. - virtual void SetIsLoading(bool is_loading, LoadNotificationDetails* details); - - // Called by a derived class when the TabContents is resized, causing - // suppressed constrained web popups to be repositioned to the new bounds - // if necessary. - void RepositionSupressedPopupsToFit(const gfx::Size& new_size); - - // Releases the download shelf. This method is used by MigrateShelfViewFrom. - // Sub-classes should clear any pointer they might keep to the shelf view and - // invoke TabContents::ReleaseDownloadShelfView(). - virtual void ReleaseDownloadShelfView(); - - // 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; } - - typedef std::vector ConstrainedWindowList; - ConstrainedWindowList child_windows_; - - // Whether we have a notification AND the notification owns popups windows. - // (We keep the notification object around even when it's not shown since it - // determines whether to show itself). - bool ShowingBlockedPopupNotification() const; - - private: - // 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); - - // Data ---------------------------------------------------------------------- - - TabContentsType type_; - - TabContentsDelegate* delegate_; - NavigationController* controller_; - - PropertyBag property_bag_; - - NotificationRegistrar registrar_; - - // Indicates whether we're currently loading a resource. - bool is_loading_; - - // See is_active() getter above. - bool is_active_; - - bool is_crashed_; // true if the tab is considered crashed. - - // See waiting_for_response() above. - bool waiting_for_response_; - - // The download shelf view (view at the bottom of the page). - scoped_ptr download_shelf_view_; - - // Whether the shelf view is visible. - bool shelf_visible_; - - // Indicates the largest PageID we've seen. This field is ignored if we are - // a WebContents, in which case the max page ID is stored separately with - // each SiteInstance. - int32 max_page_id_; - - // The id used in the ViewStorage to store the last focused view. - int last_focused_view_storage_id_; - - // See capturing_contents() above. - bool capturing_contents_; - - // ConstrainedWindow with additional methods for managing blocked - // popups. This pointer alsog goes in |child_windows_| for ownership, - // repositioning, etc. - BlockedPopupContainer* blocked_popups_; - - // Delegates for InfoBars associated with this TabContents. - std::vector infobar_delegates_; - - // See getter above. - bool is_being_destroyed_; - - DISALLOW_COPY_AND_ASSIGN(TabContents); -}; - -#endif // CHROME_BROWSER_TAB_CONTENTS_H_ diff --git a/chrome/browser/tab_contents/about_internets_status_view.cc b/chrome/browser/tab_contents/about_internets_status_view.cc new file mode 100644 index 0000000..46cf931 --- /dev/null +++ b/chrome/browser/tab_contents/about_internets_status_view.cc @@ -0,0 +1,69 @@ +// 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 "base/file_util.h" +#include "base/path_service.h" +#include "base/string_util.h" +#include "chrome/browser/tab_contents/about_internets_status_view.h" +#include "chrome/browser/tab_contents/tab_contents_delegate.h" + +AboutInternetsStatusView::AboutInternetsStatusView() + : StatusView(TAB_CONTENTS_ABOUT_INTERNETS_STATUS_VIEW) {} + +AboutInternetsStatusView::~AboutInternetsStatusView() { + if (process_handle_.IsValid()) + TerminateProcess(process_handle_.Get(), 0); +} + +const std::wstring AboutInternetsStatusView::GetDefaultTitle() const { + return L"Don't Clog the Tubes!"; +} + +const std::wstring& AboutInternetsStatusView::GetTitle() const { + return title_; +} + +void AboutInternetsStatusView::OnCreate(const CRect& rect) { + HWND contents_hwnd = GetContainerHWND(); + STARTUPINFO startup_info; + memset(&startup_info, 0, sizeof(startup_info)); + startup_info.cb = sizeof(startup_info); + PROCESS_INFORMATION process_info = {0}; + + std::wstring path; + PathService::Get(base::DIR_SYSTEM, &path); + file_util::AppendToPath(&path, L"sspipes.scr"); + std::wstring parameters; + parameters.append(path.c_str()); + // Append the handle of the HWND that we want to render the pipes into. + parameters.append(L" /p "); + parameters.append( + Int64ToWString(reinterpret_cast(contents_hwnd)).c_str()); + BOOL result = + CreateProcess(NULL, + const_cast(parameters.c_str()), + NULL, // LPSECURITY_ATTRIBUTES lpProcessAttributes + NULL, // LPSECURITY_ATTRIBUTES lpThreadAttributes + FALSE, // BOOL bInheritHandles + CREATE_DEFAULT_ERROR_MODE, // DWORD dwCreationFlags + NULL, // LPVOID lpEnvironment + NULL, // LPCTSTR lpCurrentDirectory + &startup_info, // LPstartup_info lpstartup_info + &process_info); // LPPROCESS_INFORMATION + // lpProcessInformation + + if (result) { + title_ = GetDefaultTitle(); + CloseHandle(process_info.hThread); + process_handle_.Set(process_info.hProcess); + } else { + title_ = L"The Tubes are Clogged!"; + } +} + +void AboutInternetsStatusView::OnSize(const CRect& rect) { + // We're required to implement this because it is abstract, but we don't + // actually have anything to do right here. +} + diff --git a/chrome/browser/tab_contents/about_internets_status_view.h b/chrome/browser/tab_contents/about_internets_status_view.h new file mode 100644 index 0000000..5d7498e --- /dev/null +++ b/chrome/browser/tab_contents/about_internets_status_view.h @@ -0,0 +1,45 @@ +// 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. + +#ifndef CHROME_BROWSER_ABOUT_INTERNETS_STATUS_VIEW_H__ +#define CHROME_BROWSER_ABOUT_INTERNETS_STATUS_VIEW_H__ + +#include "base/scoped_handle.h" +#include "chrome/browser/tab_contents/status_view.h" + +// Displays sspipes.scr in the content HWND. +class AboutInternetsStatusView : public StatusView { + public: + AboutInternetsStatusView(); + virtual ~AboutInternetsStatusView(); + + // TabContents overrides + virtual const std::wstring GetDefaultTitle() const; + virtual const std::wstring& GetTitle() const; + + // StatusView implementations + + // Starts sspipes.scr rendering into the contents HWND. (Actually, it looks + // like this creates a child HWND which is the same size as the contents, + // and draws into that. Thus, it doesn't resize properly.) + // TODO(devint): Fix this resizing issue. A few possibilities: + // 1) Restart the process a few seconds after a resize is completed. + // 2) Render into an invisible HWND and stretchblt to the current HWND. + virtual void OnCreate(const CRect& rect); + // Does nothing, but implementation is required by StatusView. + virtual void OnSize(const CRect& rect); + + private: + // Information about the pipes process, used to close the process when this + // view is destroyed. + ScopedHandle process_handle_; + + // Title of the page. + std::wstring title_; + + DISALLOW_EVIL_CONSTRUCTORS(AboutInternetsStatusView); +}; + +#endif // CHROME_BROWSER_ABOUT_INTERNETS_STATUS_VIEW_H__ + diff --git a/chrome/browser/tab_contents/constrained_window.h b/chrome/browser/tab_contents/constrained_window.h new file mode 100644 index 0000000..d703ad2 --- /dev/null +++ b/chrome/browser/tab_contents/constrained_window.h @@ -0,0 +1,68 @@ +// 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. + +#ifndef CHROME_BROWSER_CONSTRAINED_WINDOW_H__ +#define CHROME_BROWSER_CONSTRAINED_WINDOW_H__ + +#include "chrome/common/page_transition_types.h" +#include "webkit/glue/window_open_disposition.h" + +class ConstrainedWindow; +namespace views { +class View; +class WindowDelegate; +} +namespace gfx { +class Point; +class Rect; +} +class GURL; +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 views::View subclass + // that provides the client area. Typical uses include the HTTP Basic Auth + // prompt. The caller must provide an object implementing + // views::WindowDelegate so that the Constrained Window can be properly + // configured. If |initial_bounds| is empty, the dialog will be centered + // within the constraining TabContents. + static ConstrainedWindow* CreateConstrainedDialog( + TabContents* owner, + const gfx::Rect& initial_bounds, + views::View* contents_view, + views::WindowDelegate* window_delegate); + + // Closes the Constrained Window. + virtual void CloseConstrainedWindow() = 0; + + // Repositions the Constrained Window so that the lower right corner + // of the titlebar is at the passed in |anchor_point|. + virtual void RepositionConstrainedWindowTo( + const gfx::Point& anchor_point) = 0; + + // Tells the Constrained Window that the constraining TabContents was hidden, + // e.g. via a tab switch. + virtual void WasHidden() = 0; + + // Tells the Constrained Window that the constraining TabContents became + // visible, e.g. via a tab switch. + virtual void DidBecomeSelected() = 0; + + // Returns the title of the Constrained Window. + virtual std::wstring GetWindowTitle() const = 0; + + // Returns the current display rectangle (relative to its + // parent). This method is only called from the unit tests to check + // the location/size of a constrained window. + virtual const gfx::Rect& GetCurrentBounds() const = 0; +}; + +#endif // #ifndef CHROME_BROWSER_CONSTRAINED_WINDOW_H__ diff --git a/chrome/browser/tab_contents/infobar_delegate.cc b/chrome/browser/tab_contents/infobar_delegate.cc new file mode 100644 index 0000000..eaeb013 --- /dev/null +++ b/chrome/browser/tab_contents/infobar_delegate.cc @@ -0,0 +1,93 @@ +// 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/infobar_delegate.h" + +#include "base/logging.h" +#include "chrome/browser/tab_contents/navigation_entry.h" +#include "chrome/browser/tab_contents/navigation_controller.h" +#include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/common/l10n_util.h" + +#include "generated_resources.h" + +// InfoBarDelegate: ------------------------------------------------------------ + +bool InfoBarDelegate::ShouldExpire( + const NavigationController::LoadCommittedDetails& details) const { + bool is_reload = + PageTransition::StripQualifier(details.entry->transition_type()) == + PageTransition::RELOAD; + return is_reload || (contents_unique_id_ != details.entry->unique_id()); +} + +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; +} + +// AlertInfoBarDelegate: ------------------------------------------------------- + +bool AlertInfoBarDelegate::EqualsDelegate(InfoBarDelegate* delegate) const { + AlertInfoBarDelegate* alert_delegate = delegate->AsAlertInfoBarDelegate(); + if (!alert_delegate) + return false; + + return alert_delegate->GetMessageText() == GetMessageText(); +} + +AlertInfoBarDelegate::AlertInfoBarDelegate(TabContents* contents) + : InfoBarDelegate(contents) { +} + +// LinkInfoBarDelegate: -------------------------------------------------------- + +LinkInfoBarDelegate::LinkInfoBarDelegate(TabContents* contents) + : InfoBarDelegate(contents) { +} + +// ConfirmInfoBarDelegate: ----------------------------------------------------- + +std::wstring ConfirmInfoBarDelegate::GetButtonLabel( + InfoBarButton button) const { + if (button == BUTTON_OK) + return l10n_util::GetString(IDS_OK); + if (button == BUTTON_CANCEL) + return l10n_util::GetString(IDS_CANCEL); + NOTREACHED(); + return std::wstring(); +} + +ConfirmInfoBarDelegate::ConfirmInfoBarDelegate(TabContents* contents) + : AlertInfoBarDelegate(contents) { +} + +// SimpleAlertInfoBarDelegate: ------------------------------------------------- + +SimpleAlertInfoBarDelegate::SimpleAlertInfoBarDelegate( + TabContents* contents, + const std::wstring& message, + SkBitmap* icon) + : AlertInfoBarDelegate(contents), + message_(message), + icon_(icon) { +} + +std::wstring SimpleAlertInfoBarDelegate::GetMessageText() const { + return message_; +} + +SkBitmap* SimpleAlertInfoBarDelegate::GetIcon() const { + return icon_; +} + +void SimpleAlertInfoBarDelegate::InfoBarClosed() { + delete this; +} diff --git a/chrome/browser/tab_contents/infobar_delegate.h b/chrome/browser/tab_contents/infobar_delegate.h new file mode 100644 index 0000000..07f225b --- /dev/null +++ b/chrome/browser/tab_contents/infobar_delegate.h @@ -0,0 +1,206 @@ +// 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. + +#ifndef CHROME_BROWSER_INFOBAR_DELEGATE_H_ +#define CHROME_BROWSER_INFOBAR_DELEGATE_H_ + +#include + +#include "base/basictypes.h" +#include "chrome/browser/tab_contents/navigation_controller.h" +#include "skia/include/SkBitmap.h" + +class AlertInfoBarDelegate; +class ConfirmInfoBarDelegate; +class InfoBar; +class LinkInfoBarDelegate; + +// 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 +// AlertInfoBarDelegate or ConfirmInfoBarDelegate, or override with your own +// delegate for your own InfoBar variety. +class InfoBarDelegate { + public: + // 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 { + return false; + } + + // 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 after the InfoBar is closed. The delegate is free to delete itself + // at this point. + virtual void InfoBarClosed() {} + + // Called to create the InfoBar. Implementation of this method is + // platform-specific. + virtual InfoBar* CreateInfoBar() = 0; + + // Returns a pointer to the AlertInfoBarDelegate interface, if implemented. + virtual AlertInfoBarDelegate* AsAlertInfoBarDelegate() { + return NULL; + } + + // Returns a pointer to the LinkInfoBarDelegate interface, if implemented. + virtual LinkInfoBarDelegate* AsLinkInfoBarDelegate() { + return NULL; + } + + // Returns a pointer to the ConfirmInfoBarDelegate interface, if implemented. + virtual ConfirmInfoBarDelegate* AsConfirmInfoBarDelegate() { + return NULL; + } + + 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 taht we were + // opened for. Used to help expire on navigations. + int contents_unique_id_; + + DISALLOW_COPY_AND_ASSIGN(InfoBarDelegate); +}; + +// An interface derived from InfoBarDelegate implemented by objects wishing to +// control an AlertInfoBar. +class AlertInfoBarDelegate : public InfoBarDelegate { + public: + // Returns the message string to be displayed for the InfoBar. + virtual std::wstring GetMessageText() const = 0; + + // Return the icon to be shown for this InfoBar. If the returned bitmap is + // NULL, no icon is shown. + virtual SkBitmap* GetIcon() const { return NULL; } + + // Overridden from InfoBarDelegate: + virtual bool EqualsDelegate(InfoBarDelegate* delegate) const; + virtual InfoBar* CreateInfoBar(); + virtual AlertInfoBarDelegate* AsAlertInfoBarDelegate() { return this; } + + protected: + explicit AlertInfoBarDelegate(TabContents* contents); + + DISALLOW_COPY_AND_ASSIGN(AlertInfoBarDelegate); +}; + +// An interface derived from InfoBarDelegate implemented by objects wishing to +// control a LinkInfoBar. +class LinkInfoBarDelegate : public InfoBarDelegate { + public: + // Returns the message string to be displayed in the InfoBar. |link_offset| + // is the position where the link should be inserted. If |link_offset| is set + // to std::wstring::npos (it is by default), the link is right aligned within + // the InfoBar rather than being embedded in the message text. + virtual std::wstring GetMessageTextWithOffset(size_t* link_offset) const { + *link_offset = std::wstring::npos; + return std::wstring(); + } + + // Returns the text of the link to be displayed. + virtual std::wstring GetLinkText() const = 0; + + // Returns the icon that should be shown for this InfoBar, or NULL if there is + // none. + virtual SkBitmap* GetIcon() const { return NULL; } + + // Called when the Link is clicked. The |disposition| specifies how the + // resulting document should be loaded (based on the event flags present when + // the link was clicked). This function returns true if the InfoBar should be + // closed now or false if it should remain until the user explicitly closes + // it. + virtual bool LinkClicked(WindowOpenDisposition disposition) { + return true; + } + + // Overridden from InfoBarDelegate: + virtual InfoBar* CreateInfoBar(); + virtual LinkInfoBarDelegate* AsLinkInfoBarDelegate() { + return this; + } + + protected: + explicit LinkInfoBarDelegate(TabContents* contents); + + DISALLOW_COPY_AND_ASSIGN(LinkInfoBarDelegate); +}; + +// An interface derived from InfoBarDelegate implemented by objects wishing to +// control a ConfirmInfoBar. +class ConfirmInfoBarDelegate : public AlertInfoBarDelegate { + public: + enum InfoBarButton { + BUTTON_NONE = 0, + BUTTON_OK, + BUTTON_CANCEL + }; + + // Return the buttons to be shown for this InfoBar. + virtual int GetButtons() const { + return BUTTON_NONE; + } + + // Return the label for the specified button. The default implementation + // returns "OK" for the OK button and "Cancel" for the Cancel button. + virtual std::wstring GetButtonLabel(InfoBarButton button) const; + + // Called when the OK button is pressed. If the function returns true, the + // InfoBarDelegate should be removed from the associated TabContents. + virtual bool Accept() { return true; } + + // Called when the Cancel button is pressed. If the function returns true, + // the InfoBarDelegate should be removed from the associated TabContents. + virtual bool Cancel() { return true; } + + // Overridden from InfoBarDelegate: + virtual InfoBar* CreateInfoBar(); + virtual ConfirmInfoBarDelegate* AsConfirmInfoBarDelegate() { + return this; + } + + protected: + explicit ConfirmInfoBarDelegate(TabContents* contents); + + DISALLOW_COPY_AND_ASSIGN(ConfirmInfoBarDelegate); +}; + +// Simple implementations for common use cases --------------------------------- + +class SimpleAlertInfoBarDelegate : public AlertInfoBarDelegate { + public: + SimpleAlertInfoBarDelegate(TabContents* contents, + const std::wstring& message, + SkBitmap* icon); + + // Overridden from AlertInfoBarDelegate: + virtual std::wstring GetMessageText() const; + virtual SkBitmap* GetIcon() const; + virtual void InfoBarClosed(); + + private: + std::wstring message_; + SkBitmap* icon_; + + DISALLOW_COPY_AND_ASSIGN(SimpleAlertInfoBarDelegate); +}; + +#endif // #ifndef CHROME_BROWSER_INFOBAR_DELEGATE_H_ diff --git a/chrome/browser/tab_contents/interstitial_page.cc b/chrome/browser/tab_contents/interstitial_page.cc new file mode 100644 index 0000000..ca0f226 --- /dev/null +++ b/chrome/browser/tab_contents/interstitial_page.cc @@ -0,0 +1,362 @@ +// 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/interstitial_page.h" + +#include "chrome/browser/browser.h" +#include "chrome/browser/browser_list.h" +#include "chrome/browser/browser_resources.h" +#include "chrome/browser/dom_operation_notification_details.h" +#include "chrome/browser/render_widget_host_view_win.h" +#include "chrome/browser/tab_contents/navigation_controller.h" +#include "chrome/browser/tab_contents/navigation_entry.h" +#include "chrome/browser/tab_contents/web_contents.h" +#include "chrome/browser/tab_contents/web_contents_view_win.h" +#include "chrome/views/window.h" +#include "chrome/views/window_delegate.h" +#include "net/base/escape.h" + +enum ResourceRequestAction { + BLOCK, + RESUME, + CANCEL +}; + +namespace { + +class ResourceRequestTask : public Task { + public: + ResourceRequestTask(RenderViewHost* render_view_host, + ResourceRequestAction action) + : action_(action), + process_id_(render_view_host->process()->host_id()), + render_view_host_id_(render_view_host->routing_id()), + resource_dispatcher_host_( + g_browser_process->resource_dispatcher_host()) { + } + + virtual void Run() { + switch (action_) { + case BLOCK: + resource_dispatcher_host_->BlockRequestsForRenderView( + process_id_, render_view_host_id_); + break; + case RESUME: + resource_dispatcher_host_->ResumeBlockedRequestsForRenderView( + process_id_, render_view_host_id_); + break; + case CANCEL: + resource_dispatcher_host_->CancelBlockedRequestsForRenderView( + 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 + +// static +InterstitialPage::InterstitialPageMap* + InterstitialPage::tab_to_interstitial_page_ = NULL; + +InterstitialPage::InterstitialPage(WebContents* tab, + bool new_navigation, + const GURL& url) + : tab_(tab), + url_(url), + action_taken_(false), + enabled_(true), + new_navigation_(new_navigation), + render_view_host_(NULL), + should_revert_tab_title_(false), + ui_loop_(MessageLoop::current()) { + 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()->GetPendingEntry()); +} + +InterstitialPage::~InterstitialPage() { + InterstitialPageMap::iterator iter = tab_to_interstitial_page_->find(tab_); + DCHECK(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, close it before showing the new one. + if (tab_->interstitial_page()) + tab_->interstitial_page()->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, NOTIFY_RENDER_WIDGET_HOST_DESTROYED, + Source(tab_->render_view_host())); + + // Update the tab_to_interstitial_page_ map. + InterstitialPageMap::const_iterator 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(TAB_CONTENTS_WEB); + entry->set_url(url_); + entry->set_display_url(url_); + entry->set_page_type(NavigationEntry::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(); + + std::string data_url = "data:text/html;charset=utf-8," + + EscapePath(GetHTMLContents()); + render_view_host_->NavigateToURL(GURL(data_url)); + + notification_registrar_.Add(this, NOTIFY_TAB_CONTENTS_DESTROYED, + Source(tab_)); + notification_registrar_.Add(this, NOTIFY_NAV_ENTRY_COMMITTED, + Source(tab_->controller())); + notification_registrar_.Add(this, NOTIFY_NAV_ENTRY_PENDING, + Source(tab_->controller())); +} + +void InterstitialPage::Hide() { + 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(original_tab_title_); + tab_->NotifyNavigationStateChanged(TabContents::INVALIDATE_TITLE); + } + delete this; +} + +void InterstitialPage::Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details) { + switch (type) { + case NOTIFY_NAV_ENTRY_PENDING: + // We are navigating away from the interstitial. Make sure clicking on + // the interstitial will have no effect. + Disable(); + break; + case NOTIFY_RENDER_WIDGET_HOST_DESTROYED: + if (!action_taken_) { + // The RenderViewHost is being destroyed (as part of the tab being + // closed), make sure we clear the blocked requests. + DCHECK(Source(source).ptr() == + tab_->render_view_host()); + TakeActionOnResourceDispatcher(CANCEL); + } + break; + case NOTIFY_TAB_CONTENTS_DESTROYED: + case NOTIFY_NAV_ENTRY_COMMITTED: + if (!action_taken_) { + // 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(); + } +} + +RenderViewHost* InterstitialPage::CreateRenderViewHost() { + RenderViewHost* render_view_host = new RenderViewHost( + SiteInstance::CreateSiteInstance(tab()->profile()), + this, MSG_ROUTING_NONE, NULL); + RenderWidgetHostViewWin* view = + new RenderWidgetHostViewWin(render_view_host); + render_view_host->set_view(view); + view->Create(tab_->GetContentHWND()); + view->set_parent_hwnd(tab_->GetContentHWND()); + WebContentsViewWin* web_contents_view = + static_cast(tab_->view()); + render_view_host->CreateRenderView(); + // SetSize must be called after CreateRenderView or the HWND won't show. + view->SetSize(web_contents_view->GetContainerSize()); + + render_view_host->AllowDomAutomationBindings(); + return render_view_host; +} + +void InterstitialPage::Proceed() { + DCHECK(!action_taken_); + Disable(); + action_taken_ = true; + + // 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! + } +} + +void InterstitialPage::DontProceed() { + DCHECK(!action_taken_); + Disable(); + action_taken_ = true; + + // 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 (new_navigation_) { + // 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(); + } + + Hide(); + // WARNING: we are now deleted! +} + +void InterstitialPage::SetSize(const gfx::Size& size) { + render_view_host_->view()->SetSize(size); +} + +Profile* InterstitialPage::GetProfile() const { + return tab_->profile(); +} + +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); + + // 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::RendererGone(RenderViewHost* render_view_host) { + // Our renderer died. This should not happen in normal cases. + // Just dismiss the interstitial. + DontProceed(); +} + +void InterstitialPage::DomOperationResponse(const std::string& json_string, + int automation_id) { + if (enabled_) + CommandReceived(json_string); +} + +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 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_ = entry->title(); + should_revert_tab_title_ = true; + } + entry->set_title(title); + tab_->NotifyNavigationStateChanged(TabContents::INVALIDATE_TITLE); +} + +void InterstitialPage::Disable() { + enabled_ = false; +} + +void InterstitialPage::TakeActionOnResourceDispatcher( + ResourceRequestAction action) { + DCHECK(MessageLoop::current() == ui_loop_) << + "TakeActionOnResourceDispatcher should be called on the main thread."; + // 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 an IO thread, as when unit-tests we don't + // have one. + if (tab_->render_view_host() && g_browser_process->io_thread()) { + g_browser_process->io_thread()->message_loop()->PostTask( + FROM_HERE, new ResourceRequestTask(tab_->render_view_host(), action)); + } +} + +// static +void InterstitialPage::InitInterstitialPageMap() { + if (!tab_to_interstitial_page_) + tab_to_interstitial_page_ = new InterstitialPageMap; +} + +// static +InterstitialPage* InterstitialPage::GetInterstitialPage( + WebContents* web_contents) { + InitInterstitialPageMap(); + InterstitialPageMap::const_iterator iter = + tab_to_interstitial_page_->find(web_contents); + if (iter == tab_to_interstitial_page_->end()) + return NULL; + + return iter->second; +} diff --git a/chrome/browser/tab_contents/interstitial_page.h b/chrome/browser/tab_contents/interstitial_page.h new file mode 100644 index 0000000..6c2c76f5 --- /dev/null +++ b/chrome/browser/tab_contents/interstitial_page.h @@ -0,0 +1,168 @@ +// 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. + +#ifndef CHROME_BROWSER_INTERSTITIAL_PAGE_H_ +#define CHROME_BROWSER_INTERSTITIAL_PAGE_H_ + +#include + +#include "chrome/browser/render_view_host_delegate.h" +#include "chrome/common/notification_registrar.h" +#include "googleurl/src/gurl.h" + +class NavigationEntry; +class WebContents; + +// 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 WebContents closing them or the tab containing them +// being closed. + +enum ResourceRequestAction; + +class InterstitialPage : public NotificationObserver, + public RenderViewHostDelegate { + public: + // 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(WebContents* 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(WebContents* web_contents); + + // Sub-classes should return the HTML that should be displayed in the page. + virtual std::string GetHTMLContents() { return std::string(); } + + // 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: 'this' has been 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(); + + // Sizes the RenderViewHost showing the actual interstitial page contents. + void SetSize(const gfx::Size& size); + + protected: + // NotificationObserver method: + virtual void Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details); + + // RenderViewHostDelegate implementation: + virtual Profile* GetProfile() const; + virtual WebPreferences GetWebkitPrefs() { + return WebPreferences(); + } + virtual void DidNavigate(RenderViewHost* render_view_host, + const ViewHostMsg_FrameNavigate_Params& params); + virtual void RendererGone(RenderViewHost* render_view_host); + virtual void DomOperationResponse(const std::string& json_string, + int automation_id); + virtual void UpdateTitle(RenderViewHost* render_view_host, + int32 page_id, + const std::wstring& title); + + // 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) { } + + WebContents* tab() const { return tab_; } + const GURL& url() const { return url_; } + RenderViewHost* render_view_host() const { return render_view_host_; } + + // Creates and shows the RenderViewHost containing the interstitial content. + // Overriden in unit tests. + virtual RenderViewHost* CreateRenderViewHost(); + + private: + // AutomationProvider needs access to Proceed and DontProceed to simulate + // user actions. + friend class AutomationProvider; + + // 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. + WebContents* 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 this interstitial is enabled. See Disable() for more info. + bool enabled_; + + // Whether the Proceed or DontProceed have been called yet. + bool action_taken_; + + // Notification magic. + NotificationRegistrar notification_registrar_; + + // The RenderViewHost displaying the interstitial contents. + RenderViewHost* render_view_host_; + + // 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_; + + // The original title of the tab that should be reverted to when the + // interstitial is hidden. + std::wstring original_tab_title_; + + MessageLoop* ui_loop_; + + // We keep a map of the various blocking pages shown as the UI tests need to + // be able to retrieve them. + typedef std::map InterstitialPageMap; + static InterstitialPageMap* tab_to_interstitial_page_; + + DISALLOW_COPY_AND_ASSIGN(InterstitialPage); +}; + +#endif // #ifndef CHROME_BROWSER_INTERSTITIAL_PAGE_H_ + diff --git a/chrome/browser/tab_contents/ipc_status_view.cc b/chrome/browser/tab_contents/ipc_status_view.cc new file mode 100644 index 0000000..1385898 --- /dev/null +++ b/chrome/browser/tab_contents/ipc_status_view.cc @@ -0,0 +1,370 @@ +// 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/ipc_status_view.h" + +#include + +#include "base/logging.h" +#include "base/string_util.h" +#include "chrome/app/chrome_dll_resource.h" +#include "chrome/common/chrome_constants.h" +#include "chrome/common/ipc_logging.h" +#include "chrome/common/plugin_messages.h" +#include "chrome/common/pref_names.h" +#include "chrome/common/pref_service.h" +#include "chrome/common/render_messages.h" + +#ifdef IPC_MESSAGE_LOG_ENABLED + +using base::Time; + +namespace { +const wchar_t kTitleMsg[] = L"IPC Messages"; + +const wchar_t kStartLoggingMsg[] = L"Start IPC Logging"; +const wchar_t kStopLoggingMsg[] = L"Stop IPC Logging"; +const wchar_t kClearMsg[] = L"Clear"; +const wchar_t kSettingsMsg[] = L"Filter"; + +enum { + kTimeColumn = 0, + kChannelColumn, + kMessageColumn, + kFlagsColumn, + kDispatchColumn, + kProcessColumn, + kParamsColumn, +}; + +// This class ensures that we have a link dependency on render_messages.cc and +// plugin_messages.cc, and at the same time sets up the message logger function +// mappings. +class RegisterLoggerFuncs { + public: + RegisterLoggerFuncs() { + RenderMessagesInit(); + PluginMessagesInit(); + } +}; + +RegisterLoggerFuncs g_register_logger_funcs; + +} // namespace + +IPCStatusView* IPCStatusView::current_; + +IPCStatusView::IPCStatusView() + : StatusView(TAB_CONTENTS_IPC_STATUS_VIEW) { + DCHECK(!current_); + current_ = this; + settings_dialog_ = NULL; + init_done_ = false; + view_ = NULL; + view_host_ = NULL; + plugin_ = NULL; + plugin_host_ = NULL; + npobject_ = NULL; + plugin_process_ = NULL; + plugin_process_host_ = NULL; + + IPC::Logging::current()->SetConsumer(this); +} + +IPCStatusView::~IPCStatusView() { + current_ = NULL; + IPC::Logging::current()->SetConsumer(NULL); + + if (settings_dialog_ != NULL) + ::DestroyWindow(settings_dialog_); +} + +const std::wstring IPCStatusView::GetDefaultTitle() { + return kTitleMsg; +} + +void IPCStatusView::SetActive(bool active) { + StatusView::set_is_active(active); + + if (!disabled_messages_.empty() || !active) + return; + + Profile* current_profile = profile(); + if (!current_profile) + return; + PrefService* prefs = current_profile->GetPrefs(); + if (prefs->IsPrefRegistered(prefs::kIpcDisabledMessages)) + return; + prefs->RegisterListPref(prefs::kIpcDisabledMessages); + const ListValue* list = prefs->GetList(prefs::kIpcDisabledMessages); + if (!list) + return; + for (ListValue::const_iterator itr = list->begin(); + itr != list->end(); + ++itr) { + if (!(*itr)->IsType(Value::TYPE_INTEGER)) + continue; + int value = 0; + if (!(*itr)->GetAsInteger(&value)) + continue; + disabled_messages_.insert(value); + } +} + +void IPCStatusView::OnCreate(const CRect& rect) { + CreateButton(IDC_START_LOGGING, kStartLoggingMsg); + CreateButton(IDC_STOP_LOGGING, kStopLoggingMsg); + CreateButton(IDC_CLEAR, kClearMsg); + CreateButton(IDC_SETTINGS, kSettingsMsg); + + // Initialize the list view for messages. + // Don't worry about the size, we'll resize when we get WM_SIZE + message_list_.Create(GetContainerHWND(), const_cast(rect), NULL, + WS_CHILD | WS_VISIBLE | LVS_SORTASCENDING); + message_list_.SetViewType(LVS_REPORT); + message_list_.SetExtendedListViewStyle(LVS_EX_FULLROWSELECT); + + int column_index = 0; + message_list_.InsertColumn(kTimeColumn, L"time", LVCFMT_LEFT, 80); + message_list_.InsertColumn(kChannelColumn, L"channel", LVCFMT_LEFT, 110); + message_list_.InsertColumn(kMessageColumn, L"message", LVCFMT_LEFT, 240); + message_list_.InsertColumn(kFlagsColumn, L"flags", LVCFMT_LEFT, 50); + message_list_.InsertColumn(kDispatchColumn, L"dispatch (ms)", LVCFMT_RIGHT, 80); + message_list_.InsertColumn(kProcessColumn, L"process (ms)", LVCFMT_RIGHT, 80); + message_list_.InsertColumn(kParamsColumn, L"parameters", LVCFMT_LEFT, 500); +} + +void IPCStatusView::Log(const IPC::LogData& data) { + if (disabled_messages_.find(data.type) != disabled_messages_.end()) + return; // Message type is filtered out. + + Time sent = Time::FromInternalValue(data.sent); + Time::Exploded exploded; + sent.LocalExplode(&exploded); + if (exploded.hour > 12) + exploded.hour -= 12; + + std::wstring sent_str = StringPrintf(L"%02d:%02d:%02d.%03d", + exploded.hour, exploded.minute, exploded.second, exploded.millisecond); + + int count = message_list_.GetItemCount(); + int index = message_list_.InsertItem(count, sent_str.c_str()); + + message_list_.SetItemText(index, kTimeColumn, sent_str.c_str()); + message_list_.SetItemText(index, kChannelColumn, data.channel.c_str()); + + std::wstring message_name; + IPC::Logging::GetMessageText(data.type, &message_name, NULL, NULL); + message_list_.SetItemText(index, kMessageColumn, message_name.c_str()); + message_list_.SetItemText(index, kFlagsColumn, data.flags.c_str()); + + int64 time_to_send = (Time::FromInternalValue(data.receive) - + sent).InMilliseconds(); + // time can go backwards by a few ms (see Time), don't show that. + time_to_send = std::max(static_cast(time_to_send), 0); + std::wstring temp = StringPrintf(L"%d", time_to_send); + message_list_.SetItemText(index, kDispatchColumn, temp.c_str()); + + int64 time_to_process = (Time::FromInternalValue(data.dispatch) - + Time::FromInternalValue(data.receive)).InMilliseconds(); + time_to_process = std::max(static_cast(time_to_process), 0); + temp = StringPrintf(L"%d", time_to_process); + message_list_.SetItemText(index, kProcessColumn, temp.c_str()); + + message_list_.SetItemText(index, kParamsColumn, data.params.c_str()); + message_list_.EnsureVisible(index, FALSE); +} + +void IPCStatusView::OnSize(const CRect& rect) { + message_list_.MoveWindow(rect); +} + +void IPCStatusView::OnStartLogging(UINT code, int button_id, HWND hwnd) { + IPC::Logging::current()->Enable(); +} + +void IPCStatusView::OnStopLogging(UINT code, int button_id, HWND hwnd) { + IPC::Logging::current()->Disable(); +} + +void IPCStatusView::OnClear(UINT code, int button_id, HWND hwnd) { + message_list_.DeleteAllItems(); +} + +INT_PTR CALLBACK IPCStatusView::DialogProc( + HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { + switch (msg) { + case WM_INITDIALOG: + current()->InitDialog(hwnd); + return FALSE; // Don't set keyboard focus. + case WM_SYSCOMMAND: + if (wparam == SC_CLOSE) { + current()->CloseDialog(); + return FALSE; + } + break; + case WM_NOTIFY: { + NMLISTVIEW* info = reinterpret_cast(lparam); + if ((wparam == IDC_View || wparam == IDC_ViewHost || wparam == IDC_Plugin || + wparam == IDC_PluginHost || wparam == IDC_NPObject || + wparam == IDC_PluginProcess || wparam == IDC_PluginProcessHost) && + info->hdr.code == LVN_ITEMCHANGED) { + if (info->uChanged & LVIF_STATE) { + bool checked = (info->uNewState >> 12) == 2; + current()->OnCheck(static_cast(info->lParam), checked); + } + return FALSE; + } + break; + } + case WM_COMMAND: + if (HIWORD(wparam) == BN_CLICKED) + current()->OnButtonClick(LOWORD(wparam)); + + break; + } + return FALSE; +} + +void IPCStatusView::InitDialog(HWND hwnd) { + CreateColumn(ViewStart, ViewEnd, ::GetDlgItem(hwnd, IDC_View), &view_); + CreateColumn(ViewHostStart, ViewHostEnd, ::GetDlgItem(hwnd, IDC_ViewHost), + &view_host_); + CreateColumn(PluginStart, PluginEnd, ::GetDlgItem(hwnd, IDC_Plugin), &plugin_); + CreateColumn(PluginHostStart, PluginHostEnd, + ::GetDlgItem(hwnd, IDC_PluginHost), &plugin_host_); + CreateColumn(NPObjectStart, NPObjectEnd, ::GetDlgItem(hwnd, IDC_NPObject), + &npobject_); + CreateColumn(PluginProcessStart, PluginProcessEnd, + ::GetDlgItem(hwnd, IDC_PluginProcess), &plugin_process_); + CreateColumn(PluginProcessHostStart, PluginProcessHostEnd, + ::GetDlgItem(hwnd, IDC_PluginProcessHost), &plugin_process_host_); + init_done_ = true; +} + +void IPCStatusView::CreateColumn( + uint16 start, uint16 end, HWND hwnd, CListViewCtrl** control) { + DCHECK(*control == NULL); + *control = new CListViewCtrl(hwnd); + CListViewCtrl* control_ptr = *control; + control_ptr->SetViewType(LVS_REPORT); + control_ptr->SetExtendedListViewStyle(LVS_EX_CHECKBOXES); + control_ptr->ModifyStyle(0, LVS_SORTASCENDING | LVS_NOCOLUMNHEADER); + control_ptr->InsertColumn(0, L"id", LVCFMT_LEFT, 230); + + std::set* disabled_messages = ¤t()->disabled_messages_; + for (uint16 i = start; i < end; i++) { + std::wstring name; + IPC::Logging::GetMessageText(i, &name, NULL, NULL); + + int index = control_ptr->InsertItem( + LVIF_TEXT | LVIF_PARAM, 0, name.c_str(), 0, 0, 0, i); + + control_ptr->SetItemText(index, 0, name.c_str()); + + if (disabled_messages->find(i) == disabled_messages->end()) + control_ptr->SetCheckState(index, TRUE); + } +} + +void IPCStatusView::CloseDialog() { + delete view_; + delete view_host_; + delete plugin_host_; + delete npobject_; + delete plugin_process_; + delete plugin_process_host_; + view_ = NULL; + view_host_ = NULL; + plugin_ = NULL; + plugin_host_ = NULL; + npobject_ = NULL; + plugin_process_ = NULL; + plugin_process_host_ = NULL; + init_done_ = false; + + ::DestroyWindow(settings_dialog_); + settings_dialog_ = NULL; + + Profile* current_profile = profile(); + if (!current_profile) + return; + PrefService* prefs = current_profile->GetPrefs(); + if (!prefs->IsPrefRegistered(prefs::kIpcDisabledMessages)) + return; + ListValue* list = prefs->GetMutableList(prefs::kIpcDisabledMessages); + list->Clear(); + for (std::set::const_iterator itr = disabled_messages_.begin(); + itr != disabled_messages_.end(); + ++itr) { + list->Append(Value::CreateIntegerValue(*itr)); + } +} + +void IPCStatusView::OnCheck(int id, bool checked) { + if (!init_done_) + return; + + if (checked) { + disabled_messages_.erase(id); + } else { + disabled_messages_.insert(id); + } +} + +void IPCStatusView::OnButtonClick(int id) { + switch(id) { + case IDC_ViewAll: + CheckButtons(view_, true); + break; + case IDC_ViewNone: + CheckButtons(view_, false); + break; + case IDC_ViewHostAll: + CheckButtons(view_host_, true); + break; + case IDC_ViewHostNone: + CheckButtons(view_host_, false); + break; + case IDC_PluginAll: + CheckButtons(plugin_, true); + break; + case IDC_PluginNone: + CheckButtons(plugin_, false); + break; + case IDC_PluginHostAll: + CheckButtons(plugin_host_, true); + break; + case IDC_PluginHostNone: + CheckButtons(plugin_host_, false); + break; + case IDC_NPObjectAll: + CheckButtons(npobject_, true); + break; + case IDC_NPObjectNone: + CheckButtons(npobject_, false); + break; + } +} + +void IPCStatusView::CheckButtons(CListViewCtrl* control, bool check) { + int count = control->GetItemCount(); + for (int i = 0; i < count; ++i) + control->SetCheckState(i, check); +} + +void IPCStatusView::OnSettings(UINT code, int button_id, HWND hwnd) { + if (settings_dialog_ != NULL) + return; + + HINSTANCE module_handle = GetModuleHandle(chrome::kBrowserResourcesDll); + + settings_dialog_ = CreateDialog(module_handle, + MAKEINTRESOURCE(IDD_IPC_SETTINGS), + NULL, + IPCStatusView::DialogProc); + ::ShowWindow(settings_dialog_, SW_SHOW); +} + +#endif // IPC_MESSAGE_LOG_ENABLED diff --git a/chrome/browser/tab_contents/ipc_status_view.h b/chrome/browser/tab_contents/ipc_status_view.h new file mode 100644 index 0000000..790516d --- /dev/null +++ b/chrome/browser/tab_contents/ipc_status_view.h @@ -0,0 +1,89 @@ +// 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. + +#ifndef CHROME_BROWSER_IPC_STATUS_VIEW_H__ +#define CHROME_BROWSER_IPC_STATUS_VIEW_H__ + +#include + +#include "base/basictypes.h" +#include "chrome/browser/tab_contents/status_view.h" +#include "chrome/common/ipc_logging.h" +#include "chrome/common/ipc_message_utils.h" + +#ifdef IPC_MESSAGE_LOG_ENABLED + +class IPCStatusView : public StatusView, + public IPC::Logging::Consumer { + public: + // button types + enum { + IDC_START_LOGGING = 101, + IDC_STOP_LOGGING, + IDC_CLEAR, + IDC_SETTINGS, + }; + + IPCStatusView(); + virtual ~IPCStatusView(); + + static IPCStatusView* current() { return current_; } + void Log(const IPC::LogData& data); + + // TabContents overrides + virtual const std::wstring GetDefaultTitle(); + virtual void SetActive(bool active); + + // StatusView implementation + virtual void OnCreate(const CRect& rect); + virtual void OnSize(const CRect& rect); + + BEGIN_MSG_MAP(IPCStatusView) + COMMAND_HANDLER_EX(IDC_START_LOGGING, BN_CLICKED, OnStartLogging) + COMMAND_HANDLER_EX(IDC_STOP_LOGGING, BN_CLICKED, OnStopLogging) + COMMAND_HANDLER_EX(IDC_CLEAR, BN_CLICKED, OnClear) + COMMAND_HANDLER_EX(IDC_SETTINGS, BN_CLICKED, OnSettings) + CHAIN_MSG_MAP(StatusView); + END_MSG_MAP() + + static INT_PTR CALLBACK DialogProc( + HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam); + void InitDialog(HWND hwnd); + void CloseDialog(); + static void CreateColumn( + uint16 start, uint16 end, HWND hwnd, CListViewCtrl** control); + void OnCheck(int id, bool checked); + void OnButtonClick(int id); + static void CheckButtons(CListViewCtrl* control, bool check); + + private: + + // Event handlers + void OnStartLogging(UINT code, int button_id, HWND hwnd); + void OnStopLogging(UINT code, int button_id, HWND hwnd); + void OnClear(UINT code, int button_id, HWND hwnd); + void OnSettings(UINT code, int button_id, HWND hwnd); + + static IPCStatusView* current_; + CListViewCtrl message_list_; + + // Used for the filter dialog. + CListViewCtrl* view_; + CListViewCtrl* view_host_; + CListViewCtrl* plugin_; + CListViewCtrl* plugin_host_; + CListViewCtrl* npobject_; + CListViewCtrl* plugin_process_; + CListViewCtrl* plugin_process_host_; + bool init_done_; + HWND settings_dialog_; + std::set disabled_messages_; + + DISALLOW_EVIL_CONSTRUCTORS(IPCStatusView); +}; + +#endif // IPC_MESSAGE_LOG_ENABLED + +#endif // #ifndef CHROME_BROWSER_IPC_STATUS_VIEW_H__ + diff --git a/chrome/browser/tab_contents/native_ui_contents.cc b/chrome/browser/tab_contents/native_ui_contents.cc new file mode 100644 index 0000000..9ff65ce --- /dev/null +++ b/chrome/browser/tab_contents/native_ui_contents.cc @@ -0,0 +1,671 @@ +// 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/native_ui_contents.h" + +#include "chrome/browser/browser.h" +#include "chrome/browser/history_tab_ui.h" +#include "chrome/browser/tab_contents/navigation_entry.h" +#include "chrome/browser/views/download_tab_view.h" +#include "chrome/common/drag_drop_types.h" +#include "chrome/common/gfx/chrome_canvas.h" +#include "chrome/common/gfx/chrome_font.h" +#include "chrome/common/l10n_util.h" +#include "chrome/common/os_exchange_data.h" +#include "chrome/common/resource_bundle.h" +#include "chrome/views/background.h" +#include "chrome/views/checkbox.h" +#include "chrome/views/grid_layout.h" +#include "chrome/views/image_view.h" +#include "chrome/views/root_view.h" +#include "chrome/views/scroll_view.h" +#include "chrome/views/throbber.h" +#include "chrome/views/widget_win.h" + +#include "generated_resources.h" + +using views::ColumnSet; +using views::GridLayout; + +//static +bool NativeUIContents::g_ui_factories_initialized = false; + +// The URL scheme currently used. +static const char kNativeUIContentsScheme[] = "chrome-nativeui"; + +// Unique page id generator. +static int g_next_page_id = 0; + +// The x-position of the title. +static const int kDestinationTitleOffset = 38; + +// The x-position of the search field. +static const int kDestinationSearchOffset = 128; + +// The width of the search field. +static const int kDestinationSearchWidth = 360; + +// Padding between columns +static const int kDestinationSmallerMargin = 8; + +// The background color. +static const SkColor kBackground = SkColorSetRGB(255, 255, 255); + +// The color of the bottom margin. +static const SkColor kBottomMarginColor = SkColorSetRGB(246, 249, 255); + +// The height of the bottom margin. +static const int kBottomMargin = 5; + +// The Chrome product logo. +static const SkBitmap* kProductLogo = NULL; + +// Padding around the product logo. +static const int kProductLogoPadding = 8; + +namespace { + +// NativeRootView -------------------------------------------------------------- + +// NativeRootView is a trivial RootView subclass that allows URL drops and +// forwards them to the NavigationController to open. + +class NativeRootView : public views::RootView { + public: + explicit NativeRootView(NativeUIContents* host) + : RootView(host), + host_(host) { } + + virtual ~NativeRootView() { } + + virtual bool CanDrop(const OSExchangeData& data) { + return data.HasURL(); + } + + virtual int OnDragUpdated(const views::DropTargetEvent& event) { + if (event.GetSourceOperations() & DragDropTypes::DRAG_COPY) + return DragDropTypes::DRAG_COPY; + if (event.GetSourceOperations() & DragDropTypes::DRAG_LINK) + return DragDropTypes::DRAG_LINK; + return DragDropTypes::DRAG_NONE; + } + + virtual int OnPerformDrop(const views::DropTargetEvent& event) { + GURL url; + std::wstring title; + if (!event.GetData().GetURLAndTitle(&url, &title) || !url.is_valid()) + return DragDropTypes::DRAG_NONE; + host_->controller()->LoadURL(url, GURL(), PageTransition::GENERATED); + return OnDragUpdated(event); + } + + private: + NativeUIContents* host_; + + DISALLOW_EVIL_CONSTRUCTORS(NativeRootView); +}; + +} // namespace + + +// Returns the end of the scheme and end of the host. This is temporary until +// bug 772411 is fixed. +static void GetSchemeAndHostEnd(const GURL& url, + size_t* scheme_end, + size_t* host_end) { + const std::string spec = url.spec(); + *scheme_end = spec.find("//"); + DCHECK(*scheme_end != std::string::npos); + + *host_end = spec.find('/', *scheme_end + 2); + if (*host_end == std::string::npos) + *host_end = spec.size(); +} + +NativeUIContents::NativeUIContents(Profile* profile) + : TabContents(TAB_CONTENTS_NATIVE_UI), + is_visible_(false), + current_ui_(NULL), + current_view_(NULL), + state_(new PageState()) { + if (!g_ui_factories_initialized) { + InitializeNativeUIFactories(); + g_ui_factories_initialized = true; + } +} + +NativeUIContents::~NativeUIContents() { + if (current_ui_) { + views::RootView* root_view = GetRootView(); + current_ui_->WillBecomeInvisible(this); + root_view->RemoveChildView(current_view_); + current_ui_ = NULL; + current_view_ = NULL; + } + + STLDeleteContainerPairSecondPointers(path_to_native_uis_.begin(), + path_to_native_uis_.end()); +} + +void NativeUIContents::CreateView() { + set_delete_on_destroy(false); + WidgetWin::Init(GetDesktopWindow(), gfx::Rect(), false); +} + +LRESULT NativeUIContents::OnCreate(LPCREATESTRUCT create_struct) { + // Set the view container initial size. + CRect tmp; + ::GetWindowRect(GetHWND(), &tmp); + tmp.right = tmp.Width(); + tmp.bottom = tmp.Height(); + tmp.left = tmp.top = 0; + + // Install the focus manager so we get notified of Tab key events. + views::FocusManager::InstallFocusSubclass(GetHWND(), NULL); + GetRootView()->set_background(new NativeUIBackground); + return 0; +} + +void NativeUIContents::OnDestroy() { + views::FocusManager::UninstallFocusSubclass(GetHWND()); +} + +void NativeUIContents::OnSize(UINT size_command, const CSize& new_size) { + Layout(); + ::RedrawWindow(GetHWND(), NULL, NULL, RDW_INVALIDATE | RDW_ALLCHILDREN); +} + +void NativeUIContents::OnWindowPosChanged(WINDOWPOS* position) { + // NOTE: this may be invoked even when the visbility didn't change, in which + // case hiding and showing are both false. + const bool hiding = (position->flags & SWP_HIDEWINDOW) == SWP_HIDEWINDOW; + const bool showing = (position->flags & SWP_SHOWWINDOW) == SWP_SHOWWINDOW; + if (hiding || showing) { + if (is_visible_ != showing) { + is_visible_ = showing; + if (current_ui_) { + if (is_visible_) + current_ui_->WillBecomeVisible(this); + else + current_ui_->WillBecomeInvisible(this); + } + } + } + ChangeSize(0, CSize(position->cx, position->cy)); + + SetMsgHandled(FALSE); +} + +void NativeUIContents::GetContainerBounds(gfx::Rect* out) const { + GetBounds(out, false); +} + +void NativeUIContents::SetPageState(PageState* page_state) { + if (!page_state) + page_state = new PageState(); + state_.reset(page_state); + NavigationController* ctrl = controller(); + if (ctrl) { + int ne_index = ctrl->GetLastCommittedEntryIndex(); + NavigationEntry* ne = ctrl->GetEntryAtIndex(ne_index); + if (ne) { + // NavigationEntry is null if we're being restored. + DCHECK(ne); + std::string rep; + state_->GetByteRepresentation(&rep); + ne->set_content_state(rep); + ctrl->NotifyEntryChanged(ne, ne_index); + } + } +} + +bool NativeUIContents::NavigateToPendingEntry(bool reload) { + views::RootView* root_view = GetRootView(); + DCHECK(root_view); + + if (current_ui_) { + current_ui_->WillBecomeInvisible(this); + root_view->RemoveChildView(current_view_); + current_ui_ = NULL; + current_view_ = NULL; + } + + NavigationEntry* pending_entry = controller()->GetPendingEntry(); + NativeUI* new_ui = GetNativeUIForURL(pending_entry->url()); + if (new_ui) { + current_ui_ = new_ui; + is_visible_ = true; + current_ui_->WillBecomeVisible(this); + current_view_ = new_ui->GetView(); + root_view->AddChildView(current_view_); + + std::string s = pending_entry->content_state(); + if (s.empty()) + state_->InitWithURL(pending_entry->url()); + else + state_->InitWithBytes(s); + + current_ui_->Navigate(*state_); + Layout(); + } + + // Commit the new load in the navigation controller. If the ID of the + // NavigationEntry we were given was -1, that means this is a new load, so + // we have to generate a new ID. + controller()->CommitPendingEntry(); + + // Populate the committed entry. + NavigationEntry* committed_entry = controller()->GetLastCommittedEntry(); + committed_entry->set_title(GetDefaultTitle()); + committed_entry->favicon().set_bitmap(GetFavIcon()); + committed_entry->favicon().set_is_valid(true); + if (new_ui) { + // Strip out the query params, they should have moved to state. + // TODO(sky): use GURL methods for replacements once bug is fixed. + size_t scheme_end, host_end; + GetSchemeAndHostEnd(committed_entry->url(), &scheme_end, &host_end); + committed_entry->set_url( + GURL(committed_entry->url().spec().substr(0, host_end))); + } + std::string content_state; + state_->GetByteRepresentation(&content_state); + committed_entry->set_content_state(content_state); + + // Broadcast the fact that we just updated all that crap. + controller()->NotifyEntryChanged( + committed_entry, + controller()->GetIndexOfEntry(committed_entry)); + return true; +} + +void NativeUIContents::Layout() { + if (current_view_) { + views::RootView* root_view = GetRootView(); + current_view_->SetBounds(0, 0, root_view->width(), + root_view->height()); + current_view_->Layout(); + } +} + +const std::wstring NativeUIContents::GetDefaultTitle() const { + if (current_ui_) + return current_ui_->GetTitle(); + else + return std::wstring(); +} + +SkBitmap NativeUIContents::GetFavIcon() const { + int icon_id; + + if (current_ui_) + icon_id = current_ui_->GetFavIconID(); + else + icon_id = IDR_DEFAULT_FAVICON; + + return *ResourceBundle::GetSharedInstance().GetBitmapNamed(icon_id); +} + +void NativeUIContents::DidBecomeSelected() { + TabContents::DidBecomeSelected(); + Layout(); +} + +void NativeUIContents::SetInitialFocus() { + if (!current_ui_ || !current_ui_->SetInitialFocus()) { + int tab_index; + Browser* browser = Browser::GetBrowserForController( + this->controller(), &tab_index); + if (browser) + browser->FocusLocationBar(); + else + TabContents::SetInitialFocus(); // Will set focus to our HWND. + } +} + +void NativeUIContents::SetIsLoading(bool is_loading, + LoadNotificationDetails* details) { + TabContents::SetIsLoading(is_loading, details); +} + +// FocusTraversable Implementation +views::View* NativeUIContents::FindNextFocusableView( + views::View* starting_view, bool reverse, + views::FocusTraversable::Direction direction, bool dont_loop, + views::FocusTraversable** focus_traversable, + views::View** focus_traversable_view) { + return GetRootView()->FindNextFocusableView( + starting_view, reverse, direction, dont_loop, + focus_traversable, focus_traversable_view); +} + +//static +std::string NativeUIContents::GetScheme() { + return kNativeUIContentsScheme; +} + +//static +void NativeUIContents::InitializeNativeUIFactories() { + RegisterNativeUIFactory(DownloadTabUI::GetURL(), + DownloadTabUI::GetNativeUIFactory()); + RegisterNativeUIFactory(HistoryTabUI::GetURL(), + HistoryTabUI::GetNativeUIFactory()); +} + +// static +std::string NativeUIContents::GetFactoryKey(const GURL& url) { + size_t scheme_end; + size_t host_end; + GetSchemeAndHostEnd(url, &scheme_end, &host_end); + return url.spec().substr(scheme_end + 2, host_end - scheme_end - 2); +} + +typedef std::map PathToFactoryMap; + +static PathToFactoryMap* g_path_to_factory = NULL; + +//static +void NativeUIContents::RegisterNativeUIFactory(const GURL& url, + NativeUIFactory* factory) { + const std::string key = GetFactoryKey(url); + + if (!g_path_to_factory) + g_path_to_factory = new PathToFactoryMap; + + PathToFactoryMap::iterator i = g_path_to_factory->find(key); + if (i != g_path_to_factory->end()) { + delete i->second; + g_path_to_factory->erase(i); + } + (*g_path_to_factory)[key] = factory; +} + +views::RootView* NativeUIContents::CreateRootView() { + return new NativeRootView(this); +} + +//static +NativeUI* NativeUIContents::InstantiateNativeUIForURL( + const GURL& url, NativeUIContents* contents) { + if (!g_path_to_factory) + return NULL; + + const std::string key = GetFactoryKey(url); + + NativeUIFactory* factory = (*g_path_to_factory)[key]; + if (factory) + return factory->CreateNativeUIForURL(url, contents); + else + return NULL; +} + +NativeUI* NativeUIContents::GetNativeUIForURL(const GURL& url) { + const std::string key = GetFactoryKey(url); + + PathToUI::iterator i = path_to_native_uis_.find(key); + if (i != path_to_native_uis_.end()) + return i->second; + + NativeUI* ui = InstantiateNativeUIForURL(url, this); + if (ui) + path_to_native_uis_[key] = ui; + return ui; +} + + +//////////////////////////////////////////////////////////////////////////////// +// +// Standard NativeUI background implementation. +// +//////////////////////////////////////////////////////////////////////////////// +NativeUIBackground::NativeUIBackground() { +} + +NativeUIBackground::~NativeUIBackground() { +} + +void NativeUIBackground::Paint(ChromeCanvas* canvas, + views::View* view) const { + static const SkColor kBackground = SkColorSetRGB(255, 255, 255); + canvas->FillRectInt(kBackground, 0, 0, view->width(), view->height()); +} + +///////////////////////////////////////////////////////////////////////////// +// +// SearchableUIBackground +// A Background subclass to be used with SearchableUIContainer objects. +// Paint() is overridden to do nothing here; the background of the bar is +// painted in SearchableUIContainer::Paint. This class is necessary +// only for native controls to be able to get query the background +// brush. + +class SearchableUIBackground : public views::Background { + public: + explicit SearchableUIBackground(SkColor native_control_color) { + SetNativeControlColor(native_control_color); + } + virtual ~SearchableUIBackground() {}; + + // Empty implementation. + // The actual painting of the bar happens in SearchableUIContainer::Paint. + virtual void Paint(ChromeCanvas* canvas, views::View* view) const { } + + private: + DISALLOW_EVIL_CONSTRUCTORS(SearchableUIBackground); +}; + +///////////////////////////////////////////////////////////////////////////// +// +// SearchableUIContainer implementation. +// +///////////////////////////////////////////////////////////////////////////// + +SearchableUIContainer::SearchableUIContainer( + SearchableUIContainer::Delegate* delegate) + : delegate_(delegate), + search_field_(NULL), + title_link_(NULL), + title_image_(NULL), + scroll_view_(NULL) { + title_link_ = new views::Link; + ResourceBundle& resource_bundle = ResourceBundle::GetSharedInstance(); + ChromeFont title_font(resource_bundle + .GetFont(ResourceBundle::WebFont).DeriveFont(2)); + title_link_->SetFont(title_font); + title_link_->SetHorizontalAlignment(views::Label::ALIGN_LEFT); + title_link_->SetController(this); + + title_image_ = new views::ImageView(); + title_image_->SetVisible(false); + + // Get the product logo + if (!kProductLogo) { + kProductLogo = resource_bundle.GetBitmapNamed(IDR_PRODUCT_LOGO); + } + + product_logo_ = new views::ImageView(); + product_logo_->SetVisible(true); + product_logo_->SetImage(*kProductLogo); + AddChildView(product_logo_); + + search_field_ = new views::TextField; + search_field_->SetFont(ResourceBundle::GetSharedInstance().GetFont( + ResourceBundle::WebFont)); + search_field_->SetController(this); + + scroll_view_ = new views::ScrollView; + scroll_view_->set_background( + views::Background::CreateSolidBackground(kBackground)); + + // Set background class so that native controls can get a color. + set_background(new SearchableUIBackground(kBackground)); + + throbber_ = new views::SmoothedThrobber(50); + + GridLayout* layout = new GridLayout(this); + // View owns the LayoutManager and will delete it along with all the columns + // we create here. + SetLayoutManager(layout); + + search_button_ = + new views::NativeButton(std::wstring()); + search_button_->SetFont(resource_bundle.GetFont(ResourceBundle::WebFont)); + search_button_->SetListener(this); + + // Set a background color for the search button. If SearchableUIContainer + // provided a background, then the search button could inherit that instead. + search_button_->set_background(new SearchableUIBackground(kBackground)); + + // For the first row (icon, title/text field, search button and throbber). + ColumnSet* column_set = layout->AddColumnSet(0); + column_set->AddPaddingColumn(0, kDestinationTitleOffset); + + // Add the icon column. + column_set->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 0, + GridLayout::USE_PREF, + kDestinationSearchOffset - kDestinationTitleOffset - + kDestinationSmallerMargin, + kDestinationSearchOffset - kDestinationTitleOffset - + kDestinationSmallerMargin); + column_set->AddPaddingColumn(0, kDestinationSmallerMargin); + + // Add the title/search field column. + column_set->AddColumn(GridLayout::FILL, GridLayout::CENTER, 0, + GridLayout::USE_PREF, kDestinationSearchWidth, + kDestinationSearchWidth); + column_set->AddPaddingColumn(0, kDestinationSmallerMargin); + + // Add the search button column. + column_set->AddColumn(GridLayout::CENTER, GridLayout::CENTER, 0, + GridLayout::USE_PREF, 0, 0); + column_set->AddPaddingColumn(0, kDestinationSmallerMargin); + + // Add the throbber column. + column_set->AddColumn(GridLayout::CENTER, GridLayout::CENTER, 0, + GridLayout::USE_PREF, 0, 0); + + // For the scroll view. + column_set = layout->AddColumnSet(1); + column_set->AddPaddingColumn(0, 1); + column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1, + GridLayout::USE_PREF, 0, 0); + + layout->AddPaddingRow(0, kDestinationSmallerMargin); + layout->StartRow(0, 0); + layout->AddView(title_image_, 1, 2); + layout->AddView(title_link_); + + layout->StartRow(0, 0); + layout->SkipColumns(1); + layout->AddView(search_field_); + layout->AddView(search_button_); + layout->AddView(throbber_); + + layout->AddPaddingRow(0, kDestinationSmallerMargin); + layout->StartRow(1, 1); + layout->AddView(scroll_view_); +} + +SearchableUIContainer::~SearchableUIContainer() { +} + +void SearchableUIContainer::SetContents(views::View* contents) { + // The column view will resize to accomodate long titles. + title_link_->SetText(delegate_->GetTitle()); + + int section_icon_id = delegate_->GetSectionIconID(); + if (section_icon_id != 0) { + title_image_->SetImage(*ResourceBundle::GetSharedInstance(). + GetBitmapNamed(section_icon_id)); + title_image_->SetVisible(true); + } + + search_button_->SetLabel(delegate_->GetSearchButtonText()); + scroll_view_->SetContents(contents); +} + +views::View* SearchableUIContainer::GetContents() { + return scroll_view_->GetContents(); +} + +void SearchableUIContainer::Layout() { + View::Layout(); + + gfx::Size search_button_size = search_button_->GetPreferredSize(); + gfx::Size product_logo_size = product_logo_->GetPreferredSize(); + + int field_width = kDestinationSearchOffset + + kDestinationSearchWidth + + kDestinationSmallerMargin + + static_cast(search_button_size.width()) + + kDestinationSmallerMargin; + + product_logo_->SetBounds(std::max(width() - kProductLogo->width() - + kProductLogoPadding, + field_width), + kProductLogoPadding, + product_logo_size.width(), + product_logo_size.height()); +} + +void SearchableUIContainer::Paint(ChromeCanvas* canvas) { + SkColor top_color(kBackground); + canvas->FillRectInt(top_color, 0, 0, + width(), scroll_view_->y()); + + canvas->FillRectInt(kBottomMarginColor, 0, scroll_view_->y() - + kBottomMargin, width(), kBottomMargin); + + canvas->FillRectInt(SkColorSetRGB(196, 196, 196), + 0, scroll_view_->y() - 1, width(), 1); +} + +views::TextField* SearchableUIContainer::GetSearchField() const { + return search_field_; +} + +views::ScrollView* SearchableUIContainer::GetScrollView() const { + return scroll_view_; +} + +void SearchableUIContainer::SetSearchEnabled(bool enabled) { + search_field_->SetReadOnly(!enabled); + search_button_->SetEnabled(enabled); +} + +void SearchableUIContainer::StartThrobber() { + throbber_->Start(); +} + +void SearchableUIContainer::StopThrobber() { + throbber_->Stop(); +} + +void SearchableUIContainer::ButtonPressed(views::NativeButton* sender) { + DoSearch(); +} + +void SearchableUIContainer::LinkActivated(views::Link *link, + int event_flags) { + if (link == title_link_) { + search_field_->SetText(std::wstring()); + DoSearch(); + } +} + +void SearchableUIContainer::HandleKeystroke(views::TextField* sender, + UINT message, + TCHAR key, + UINT repeat_count, + UINT flags) { + if (key == VK_RETURN) + DoSearch(); +} + +void SearchableUIContainer::DoSearch() { + if (delegate_) + delegate_->DoSearch(search_field_->GetText()); + + scroll_view_->ScrollToPosition(scroll_view_->vertical_scroll_bar(), 0); +} + diff --git a/chrome/browser/tab_contents/native_ui_contents.h b/chrome/browser/tab_contents/native_ui_contents.h new file mode 100644 index 0000000..decf123 --- /dev/null +++ b/chrome/browser/tab_contents/native_ui_contents.h @@ -0,0 +1,295 @@ +// 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. + +#ifndef CHROME_BROWSER_NATIVE_UI_CONTENTS_H__ +#define CHROME_BROWSER_NATIVE_UI_CONTENTS_H__ + +#include "chrome/browser/page_state.h" +#include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/views/background.h" +#include "chrome/views/link.h" +#include "chrome/views/native_button.h" +#include "chrome/views/text_field.h" +#include "chrome/views/widget_win.h" + +namespace views { +class CheckBox; +class FocusTraversable; +class ImageView; +class ScrollView; +class Throbber; +} + +class NativeUIFactory; +class NativeUI; + +//////////////////////////////////////////////////////////////////////////////// +// +// NativeUIContents +// +// NativeUIContents is a TabContents that is used to show some pages made with +// some native user interface elements. NativeUIContents maintains a list of URL +// path mapping to specific NativeUI implementations. +// +//////////////////////////////////////////////////////////////////////////////// +class NativeUIContents : public TabContents, + public views::WidgetWin { + public: + explicit NativeUIContents(Profile* profile); + + virtual void CreateView(); + virtual HWND GetContainerHWND() const { return GetHWND(); } + virtual void GetContainerBounds(gfx::Rect* out) const; + + // Sets the page state. NativeUIContents takes ownership of the supplied + // PageState. Use a value of NULL to set the state to empty. + void SetPageState(PageState* page_state); + + // Returns the page state. This is intended for UIs that want to store page + // state. + const PageState& page_state() const { return *state_; } + + // + // TabContents implementation + // + virtual bool NavigateToPendingEntry(bool reload); + virtual const std::wstring GetDefaultTitle() const; + virtual SkBitmap GetFavIcon() const; + virtual bool ShouldDisplayURL() { return false; } + virtual bool ShouldDisplayFavIcon() { return true; } + virtual void DidBecomeSelected(); + virtual void SetInitialFocus(); + + // Sets the current loading state. This is public for NativeUIs to update. + void SetIsLoading(bool is_loading, LoadNotificationDetails* details); + + // FocusTraversable Implementation + virtual views::View* FindNextFocusableView( + views::View* starting_view, + bool reverse, + views::FocusTraversable::Direction direction, + bool dont_loop, + views::FocusTraversable** focus_traversable, + views::View** focus_traversable_view); + virtual views::RootView* GetContentsRootView() { return GetRootView(); } + + // Return the scheme used. We currently use chrome-nativeui: + static std::string GetScheme(); + + // Register a NativeUIFactory for a given path. + static void RegisterNativeUIFactory(const GURL& url, + NativeUIFactory* factory); + + protected: + // Should be deleted via CloseContents. + virtual ~NativeUIContents(); + + // Overridden to create a view that that handles drag and drop. + virtual views::RootView* CreateRootView(); + + private: + // Initialize the factories. This is called the first time a NativeUIContents + // object is created. If you add a new factory, you need to add a line in this + // method. + static void InitializeNativeUIFactories(); + + // Instantiates a native UI for the provided URL. This is done by using the + // native factories which have been registered. + static NativeUI* InstantiateNativeUIForURL(const GURL& url, + NativeUIContents* contents); + + // Returns the key to use based on the TabUI's url. + static std::string GetFactoryKey(const GURL& url); + + // Size the current UI if any. + void Layout(); + + // Return the Native UI for the provided URL. The NativeUIs are returned from + // a cache. Returns NULL if no such UI exists. + NativeUI* GetNativeUIForURL(const GURL& url); + + // Windows message handlers. + virtual LRESULT OnCreate(LPCREATESTRUCT create_struct); + virtual void OnDestroy(); + virtual void OnSize(UINT size_command, const CSize& new_size); + virtual void OnWindowPosChanged(WINDOWPOS* position); + + // Whether this contents is visible. + bool is_visible_; + + // Path to NativeUI map. We keep reusing the same UIs. + typedef std::map PathToUI; + PathToUI path_to_native_uis_; + + // The current UI. + NativeUI* current_ui_; + + // The current view for the current UI. We don't ask again just in case the + // UI implementation keeps allocating new uis. + views::View* current_view_; + + // The current page state for the native contents. + scoped_ptr state_; + + // Whether factories have been initialized. + static bool g_ui_factories_initialized; + + DISALLOW_EVIL_CONSTRUCTORS(NativeUIContents); +}; + +///////////////////////////////////////////////////////////////////////////// +// +// A native UI needs to implement the following interface to work with the +// NativeUIContents. +// +///////////////////////////////////////////////////////////////////////////// +class NativeUI { + public: + virtual ~NativeUI() {} + + // Return the title for this user interface. The title is used as a tab title. + virtual const std::wstring GetTitle() const = 0; + + // Return the favicon id for this user interface. + virtual const int GetFavIconID () const = 0; + + // Return the view that should be used to render this user interface. + virtual views::View* GetView() = 0; + + // Inform the view that it is about to become visible. + virtual void WillBecomeVisible(NativeUIContents* parent) = 0; + + // Inform the view that it is about to become invisible. + virtual void WillBecomeInvisible(NativeUIContents* parent) = 0; + + // Inform the view that it should recreate the provided state. The state + // should be updated as needed by using the current navigation entry of + // the provided tab contents. + virtual void Navigate(const PageState& state) = 0; + + // Requests the contents set the initial focus. A return value of true + // indicates the contents wants focus and requested focus. A return value of + // false indicates the contents does not want focus, and that focus should + // go to the location bar. + virtual bool SetInitialFocus() = 0; +}; + +///////////////////////////////////////////////////////////////////////////// +// +// NativeUIFactory defines the method necessary to instantiate a NativeUI +// object. Typically, each NativeUI implementation registers an object that +// can instantiate NativeUI objects given the necessary path. +// +///////////////////////////////////////////////////////////////////////////// +class NativeUIFactory { + public: + virtual ~NativeUIFactory() {} + + // Request the factory to instantiate a NativeUI object given the provided + // url. The url is a nativeui: URL which contains the path for which this + // factory was registered. + // + // See NativeUIContents::RegisterNativeUI(). + virtual NativeUI* CreateNativeUIForURL(const GURL& url, + NativeUIContents* contents) = 0; +}; + + +//////////////////////////////////////////////////////////////////////////////// +// +// A standard background for native UIs. +// +//////////////////////////////////////////////////////////////////////////////// +class NativeUIBackground : public views::Background { + public: + NativeUIBackground(); + virtual ~NativeUIBackground(); + + virtual void Paint(ChromeCanvas* canvas, views::View* view) const; + + private: + + DISALLOW_EVIL_CONSTRUCTORS(NativeUIBackground); +}; + +//////////////////////////////////////////////////////////////////////////////// +// +// A view subclass used to implement native uis that feature a search field. +// This view contains a search field and a ScrollView for the contents. It +// implements a consistent look for these UIs. +// +//////////////////////////////////////////////////////////////////////////////// +class SearchableUIContainer : public views::View, + public views::NativeButton::Listener, + public views::LinkController, + public views::TextField::Controller { + public: + // The Delegate is notified when the user clicks the search button. + class Delegate { + public: + virtual void DoSearch(const std::wstring& text) = 0; + virtual const std::wstring GetTitle() const = 0; + virtual const int GetSectionIconID() const = 0; + virtual const std::wstring GetSearchButtonText() const = 0; + }; + + // Create a new SearchableUIContainer given a delegate. + explicit SearchableUIContainer(Delegate* delegate); + + virtual ~SearchableUIContainer(); + + // Add the view as the contents of the container. + void SetContents(views::View* contents); + views::View* GetContents(); + + virtual void Layout(); + + // Overriden to paint the container. + virtual void Paint(ChromeCanvas* canvas); + + // Provide the mode access to various UI elements. + views::TextField* GetSearchField() const; + views::ScrollView* GetScrollView() const; + + // Enable/disable the search text-field/button. + void SetSearchEnabled(bool enabled); + + // Start and stop the throbber. + void StartThrobber(); + void StopThrobber(); + + private: + // Invoked when the user presses the search button. + virtual void ButtonPressed(views::NativeButton* sender); + + // TextField method, does nothing. + virtual void ContentsChanged(views::TextField* sender, + const std::wstring& new_contents) {} + + // Textfield method, if key is the return key the search is updated. + virtual void HandleKeystroke(views::TextField* sender, + UINT message, + TCHAR key, + UINT repeat_count, + UINT flags); + + // Notifies the delegate to update the search. + void DoSearch(); + + void LinkActivated(views::Link* link, int event_flags); + + Delegate* delegate_; + views::Link* title_link_; + views::ImageView* title_image_; + views::ImageView* product_logo_; + views::TextField* search_field_; + views::NativeButton* search_button_; + views::ScrollView* scroll_view_; + views::Throbber* throbber_; + + DISALLOW_EVIL_CONSTRUCTORS(SearchableUIContainer); +}; + +#endif // CHROME_BROWSER_NATIVE_UI_CONTENTS_H__ + diff --git a/chrome/browser/tab_contents/navigation_controller.cc b/chrome/browser/tab_contents/navigation_controller.cc new file mode 100644 index 0000000..e9dd832 --- /dev/null +++ b/chrome/browser/tab_contents/navigation_controller.cc @@ -0,0 +1,1233 @@ +// 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_controller.h" + +#include "base/command_line.h" +#include "base/file_util.h" +#include "base/logging.h" +#include "base/string_util.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/dom_ui/dom_ui_host.h" +#include "chrome/browser/profile.h" +#include "chrome/browser/repost_form_warning_dialog.h" +#include "chrome/browser/sessions/session_types.h" +#include "chrome/browser/tab_contents/navigation_entry.h" +#include "chrome/browser/tab_contents/site_instance.h" +#include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/tab_contents/tab_contents_delegate.h" +#include "chrome/common/chrome_switches.h" +#include "chrome/common/navigation_types.h" +#include "chrome/common/resource_bundle.h" +#include "chrome/common/scoped_vector.h" +#include "net/base/net_util.h" +#include "webkit/glue/webkit_glue.h" + +namespace { + +// 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( + NOTIFY_NAV_LIST_PRUNED, + Source(nav_controller), + Details(&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->tab_type() == TAB_CONTENTS_WEB || + entry->tab_type() == TAB_CONTENTS_NEW_TAB_UI || + entry->tab_type() == TAB_CONTENTS_ABOUT_UI || + entry->tab_type() == TAB_CONTENTS_HTML_DIALOG || + entry->tab_type() == TAB_CONTENTS_VIEW_SOURCE)) { + 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 >* entries) { + 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_restored(true); + // 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()) + return false; + + url_canon::Replacements replacements; + replacements.ClearRef(); + return existing_url.ReplaceComponents(replacements) == + new_url.ReplaceComponents(replacements); +} + +} // namespace + +// TabContentsCollector --------------------------------------------------- + +// We never destroy a TabContents synchronously because there are some +// complex code path that cause the current TabContents to be in the call +// stack. So instead, we use a TabContentsCollector which either destroys +// the TabContents or does nothing if it has been cancelled. +class TabContentsCollector : public Task { + public: + TabContentsCollector(NavigationController* target, + TabContentsType target_type) + : target_(target), + target_type_(target_type) { + } + + void Cancel() { + target_ = NULL; + } + + virtual void Run() { + if (target_) { + // Note: this will cancel this task as a side effect so target_ is + // now null. + TabContents* tc = target_->GetTabContents(target_type_); + tc->Destroy(); + } + } + + private: + // The NavigationController we are acting on. + NavigationController* target_; + + // The TabContentsType that needs to be collected. + TabContentsType target_type_; + + DISALLOW_EVIL_CONSTRUCTORS(TabContentsCollector); +}; + +// NavigationController --------------------------------------------------- + +// static +size_t NavigationController::max_entry_count_ = 50; + +// static +bool NavigationController::check_for_repost_ = true; + +// Creates a new NavigationEntry for each TabNavigation in navigations, adding +// the NavigationEntry to entries. This is used during session restore. +static void CreateNavigationEntriesFromTabNavigations( + const std::vector& navigations, + std::vector >* entries) { + // Create a NavigationEntry for each of the navigations. + int page_id = 0; + for (std::vector::const_iterator i = + navigations.begin(); i != navigations.end(); ++i, ++page_id) { + entries->push_back( + linked_ptr(i->ToNavigationEntry(page_id))); + } +} + +NavigationController::NavigationController(TabContents* contents, + Profile* profile) + : profile_(profile), + pending_entry_(NULL), + last_committed_entry_index_(-1), + pending_entry_index_(-1), + transient_entry_index_(-1), + active_contents_(contents), + max_restored_page_id_(-1), + ssl_manager_(this, NULL), + needs_reload_(false), + load_pending_entry_when_active_(false) { + if (contents) + RegisterTabContents(contents); + DCHECK(profile_); +} + +NavigationController::NavigationController( + Profile* profile, + const std::vector& navigations, + int selected_navigation) + : profile_(profile), + pending_entry_(NULL), + last_committed_entry_index_(-1), + pending_entry_index_(-1), + transient_entry_index_(-1), + active_contents_(NULL), + max_restored_page_id_(-1), + ssl_manager_(this, NULL), + needs_reload_(true), + load_pending_entry_when_active_(false) { + DCHECK(profile_); + DCHECK(selected_navigation >= 0 && + selected_navigation < static_cast(navigations.size())); + + // Populate entries_ from the supplied TabNavigations. + CreateNavigationEntriesFromTabNavigations(navigations, &entries_); + + // And finish the restore. + FinishRestore(selected_navigation); +} + +NavigationController::~NavigationController() { + DCHECK(tab_contents_map_.empty()); + DCHECK(tab_contents_collector_map_.empty()); + + DiscardNonCommittedEntriesInternal(); + + NotificationService::current()->Notify(NOTIFY_TAB_CLOSED, + Source(this), + NotificationService::NoDetails()); +} + +TabContents* NavigationController::GetTabContents(TabContentsType t) { + // Make sure the TabContents is no longer scheduled for collection. + CancelTabContentsCollection(t); + return tab_contents_map_[t]; +} + +void NavigationController::Reload(bool check_for_repost) { + // Reloading a transient entry does nothing. + if (transient_entry_index_ != -1) + return; + + DiscardNonCommittedEntriesInternal(); + int current_index = GetCurrentEntryIndex(); + if (check_for_repost_ && check_for_repost && current_index != -1 && + 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, RepostFormWarningDialog calls us + // back with ReloadDontCheckForRepost. + active_contents_->Activate(); + RepostFormWarningDialog::RunRepostFormWarningDialog(this); + } else { + // Base the navigation on where we are now... + 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; + + DiscardNonCommittedEntriesInternal(); + + pending_entry_index_ = current_index; + entries_[pending_entry_index_]->set_transition_type(PageTransition::RELOAD); + NavigateToPendingEntry(true); + } +} + +NavigationEntry* NavigationController::GetEntryWithPageID( + TabContentsType type, SiteInstance* instance, int32 page_id) const { + int index = GetEntryIndexWithPageID(type, instance, page_id); + return (index != -1) ? entries_[index].get() : NULL; +} + +void NavigationController::LoadEntry(NavigationEntry* entry) { + // 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( + NOTIFY_NAV_ENTRY_PENDING, + Source(this), + NotificationService::NoDetails()); + NavigateToPendingEntry(false); +} + +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(); +} + +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 >= GetEntryCount()) + 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(entries_.size()) - 1); +} + +void NavigationController::GoBack() { + if (!CanGoBack()) { + NOTREACHED(); + return; + } + + // Base the navigation on where we are now... + int current_index = GetCurrentEntryIndex(); + + DiscardNonCommittedEntries(); + + pending_entry_index_ = current_index - 1; + NavigateToPendingEntry(false); +} + +void NavigationController::GoForward() { + if (!CanGoForward()) { + NOTREACHED(); + return; + } + + 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_++; + + NavigateToPendingEntry(false); +} + +void NavigationController::GoToIndex(int index) { + if (index < 0 || index >= static_cast(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--; + } + } + + DiscardNonCommittedEntries(); + + pending_entry_index_ = index; + NavigateToPendingEntry(false); +} + +void NavigationController::GoToOffset(int offset) { + int index = (transient_entry_index_ != -1) ? + transient_entry_index_ + offset : + last_committed_entry_index_ + offset; + if (index < 0 || index >= GetEntryCount()) + return; + + GoToIndex(index); +} + +void NavigationController::RemoveEntryAtIndex(int index, + const GURL& default_url) { + int size = static_cast(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(false); + } 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::Destroy() { + // Close all tab contents owned by this controller. We make a list on the + // stack because they are removed from the map as they are Destroyed + // (invalidating the iterators), which may or may not occur synchronously. + // We also keep track of any NULL entries in the map so that we can clean + // them out. + std::list tabs_to_destroy; + std::list tab_types_to_erase; + for (TabContentsMap::iterator i = tab_contents_map_.begin(); + i != tab_contents_map_.end(); ++i) { + if (i->second) + tabs_to_destroy.push_back(i->second); + else + tab_types_to_erase.push_back(i->first); + } + + // Clean out all NULL entries in the map so that we know empty map means all + // tabs destroyed. This is needed since TabContentsWasDestroyed() won't get + // called for types that are in our map with a NULL contents. (We don't do + // this by iterating over TAB_CONTENTS_NUM_TYPES because some tests create + // additional types.) + for (std::list::iterator i = tab_types_to_erase.begin(); + i != tab_types_to_erase.end(); ++i) { + TabContentsMap::iterator map_iterator = tab_contents_map_.find(*i); + if (map_iterator != tab_contents_map_.end()) { + DCHECK(!map_iterator->second); + tab_contents_map_.erase(map_iterator); + } + } + + // Cancel all the TabContentsCollectors. + for (TabContentsCollectorMap::iterator i = + tab_contents_collector_map_.begin(); + i != tab_contents_collector_map_.end(); ++i) { + DCHECK(i->second); + i->second->Cancel(); + } + tab_contents_collector_map_.clear(); + + + // Finally destroy all the tab contents. + for (std::list::iterator i = tabs_to_destroy.begin(); + i != tabs_to_destroy.end(); ++i) { + (*i)->Destroy(); + } + // We are deleted at this point. +} + +void NavigationController::TabContentsWasDestroyed(TabContentsType type) { + TabContentsMap::iterator i = tab_contents_map_.find(type); + DCHECK(i != tab_contents_map_.end()); + tab_contents_map_.erase(i); + + // Make sure we cancel any collector for that TabContents. + CancelTabContentsCollection(type); + + // If that was the last tab to be destroyed, delete ourselves. + if (tab_contents_map_.empty()) + delete this; +} + +NavigationEntry* NavigationController::CreateNavigationEntry( + const GURL& url, const GURL& referrer, PageTransition::Type transition) { + GURL real_url = url; + TabContentsType type; + + // If the active contents supports |url|, use it. + // Note: in both cases, we give TabContents a chance to rewrite the URL. + TabContents* active = active_contents(); + if (active && active->SupportsURL(&real_url)) + type = active->type(); + else + type = TabContents::TypeForURL(&real_url); + + NavigationEntry* entry = new NavigationEntry(type, NULL, -1, real_url, + referrer, + std::wstring(), transition); + entry->set_display_url(url); + entry->set_user_typed_url(url); + if (url.SchemeIsFile()) { + entry->set_title(file_util::GetFilenameFromPath(UTF8ToWide(url.host() + + url.path()))); + } + return entry; +} + +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(entry)); + transient_entry_index_ = index; + active_contents_->NotifyNavigationStateChanged( + TabContents::INVALIDATE_EVERYTHING); +} + +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); + + LoadEntry(entry); +} + +void NavigationController::LoadURLLazily(const GURL& url, + const GURL& referrer, + PageTransition::Type type, + const std::wstring& title, + SkBitmap* icon) { + NavigationEntry* entry = CreateNavigationEntry(url, referrer, type); + entry->set_title(title); + if (icon) + entry->favicon().set_bitmap(*icon); + + DiscardNonCommittedEntriesInternal(); + pending_entry_ = entry; + load_pending_entry_when_active_ = true; +} + +bool NavigationController::LoadingURLLazily() { + return load_pending_entry_when_active_; +} + +const std::wstring& NavigationController::GetLazyTitle() const { + if (pending_entry_) + return pending_entry_->GetTitleForDisplay(); + else + return EmptyWString(); +} + +const SkBitmap& NavigationController::GetLazyFavIcon() const { + if (pending_entry_) { + return pending_entry_->favicon().bitmap(); + } else { + ResourceBundle &rb = ResourceBundle::GetSharedInstance(); + return *rb.GetBitmapNamed(IDR_DEFAULT_FAVICON); + } +} + +bool NavigationController::RendererDidNavigate( + const ViewHostMsg_FrameNavigate_Params& params, + LoadCommittedDetails* details) { + // Save the previous state before we clobber it. + if (GetLastCommittedEntry()) { + details->previous_url = GetLastCommittedEntry()->url(); + details->previous_entry_index = GetLastCommittedEntryIndex(); + } 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(active_contents_->GetSiteInstance()); + + // 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); + break; + case NavigationType::EXISTING_PAGE: + RendererDidNavigateToExistingPage(params); + break; + case NavigationType::SAME_PAGE: + RendererDidNavigateToSamePage(params); + break; + case NavigationType::IN_PAGE: + RendererDidNavigateInPage(params); + 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) && + !GetPendingEntry()) || + params.gesture == NavigationGestureAuto; + + // Now prep the rest of the details for the notification and broadcast. + details->entry = GetActiveEntry(); + details->is_in_page = IsURLInPageNavigation(params.url); + details->is_main_frame = PageTransition::IsMainFrame(params.transition); + details->serialized_security_info = params.security_info; + details->is_content_filtered = params.is_content_filtered; + NotifyNavigationEntryCommitted(details); + + // It is now a safe time to schedule collection for any tab contents of a + // different type, because a navigation is necessary to get back to them. + ScheduleTabContentsCollectionForInactiveTabs(); + return true; +} + +NavigationType::Type NavigationController::ClassifyNavigation( + const ViewHostMsg_FrameNavigate_Params& params) const { + // If a page makes a popup navigated to about blank, and then writes stuff + // like a subframe navigated to a real site, we'll get a notification with an + // invalid page ID. There's nothing we can do with these, so just ignore them. + if (params.page_id == -1) { + DCHECK(!GetActiveEntry()) << "Got an invalid page ID but we seem to be " + " navigated to a valid page. This should be impossible."; + return NavigationType::NAV_IGNORE; + } + + if (params.page_id > active_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( + active_contents_->type(), + active_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 (pending_entry_ && + pending_entry_->url() == params.url && + existing_entry != pending_entry_ && + pending_entry_->page_id() == -1 && + pending_entry_->url() == existing_entry->url()) { + // 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; + } + + 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; + } + + // 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; +} + +void NavigationController::RendererDidNavigateToNewPage( + const ViewHostMsg_FrameNavigate_Params& params) { + 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(NavigationEntry::NORMAL_PAGE); + } else { + new_entry = new NavigationEntry(active_contents_->type()); + } + + new_entry->set_url(params.url); + new_entry->set_page_id(params.page_id); + new_entry->set_transition_type(params.transition); + new_entry->set_site_instance(active_contents_->GetSiteInstance()); + new_entry->set_has_post_data(params.is_post); + + InsertEntry(new_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( + active_contents_->type(), + active_contents_->GetSiteInstance(), + params.page_id); + DCHECK(entry_index >= 0 && + entry_index < static_cast(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); + DCHECK(entry->site_instance() == NULL || + entry->site_instance() == active_contents_->GetSiteInstance()); + entry->set_site_instance(active_contents_->GetSiteInstance()); + + // 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(); + + last_committed_entry_index_ = entry_index; +} + +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( + active_contents_->type(), + active_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()); + + DiscardNonCommittedEntries(); +} + +void NavigationController::RendererDidNavigateInPage( + const ViewHostMsg_FrameNavigate_Params& params) { + 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( + active_contents_->type(), + active_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); + new_entry->set_url(params.url); + InsertEntry(new_entry); +} + +void NavigationController::RendererDidNavigateNewSubframe( + const ViewHostMsg_FrameNavigate_Params& params) { + // 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); + InsertEntry(new_entry); +} + +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( + active_contents_->type(), + active_contents_->GetSiteInstance(), + params.page_id); + if (entry_index < 0 || + entry_index >= static_cast(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; +} + +void NavigationController::CommitPendingEntry() { + DiscardTransientEntry(); + + if (!GetPendingEntry()) + 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 = GetLastCommittedEntryIndex(); + } 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 InsertEntry 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 WebContents, the IDs are generated by the + // renderer, so we can't do this. + details.type = NavigationType::NEW_PAGE; + pending_entry_->set_page_id(active_contents_->GetMaxPageID() + 1); + active_contents_->UpdateMaxPageID(pending_entry_->page_id()); + InsertEntry(new NavigationEntry(*pending_entry_)); + } + + // 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); +} + +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(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::DiscardNonCommittedEntries() { + bool transient = transient_entry_index_ != -1; + DiscardNonCommittedEntriesInternal(); + + // Synchronize the active_contents_ to the last committed entry. + NavigationEntry* last_entry = GetLastCommittedEntry(); + if (last_entry && last_entry->tab_type() != active_contents_->type()) { + TabContents* from_contents = active_contents_; + from_contents->set_is_active(false); + + // Switch back to the previous tab contents. + active_contents_ = GetTabContents(last_entry->tab_type()); + DCHECK(active_contents_); + + active_contents_->set_is_active(true); + + // If we are transitioning from two types of WebContents, we need to migrate + // the download shelf if it is visible. The download shelf may have been + // created before the error that caused us to discard the entry. + WebContents::MigrateShelfView(from_contents, active_contents_); + + if (from_contents->delegate()) { + from_contents->delegate()->ReplaceContents(from_contents, + active_contents_); + } + + // The entry we just discarded needed a different TabContents type. We no + // longer need it but we can't destroy it just yet because the TabContents + // is very likely involved in the current stack. + DCHECK(from_contents != active_contents_); + ScheduleTabContentsCollection(from_contents->type()); + } + + // If there was a transient entry, invalidate everything so the new active + // entry state is shown. + if (transient) { + active_contents_->NotifyNavigationStateChanged( + TabContents::INVALIDATE_EVERYTHING); + } +} + +void NavigationController::InsertEntry(NavigationEntry* entry) { + 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(entries_.size()); + + // Prune any entries which are in front of the current entry. + if (current_size > 0) { + int num_pruned = 0; + while (last_committed_entry_index_ < (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(entry)); + last_committed_entry_index_ = static_cast(entries_.size()) - 1; + + // This is a new page ID, so we need everybody to know about it. + active_contents_->UpdateMaxPageID(entry->page_id()); +} + +void NavigationController::SetWindowID(const SessionID& id) { + window_id_ = id; + NotificationService::current()->Notify(NOTIFY_TAB_PARENTED, + Source(this), + NotificationService::NoDetails()); +} + +void NavigationController::NavigateToPendingEntry(bool reload) { + TabContents* from_contents = active_contents_; + + // For session history navigations only the pending_entry_index_ is set. + if (!pending_entry_) { + DCHECK(pending_entry_index_ != -1); + pending_entry_ = entries_[pending_entry_index_].get(); + } + + // Reset the security states as any SSL error may have been resolved since we + // last visited that page. + pending_entry_->ssl() = NavigationEntry::SSLStatus(); + + if (from_contents && from_contents->type() != pending_entry_->tab_type()) + from_contents->set_is_active(false); + + TabContents* contents = GetTabContentsCreateIfNecessary(*pending_entry_); + + contents->set_is_active(true); + active_contents_ = contents; + + if (from_contents && from_contents != contents) { + if (from_contents->delegate()) + from_contents->delegate()->ReplaceContents(from_contents, contents); + + if (from_contents->type() != contents->type()) { + // The entry we just discarded needed a different TabContents type. We no + // longer need it but we can't destroy it just yet because the TabContents + // is very likely involved in the current stack. + ScheduleTabContentsCollection(from_contents->type()); + } + } + + NavigationEntry temp_entry(*pending_entry_); + if (!contents->NavigateToPendingEntry(reload)) + DiscardNonCommittedEntries(); +} + +void NavigationController::NotifyNavigationEntryCommitted( + LoadCommittedDetails* 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. + ssl_manager_.NavigationStateChanged(); + active_contents_->NotifyNavigationStateChanged( + TabContents::INVALIDATE_EVERYTHING); + + details->entry = GetActiveEntry(); + NotificationService::current()->Notify( + NOTIFY_NAV_ENTRY_COMMITTED, + Source(this), + Details(details)); +} + +TabContents* NavigationController::GetTabContentsCreateIfNecessary( + const NavigationEntry& entry) { + TabContents* contents = GetTabContents(entry.tab_type()); + if (!contents) { + contents = TabContents::CreateWithType(entry.tab_type(), profile_, + entry.site_instance()); + if (!contents->AsWebContents()) { + // Update the max page id, otherwise the newly created TabContents may + // have reset its max page id resulting in all new navigations. We only + // do this for non-WebContents as WebContents takes care of this via its + // SiteInstance. If this creation is the result of a restore, WebContents + // handles invoking ReservePageIDRange to make sure the renderer's + // max_page_id is updated to reflect the restored range of page ids. + int32 max_page_id = contents->GetMaxPageID(); + for (size_t i = 0; i < entries_.size(); ++i) { + if (entries_[i]->tab_type() == entry.tab_type()) + max_page_id = std::max(max_page_id, entries_[i]->page_id()); + } + contents->UpdateMaxPageID(max_page_id); + } + RegisterTabContents(contents); + } + + // We should not be trying to collect this tab contents. + DCHECK(tab_contents_collector_map_.find(contents->type()) == + tab_contents_collector_map_.end()); + + return contents; +} + +void NavigationController::RegisterTabContents(TabContents* some_contents) { + DCHECK(some_contents); + TabContentsType t = some_contents->type(); + TabContents* tc; + if ((tc = tab_contents_map_[t]) != some_contents) { + if (tc) { + NOTREACHED() << "Should not happen. Multiple contents for one type"; + } else { + tab_contents_map_[t] = some_contents; + some_contents->set_controller(this); + } + } + if (some_contents->AsDOMUIHost()) + some_contents->AsDOMUIHost()->AttachMessageHandlers(); +} + +// static +void NavigationController::DisablePromptOnRepost() { + check_for_repost_ = false; +} + +void NavigationController::SetActive(bool is_active) { + if (is_active) { + if (needs_reload_) { + LoadIfNecessary(); + } else if (load_pending_entry_when_active_) { + NavigateToPendingEntry(false); + load_pending_entry_when_active_ = false; + } + } +} + +void NavigationController::LoadIfNecessary() { + if (!needs_reload_) + return; + + needs_reload_ = false; + // 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(false); +} + +void NavigationController::NotifyEntryChanged(const NavigationEntry* entry, + int index) { + EntryChangedDetails det; + det.changed_entry = entry; + det.index = index; + NotificationService::current()->Notify(NOTIFY_NAV_ENTRY_CHANGED, + Source(this), + Details(&det)); +} + +NavigationController* NavigationController::Clone() { + NavigationController* nc = new NavigationController(NULL, profile_); + + if (GetEntryCount() == 0) + return nc; + + nc->needs_reload_ = true; + + nc->entries_.reserve(entries_.size()); + for (int i = 0, c = GetEntryCount(); i < c; ++i) { + nc->entries_.push_back(linked_ptr( + new NavigationEntry(*GetEntryAtIndex(i)))); + } + + nc->FinishRestore(last_committed_entry_index_); + + return nc; +} + +void NavigationController::ScheduleTabContentsCollectionForInactiveTabs() { + int index = GetCurrentEntryIndex(); + if (index < 0 || GetPendingEntryIndex() != -1) + return; + + TabContentsType active_type = GetEntryAtIndex(index)->tab_type(); + for (TabContentsMap::iterator i = tab_contents_map_.begin(); + i != tab_contents_map_.end(); ++i) { + if (i->first != active_type) + ScheduleTabContentsCollection(i->first); + } +} + +void NavigationController::ScheduleTabContentsCollection(TabContentsType t) { + TabContentsCollectorMap::const_iterator i = + tab_contents_collector_map_.find(t); + + // The tab contents is already scheduled for collection. + if (i != tab_contents_collector_map_.end()) + return; + + // If we currently don't have a TabContents for t, skip. + if (tab_contents_map_.find(t) == tab_contents_map_.end()) + return; + + // Create a collector and schedule it. + TabContentsCollector* tcc = new TabContentsCollector(this, t); + tab_contents_collector_map_[t] = tcc; + MessageLoop::current()->PostTask(FROM_HERE, tcc); +} + +void NavigationController::CancelTabContentsCollection(TabContentsType t) { + TabContentsCollectorMap::iterator i = tab_contents_collector_map_.find(t); + + if (i != tab_contents_collector_map_.end()) { + DCHECK(i->second); + i->second->Cancel(); + tab_contents_collector_map_.erase(i); + } +} + +void NavigationController::FinishRestore(int selected_index) { + DCHECK(selected_index >= 0 && selected_index < GetEntryCount()); + ConfigureEntriesForRestore(&entries_); + + set_max_restored_page_id(GetEntryCount()); + + last_committed_entry_index_ = selected_index; + + // Callers assume we have an active_contents after restoring, so set it now. + active_contents_ = GetTabContentsCreateIfNecessary(*entries_[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_ ); + transient_entry_index_ = -1; +} + +int NavigationController::GetEntryIndexWithPageID( + TabContentsType type, SiteInstance* instance, int32 page_id) const { + for (int i = static_cast(entries_.size()) - 1; i >= 0; --i) { + if ((entries_[i]->tab_type() == type) && + (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(); +} diff --git a/chrome/browser/tab_contents/navigation_controller.h b/chrome/browser/tab_contents/navigation_controller.h new file mode 100644 index 0000000..dac0a37 --- /dev/null +++ b/chrome/browser/tab_contents/navigation_controller.h @@ -0,0 +1,550 @@ +// 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. + +#ifndef CHROME_BROWSER_NAVIGATION_CONTROLLER_H_ +#define CHROME_BROWSER_NAVIGATION_CONTROLLER_H_ + +#include + +#include "base/linked_ptr.h" +#include "base/ref_counted.h" +#include "chrome/browser/sessions/session_id.h" +#include "chrome/browser/ssl_manager.h" +#include "chrome/browser/tab_contents/site_instance.h" +#include "chrome/browser/tab_contents/tab_contents_type.h" +#include "chrome/common/navigation_types.h" + +class GURL; +class Profile; +class TabContents; +class WebContents; +class TabContentsCollector; +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), + is_auto(false), + is_in_page(false), + is_main_frame(true) { + } + + // 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 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; + } + }; + + // 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; + }; + + // --------------------------------------------------------------------------- + + NavigationController(TabContents* initial_contents, Profile* profile); + + // Creates a NavigationController from the specified history. Processing + // for this is asynchronous and handled via the RestoreHelper (in + // navigation_controller.cc). + NavigationController( + Profile* profile, + const std::vector& navigations, + int selected_navigation); + ~NavigationController(); + + // Begin the destruction sequence for this NavigationController and all its + // registered tabs. The sequence is as follows: + // 1. All tabs are asked to Destroy themselves. + // 2. When each tab is finished Destroying, it will notify the controller. + // 3. Once all tabs are Destroyed, the NavigationController deletes itself. + // This ensures that all the TabContents outlive the NavigationController. + void Destroy(); + + // Clone the receiving navigation controller. Only the active tab contents is + // duplicated. + NavigationController* Clone(); + + // Returns the profile for this controller. It can never be NULL. + Profile* profile() const { + return profile_; + } + + // 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 the index of the last committed entry. + int GetLastCommittedEntryIndex() 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 GetEntryCount() const { + return static_cast(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 type, instance, and + // page_id, or -1 if not found. Use a NULL instance if the type is not + // TAB_CONTENTS_WEB. + int GetEntryIndexWithPageID(TabContentsType type, + SiteInstance* instance, + int32 page_id) const; + + // Return the entry with the corresponding type, instance, and page_id, or + // NULL if not found. Use a NULL instance if the type is not + // TAB_CONTENTS_WEB. + NavigationEntry* GetEntryWithPageID(TabContentsType type, + 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. Calling this may cause + // the active tab contents to switch if the current entry corresponds to a + // different tab contents type. + void DiscardNonCommittedEntries(); + + // Returns the pending entry corresponding to the navigation that is + // currently in progress, or null if there is none. + NavigationEntry* GetPendingEntry() 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 GetPendingEntryIndex() 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); + + // Load the specified URL the next time it becomes active. + void LoadURLLazily(const GURL& url, const GURL& referrer, + PageTransition::Type type, const std::wstring& title, + SkBitmap* icon); + + // 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); + + // 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 --------------------------------------------------------------- + + // Notifies the controller that a TabContents that it owns has been destroyed. + // This is part of the NavigationController's Destroy sequence. + void TabContentsWasDestroyed(TabContentsType type); + + // Returns the TabContents cached on this controller for the given type or + // NULL if there is none. + TabContents* GetTabContents(TabContentsType type); + + // Returns the currently-active TabContents associated with this controller. + // You should use GetActiveEntry instead of this in most cases. + TabContents* active_contents() const { + return active_contents_; + } + + // For use by TabContents ---------------------------------------------------- + + // Handles updating the navigation state after the renderer has navigated. + // This is used by the WebContents. 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. + bool RendererDidNavigate(const ViewHostMsg_FrameNavigate_Params& params, + 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; + + // Random data --------------------------------------------------------------- + + // Returns true if this NavigationController is is configured to load a URL + // lazily. If true, use GetLazyTitle() and GetLazyFavIcon() to discover the + // titles and favicons. Since no request was made, this is the only info + // we have about this page. This feature is used by web application clusters. + bool LoadingURLLazily(); + const std::wstring& GetLazyTitle() const; + const SkBitmap& GetLazyFavIcon() const; + + // 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_; } + + // Returns the largest restored page ID seen in this navigation controller, + // if it was restored from a previous session. (-1 otherwise) + int max_restored_page_id() const { return max_restored_page_id_; } + + // 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. + static void set_max_entry_count(size_t max_entry_count) { + max_entry_count_ = max_entry_count; + } + static size_t max_entry_count() { return max_entry_count_; } + + 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. + void RendererDidNavigateToNewPage( + const ViewHostMsg_FrameNavigate_Params& params); + void RendererDidNavigateToExistingPage( + const ViewHostMsg_FrameNavigate_Params& params); + void RendererDidNavigateToSamePage( + const ViewHostMsg_FrameNavigate_Params& params); + void RendererDidNavigateInPage( + const ViewHostMsg_FrameNavigate_Params& params); + void RendererDidNavigateNewSubframe( + const ViewHostMsg_FrameNavigate_Params& params); + bool RendererDidNavigateAutoSubframe( + const ViewHostMsg_FrameNavigate_Params& params); + + // Actually issues the navigation held in pending_entry. + void NavigateToPendingEntry(bool reload); + + // Allows the derived class to issue notifications that a load has been + // committed. This will fill in the active entry to the details structure. + void NotifyNavigationEntryCommitted(LoadCommittedDetails* details); + + // Returns the TabContents for the |entry|'s type. If the TabContents + // doesn't yet exist, it is created. If a new TabContents is created, its + // parent is |parent|. Becomes part of |entry|'s SiteInstance. + TabContents* GetTabContentsCreateIfNecessary(const NavigationEntry& entry); + + // Register the provided tab contents. This tab contents will be owned + // and deleted by this navigation controller + void RegisterTabContents(TabContents* some_contents); + + // Sets the max restored page ID this NavigationController has seen, if it + // was restored from a previous session. + void set_max_restored_page_id(int max_id) { max_restored_page_id_ = max_id; } + + NavigationEntry* CreateNavigationEntry(const GURL& url, const GURL& referrer, + PageTransition::Type transition); + + // Invokes ScheduleTabContentsCollection for all TabContents but the active + // one. + void ScheduleTabContentsCollectionForInactiveTabs(); + + // Schedule the TabContents currently allocated for |tc| for collection. + // The TabContents will be destroyed later from a different event. + void ScheduleTabContentsCollection(TabContentsType t); + + // Cancel the collection of the TabContents allocated for |tc|. This method + // is used when we keep using a TabContents because a provisional load failed. + void CancelTabContentsCollection(TabContentsType t); + + // 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. + void FinishRestore(int selected_index); + + // Inserts an entry after the current position, removing all entries after it. + // The new entry will become the active one. + void InsertEntry(NavigationEntry* entry); + + // Discards the pending and transient entries without updating + // active_contents_. + void DiscardNonCommittedEntriesInternal(); + + // Discards the transient entry without updating active_contents_. + void DiscardTransientEntry(); + + // --------------------------------------------------------------------------- + + // The user profile associated with this controller + Profile* profile_; + + // List of NavigationEntry for this tab + typedef std::vector > 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 poiting to an entry + // after the transient entry will become invalid if you navigate forward. + int transient_entry_index_; + + // Tab contents. One entry per type used. The tab controller owns + // every tab contents used. + typedef std::map TabContentsMap; + TabContentsMap tab_contents_map_; + + // A map of TabContentsType -> TabContentsCollector containing all the + // pending collectors. + typedef base::hash_map + TabContentsCollectorMap; + TabContentsCollectorMap tab_contents_collector_map_; + + // The tab contents that is currently active. + TabContents* active_contents_; + + // The max restored page ID in this controller, if it was restored. We must + // store this so that WebContents can tell any renderer in charge of one of + // the restored entries to update its max page ID. + int max_restored_page_id_; + + // Manages the SSL security UI + SSLManager ssl_manager_; + + // Whether we need to be reloaded when made active. + bool needs_reload_; + + // If true, the pending entry is lazy and should be loaded as soon as this + // controller becomes active. + bool load_pending_entry_when_active_; + + // 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. + const SessionID session_id_; + + // Unique identifier of the window we're in. Used by session restore. + SessionID window_id_; + + // 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_; + + DISALLOW_COPY_AND_ASSIGN(NavigationController); +}; + +#endif // CHROME_BROWSER_NAVIGATION_CONTROLLER_H_ diff --git a/chrome/browser/tab_contents/navigation_entry.cc b/chrome/browser/tab_contents/navigation_entry.cc new file mode 100644 index 0000000..bf0951c --- /dev/null +++ b/chrome/browser/tab_contents/navigation_entry.cc @@ -0,0 +1,64 @@ +// 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 "chrome/common/resource_bundle.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), + content_status_(NORMAL_CONTENT) { +} + +NavigationEntry::FaviconStatus::FaviconStatus() : valid_(false) { + ResourceBundle &rb = ResourceBundle::GetSharedInstance(); + bitmap_ = *rb.GetBitmapNamed(IDR_DEFAULT_FAVICON); +} + +NavigationEntry::NavigationEntry(TabContentsType type) + : unique_id_(GetUniqueID()), + tab_type_(type), + site_instance_(NULL), + page_type_(NORMAL_PAGE), + page_id_(-1), + transition_type_(PageTransition::LINK), + has_post_data_(false), + restored_(false) { +} + +NavigationEntry::NavigationEntry(TabContentsType type, + SiteInstance* instance, + int page_id, + const GURL& url, + const GURL& referrer, + const std::wstring& title, + PageTransition::Type transition_type) + : unique_id_(GetUniqueID()), + tab_type_(type), + site_instance_(instance), + page_type_(NORMAL_PAGE), + url_(url), + referrer_(referrer), + title_(title), + page_id_(page_id), + transition_type_(transition_type), + has_post_data_(false), + restored_(false) { +} + +const std::wstring& NavigationEntry::GetTitleForDisplay() { + if (title_.empty()) + return display_url_as_string_; + return title_; +} diff --git a/chrome/browser/tab_contents/navigation_entry.h b/chrome/browser/tab_contents/navigation_entry.h new file mode 100644 index 0000000..3ffbfdb --- /dev/null +++ b/chrome/browser/tab_contents/navigation_entry.h @@ -0,0 +1,399 @@ +// 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. + +#ifndef CHROME_BROWSER_NAVIGATION_ENTRY_H_ +#define CHROME_BROWSER_NAVIGATION_ENTRY_H_ + +#include "base/basictypes.h" +#include "base/scoped_ptr.h" +#include "chrome/app/theme/theme_resources.h" +#include "chrome/browser/security_style.h" +#include "chrome/browser/tab_contents/site_instance.h" +#include "chrome/browser/tab_contents/tab_contents_type.h" +#include "chrome/common/page_transition_types.h" +#include "googleurl/src/gurl.h" +#include "skia/include/SkBitmap.h" + +//////////////////////////////////////////////////////////////////////////////// +// +// 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 { + NORMAL_CONTENT = 0, // Neither of the 2 cases below. + MIXED_CONTENT = 1 << 0, // https page containing http resources. + UNSAFE_CONTENT = 1 << 1 // https page containing broken https resources. + }; + + SSLStatus(); + + 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_; + } + + // Mixed content means that this page which is served over https contains + // http sub-resources. + void set_has_mixed_content() { + content_status_ |= MIXED_CONTENT; + } + bool has_mixed_content() const { + return (content_status_ & MIXED_CONTENT) != 0; + } + + // Unsafe content means that this page is served over https but contains + // https sub-resources with cert errors. + void set_has_unsafe_content() { + content_status_ |= UNSAFE_CONTENT; + } + bool has_unsafe_content() const { + return (content_status_ & UNSAFE_CONTENT) != 0; + } + + // Raw accessors for all the content status flags. This contains a + // combination of any of the ContentStatusFlags defined above. It is used + // by the UI 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 content_status_; + + // Copy and assignment is explicitly allowed for this class. + }; + + // The type of the page an entry corresponds to. Used by ui tests. + enum PageType { + NORMAL_PAGE = 0, + ERROR_PAGE, + INTERSTITIAL_PAGE + }; + + // 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. + }; + + // --------------------------------------------------------------------------- + + explicit NavigationEntry(TabContentsType type); + NavigationEntry(TabContentsType type, + SiteInstance* instance, + int page_id, + const GURL& url, + const GURL& referrer, + const std::wstring& 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_; + } + + // Return the TabContents type required to display this entry. Immutable + // because a tab can never change its type. + TabContentsType tab_type() const { + return tab_type_; + } + + // 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) { + site_instance_ = 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 display_url() below for showing to + // the user. + void set_url(const GURL& url) { + url_ = url; + if (display_url_.is_empty()) { + // If there is no explicit display URL, then we'll display this URL. + display_url_as_string_ = UTF8ToWide(url_.spec()); + } + } + 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 display 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. + // + // display_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_display_url(const GURL& url) { + display_url_ = (url == url_) ? GURL() : url; + display_url_as_string_ = UTF8ToWide(url.spec()); + } + bool has_display_url() const { + return !display_url_.is_empty(); + } + const GURL& display_url() const { + return display_url_.is_empty() ? url_ : display_url_; + } + + // 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 std::wstring& title) { + title_ = title; + } + const std::wstring& 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 you write a custom TabContents and provide your own state make + // sure you have the ability to modify the format in the future while being + // 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_; + } + + // 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_; + } + + // Was this entry created from session/tab restore? If so this is true and + // gets set to false once we navigate to it. + // (See NavigationController::DidNavigateToEntry). + void set_restored(bool restored) { + restored_ = restored; + } + bool restored() const { + return restored_; + } + + // Returns the title to be displayed on the tab. This could be the title of + // the page if it is available or the URL. + const std::wstring& GetTitleForDisplay(); + + 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_; + TabContentsType tab_type_; + scoped_refptr site_instance_; + PageType page_type_; + GURL url_; + GURL referrer_; + + GURL display_url_; + + // We cache a copy of the display URL as a string so we don't have to + // convert the display URL to a wide string every time we paint. + std::wstring display_url_as_string_; + + std::wstring title_; + FaviconStatus favicon_; + std::string content_state_; + int32 page_id_; + SSLStatus ssl_; + PageTransition::Type transition_type_; + GURL user_typed_url_; + bool has_post_data_; + bool restored_; + + // Copy and assignment is explicitly allowed for this class. +}; + +#endif // CHROME_BROWSER_NAVIGATION_ENTRY_H_ diff --git a/chrome/browser/tab_contents/network_status_view.cc b/chrome/browser/tab_contents/network_status_view.cc new file mode 100644 index 0000000..2061ffe --- /dev/null +++ b/chrome/browser/tab_contents/network_status_view.cc @@ -0,0 +1,320 @@ +// 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/network_status_view.h" + +#include + +#include "base/string_util.h" +#include "base/thread.h" +#include "chrome/browser/browser.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/tab_contents/tab_contents_delegate.h" +#include "chrome/views/root_view.h" +#include "net/url_request/url_request.h" +#include "net/url_request/url_request_job.h" + +namespace { +const wchar_t kTitleMsg[] = L"Network Status"; +const wchar_t kStartTrackingMsg[] = L"Start I/O Tracking"; +const wchar_t kStopTrackingMsg[] = L"Stop I/O Tracking"; + +const wchar_t kShowIOStatusMsg[] = L"Show Current I/O Status"; +const wchar_t kClearOutputMsg[] = L"Clear Output"; + +// Returns a string representing the URL, handling the case where the spec +// is invalid. +std::wstring StringForURL(const GURL& url) { + if (url.is_valid()) + return UTF8ToWide(url.spec()); + return UTF8ToWide(url.possibly_invalid_spec()) + L" (invalid)"; +} + +std::wstring URLForJob(URLRequestJob* job) { + URLRequest* request = job->request(); + if (request) + return StringForURL(request->url()); + return std::wstring(L"(orphaned)"); +} + +} // namespace + +NetworkStatusView::NetworkStatusView() + : StatusView(TAB_CONTENTS_NETWORK_STATUS_VIEW) { + tracker_ = new JobTracker(this); +} + +NetworkStatusView::~NetworkStatusView() { + if (monospaced_font_) + DeleteObject(monospaced_font_); + + if (is_tracking_) { + tracker_->StopTracking(); + is_tracking_ = false; + } + + tracker_->DetachView(); +} + +const std::wstring NetworkStatusView::GetDefaultTitle() { + return kTitleMsg; +} + +void NetworkStatusView::OnCreate(const CRect& rect) { + CreateButton(IDC_CONFIG_TRACKING_BUTTON, kStartTrackingMsg); + CreateButton(IDC_CURRENT_STATUS_BUTTON, kShowIOStatusMsg); + CreateButton(IDC_CLEAR, kClearOutputMsg); + + is_tracking_ = false; + + // Initialize the text box for network tracking + // Don't worry about the size, we'll resize when we get WM_SIZE + text_area_.Create(m_hWnd, const_cast(rect), NULL, + WS_CHILD | WS_HSCROLL | WS_VSCROLL | + ES_MULTILINE | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0); + + // This raises the maximum number of chars from 32K to some large maximum, + // probably 2GB. 32K is not nearly enough for our use-case. + text_area_.SendMessageW(EM_SETLIMITTEXT, 0, 0); + + // make a monospaced font for the edit control + LOGFONT lf = {0}; + lf.lfHeight = 16; + wcscpy_s(lf.lfFaceName, LF_FACESIZE, L"Courier New"); + monospaced_font_ = CreateFontIndirect(&lf); + text_area_.SetFont(monospaced_font_); +} + +void NetworkStatusView::OnSize(const CRect& rect) { + // re-layout the edit control + text_area_.MoveWindow(rect); + + // re-layout the performance view + CRect new_rect(rect); + int list_width = rect.Width(); + int list_height = static_cast(rect.Height() / 5); + int page_width = rect.Width() / 2; + int page_height = static_cast(rect.Height() * 4 / 5); +} + +void NetworkStatusView::OnConfigTrackingClicked(UINT code, int button_id, + HWND hwnd) { + if (is_tracking_) { + tracker_->StopTracking(); + is_tracking_ = false; + + SetButtonText(IDC_CONFIG_TRACKING_BUTTON, kStartTrackingMsg); + } else { + tracker_->StartTracking(); + is_tracking_ = true; + + ClearTrackingResults(); + ShowTrackingResults(); + + SetButtonText(IDC_CONFIG_TRACKING_BUTTON, kStopTrackingMsg); + } +} + +void NetworkStatusView::OnCurrentStatusClicked(UINT code, int button_id, + HWND hwnd) { + ShowTrackingResults(); + if (is_tracking_) { + tracker_->ReportStatus(); + } +} + +void NetworkStatusView::OnClearClicked(UINT code, int button_id, HWND hwnd) { + ClearTrackingResults(); +} + +void NetworkStatusView::AppendText(const std::wstring& text) { + text_area_.AppendText(text.c_str()); +} + +void NetworkStatusView::HideTrackingResults() { + text_area_.ShowWindow(SW_HIDE); +} + +void NetworkStatusView::ShowTrackingResults() { + text_area_.ShowWindow(SW_SHOW); +} + +void NetworkStatusView::ClearTrackingResults() { + text_area_.SetSelAll(); + text_area_.Clear(); +} + +//----------------------------------------------------------------------------- + +// main thread: +NetworkStatusView::JobTracker::JobTracker(NetworkStatusView* view) + : view_(view), + view_message_loop_(MessageLoop::current()) { +} + +// main thread: +void NetworkStatusView::JobTracker::InvokeOnIOThread(void (JobTracker::*m)()) { + base::Thread* thread = g_browser_process->io_thread(); + if (!thread) + return; + thread->message_loop()->PostTask(FROM_HERE, NewRunnableMethod(this, m)); +} + +// main thread: +void NetworkStatusView::JobTracker::StartTracking() { + DCHECK(MessageLoop::current() == view_message_loop_); + DCHECK(view_); + InvokeOnIOThread(&JobTracker::OnStartTracking); +} + +// main thread: +void NetworkStatusView::JobTracker::StopTracking() { + DCHECK(MessageLoop::current() == view_message_loop_); + // The tracker should not be deleted before it is removed from observer + // list. + AddRef(); + InvokeOnIOThread(&JobTracker::OnStopTracking); +} + +// main thread: +void NetworkStatusView::JobTracker::ReportStatus() { + DCHECK(MessageLoop::current() == view_message_loop_); + InvokeOnIOThread(&JobTracker::OnReportStatus); +} + +// main thread: +void NetworkStatusView::JobTracker::OnAppendText(const std::wstring& text) { + DCHECK(MessageLoop::current() == view_message_loop_); + if (view_ && view_->is_tracking_) + view_->AppendText(text); +} + +// IO thread: +void NetworkStatusView::JobTracker::AppendText(const std::wstring& text) { + DCHECK(MessageLoop::current() != view_message_loop_); + view_message_loop_->PostTask(FROM_HERE, NewRunnableMethod( + this, &JobTracker::OnAppendText, text)); +} + +// IO thread: +void NetworkStatusView::JobTracker::OnStartTracking() { + DCHECK(MessageLoop::current() != view_message_loop_); + g_url_request_job_tracker.AddObserver(this); +} + +// IO thread: +void NetworkStatusView::JobTracker::OnStopTracking() { + DCHECK(MessageLoop::current() != view_message_loop_); + g_url_request_job_tracker.RemoveObserver(this); + // Balance the AddRef() in StopTracking() called in main thread. + Release(); +} + +// IO thread: +void NetworkStatusView::JobTracker::OnReportStatus() { + DCHECK(MessageLoop::current() != view_message_loop_); + + std::wstring text(L"\r\n===== Active Job Summary =====\r\n"); + + URLRequestJobTracker::JobIterator begin_job = + g_url_request_job_tracker.begin(); + URLRequestJobTracker::JobIterator end_job = g_url_request_job_tracker.end(); + int orphaned_count = 0; + int regular_count = 0; + for (URLRequestJobTracker::JobIterator cur = begin_job; + cur != end_job; ++cur) { + URLRequestJob* job = (*cur); + URLRequest* request = job->request(); + if (!request) { + orphaned_count++; + continue; + } + + regular_count++; + + // active state + if (job->is_done()) + text.append(L" Done: "); + else + text.append(L" Active: "); + + // URL + text.append(StringForURL(request->url())); + text.append(L"\r\n"); + } + + if (regular_count == 0) + text.append(L" (No active jobs)\r\n"); + + if (orphaned_count) { + wchar_t buf[64]; + swprintf(buf, arraysize(buf), L" %d orphaned jobs\r\n", orphaned_count); + text.append(buf); + } + + text.append(L"=====\r\n\r\n"); + AppendText(text); +} + +// IO thread: +void NetworkStatusView::JobTracker::OnJobAdded(URLRequestJob* job) { + DCHECK(MessageLoop::current() != view_message_loop_); + + std::wstring text(L"+ New job : "); + text.append(URLForJob(job)); + text.append(L"\r\n"); + AppendText(text); +} + +// IO thread: +void NetworkStatusView::JobTracker::OnJobRemoved(URLRequestJob* job) { + DCHECK(MessageLoop::current() != view_message_loop_); +} + +// IO thread: +void NetworkStatusView::JobTracker::OnJobDone(URLRequestJob* job, + const URLRequestStatus& status) { + DCHECK(MessageLoop::current() != view_message_loop_); + + std::wstring text; + if (status.is_success()) { + text.assign(L"- Complete: "); + } else if (status.status() == URLRequestStatus::CANCELED) { + text.assign(L"- Canceled: "); + } else if (status.status() == URLRequestStatus::HANDLED_EXTERNALLY) { + text.assign(L"- Handled externally: "); + } else { + wchar_t buf[32]; + swprintf(buf, arraysize(buf), L"Failed with %d: ", status.os_error()); + text.assign(buf); + } + + text.append(URLForJob(job)); + text.append(L"\r\n"); + AppendText(text); +} + +// IO thread: +void NetworkStatusView::JobTracker::OnJobRedirect(URLRequestJob* job, + const GURL& location, + int status_code) { + DCHECK(MessageLoop::current() != view_message_loop_); + + std::wstring text(L"- Redirect: "); + text.append(URLForJob(job)); + text.append(L"\r\n "); + + wchar_t buf[16]; + swprintf(buf, arraysize(buf), L"(%d) to: ", status_code); + text.append(buf); + + text.append(StringForURL(location)); + text.append(L"\r\n"); + AppendText(text); +} + +void NetworkStatusView::JobTracker::OnBytesRead(URLRequestJob* job, + int byte_count) { +} + diff --git a/chrome/browser/tab_contents/network_status_view.h b/chrome/browser/tab_contents/network_status_view.h new file mode 100644 index 0000000..5d6f53a9 --- /dev/null +++ b/chrome/browser/tab_contents/network_status_view.h @@ -0,0 +1,117 @@ +// 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. + +#ifndef CHROME_BROWSER_NETWORK_STATUS_VIEW_H__ +#define CHROME_BROWSER_NETWORK_STATUS_VIEW_H__ + +#include "base/basictypes.h" +#include "base/ref_counted.h" +#include "base/scoped_ptr.h" +#include "chrome/common/render_messages.h" +#include "chrome/browser/tab_contents/status_view.h" +#include "net/url_request/url_request_job_tracker.h" + +class MessageLoop; +class RenderProcessHost; +class NavigationPerformanceViewer; +class PageLoadView; + +class NetworkStatusView : public StatusView { + public: + // button types + enum { + IDC_CONFIG_TRACKING_BUTTON = 101, + IDC_CURRENT_STATUS_BUTTON, + IDC_CLEAR, + }; + + NetworkStatusView(); + virtual ~NetworkStatusView(); + + // TabContents overrides + virtual const std::wstring GetDefaultTitle(); + + // StatusView implementation + virtual void OnCreate(const CRect& rect); + virtual void OnSize(const CRect& rect); + + BEGIN_MSG_MAP(NetworkStatusView) + COMMAND_HANDLER_EX(IDC_CONFIG_TRACKING_BUTTON, BN_CLICKED, OnConfigTrackingClicked) + COMMAND_HANDLER_EX(IDC_CURRENT_STATUS_BUTTON, BN_CLICKED, OnCurrentStatusClicked) + COMMAND_HANDLER_EX(IDC_CLEAR, BN_CLICKED, OnClearClicked) + CHAIN_MSG_MAP(StatusView); + END_MSG_MAP() + + bool is_tracking() const { return is_tracking_; } + + private: + + // Event handlers + void OnConfigTrackingClicked(UINT code, int button_id, HWND hwnd); + void OnCurrentStatusClicked(UINT code, int button_id, HWND hwnd); + void OnClearClicked(UINT code, int button_id, HWND hwnd); + + void AppendText(const std::wstring& text); + + // Hide/Show tracking output window + void HideTrackingResults(); + void ShowTrackingResults(); + + // Clear tracking output + void ClearTrackingResults(); + + // A JobTracker is allocated to monitor network jobs running on the IO + // thread. This allows the NetworkStatusView to remain single-threaded. + class JobTracker : public URLRequestJobTracker::JobObserver, + public base::RefCountedThreadSafe { + public: + JobTracker(NetworkStatusView* view); + + // Called by the NetworkStatusView on the main application thread. + void StartTracking(); + void StopTracking(); + void ReportStatus(); + + // URLRequestJobTracker::JobObserver methods (called on the IO thread): + virtual void OnJobAdded(URLRequestJob* job); + virtual void OnJobRemoved(URLRequestJob* job); + virtual void OnJobDone(URLRequestJob* job, const URLRequestStatus& status); + virtual void OnJobRedirect(URLRequestJob* job, const GURL& location, + int status_code); + virtual void OnBytesRead(URLRequestJob* job, int byte_count); + + // The JobTracker may be deleted after NetworkStatusView is deleted. + void DetachView() { view_ = NULL; } + + private: + void InvokeOnIOThread(void (JobTracker::*method)()); + + // Called on the IO thread + void OnStartTracking(); + void OnStopTracking(); + void OnReportStatus(); + void AppendText(const std::wstring& text); + + // Called on the main thread + void OnAppendText(const std::wstring& text); + + NetworkStatusView* view_; + MessageLoop* view_message_loop_; + }; + friend class JobTracker; + + scoped_refptr tracker_; + + bool is_tracking_; + + // Textual output of network tracking + CEdit text_area_; + + HFONT monospaced_font_; + + DISALLOW_COPY_AND_ASSIGN(NetworkStatusView); +}; + +#endif // #ifndef CHROME_BROWSER_NETWORK_STATUS_VIEW_H__ + diff --git a/chrome/browser/tab_contents/page_navigator.h b/chrome/browser/tab_contents/page_navigator.h new file mode 100644 index 0000000..0152d39 --- /dev/null +++ b/chrome/browser/tab_contents/page_navigator.h @@ -0,0 +1,27 @@ +// 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. + +// 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_PAGE_NAVIGATOR_H__ +#define CHROME_BROWSER_PAGE_NAVIGATOR_H__ + +#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; +}; + +#endif // CHROME_BROWSER_PAGE_NAVIGATOR_H__ + diff --git a/chrome/browser/tab_contents/provisional_load_details.cc b/chrome/browser/tab_contents/provisional_load_details.cc new file mode 100644 index 0000000..1ec1206 --- /dev/null +++ b/chrome/browser/tab_contents/provisional_load_details.cc @@ -0,0 +1,25 @@ +// 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_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) + : error_code_(net::OK), + url_(url), + is_main_frame_(is_main_frame), + is_in_page_navigation_(is_in_page_navigation), + is_content_filtered_(is_content_filtered) { + SSLManager::DeserializeSecurityInfo(security_info, + &ssl_cert_id_, + &ssl_cert_status_, + &ssl_security_bits_); +} + diff --git a/chrome/browser/tab_contents/provisional_load_details.h b/chrome/browser/tab_contents/provisional_load_details.h new file mode 100644 index 0000000..5cb9501 --- /dev/null +++ b/chrome/browser/tab_contents/provisional_load_details.h @@ -0,0 +1,60 @@ +// 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. + +#ifndef CHROME_BROWSER_PROVISIONAL_LOAD_DETAILS_H_ +#define CHROME_BROWSER_PROVISIONAL_LOAD_DETAILS_H_ + +#include "base/basictypes.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); + virtual ~ProvisionalLoadDetails() { } + + void set_error_code(int error_code) { error_code_ = error_code; }; + int error_code() const { return error_code_; } + + 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_; } + + bool is_content_filtered() const { return is_content_filtered_; } + + private: + int error_code_; + GURL url_; + bool is_main_frame_; + bool is_in_page_navigation_; + int ssl_cert_id_; + int ssl_cert_status_; + int ssl_security_bits_; + bool is_content_filtered_; + + DISALLOW_COPY_AND_ASSIGN(ProvisionalLoadDetails); +}; + +#endif // CHROME_BROWSER_PROVISIONAL_LOAD_DETAILS_H_ + diff --git a/chrome/browser/tab_contents/site_instance.cc b/chrome/browser/tab_contents/site_instance.cc new file mode 100644 index 0000000..a303f85 --- /dev/null +++ b/chrome/browser/tab_contents/site_instance.cc @@ -0,0 +1,145 @@ +// 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/site_instance.h" + +#include "net/base/registry_controlled_domain.h" + +SiteInstance::~SiteInstance() { + // Now that no one is referencing us, we can safely remove ourselves from + // the BrowsingInstance. Any future visits to a page from this site + // (within the same BrowsingInstance) can safely create a new SiteInstance. + if (has_site_) + browsing_instance_->UnregisterSiteInstance(this); +} + +RenderProcessHost* SiteInstance::GetProcess() { + RenderProcessHost* process = NULL; + if (process_host_id_ != -1) + process = RenderProcessHost::FromID(process_host_id_); + + // Create a new process if ours went away or was reused. + if (!process) { + // See if we should reuse an old process + if (RenderProcessHost::ShouldTryToUseExistingProcessHost()) + process = RenderProcessHost::GetExistingProcessHost( + browsing_instance_->profile()); + + // Otherwise (or if that fails), create a new one. + if (!process) + process = new RenderProcessHost(browsing_instance_->profile()); + + // Update our host ID, so all pages in this SiteInstance will use + // the correct process. + process_host_id_ = process->host_id(); + + // Make sure the process starts at the right max_page_id + process->UpdateMaxPageID(max_page_id_); + } + DCHECK(process); + + return process; +} + +void SiteInstance::SetSite(const GURL& url) { + // A SiteInstance's site should not change. + // TODO(creis): When following links or script navigations, we can currently + // render pages from other sites in this SiteInstance. This will eventually + // be fixed, but until then, we should still not set the site of a + // SiteInstance more than once. + DCHECK(!has_site_); + + // Remember that this SiteInstance has been used to load a URL, even if the + // URL is invalid. + has_site_ = true; + site_ = GetSiteForURL(url); + + // Now that we have a site, register it with the BrowsingInstance. This + // ensures that we won't create another SiteInstance for this site within + // the same BrowsingInstance, because all same-site pages within a + // BrowsingInstance can script each other. + browsing_instance_->RegisterSiteInstance(this); +} + +bool SiteInstance::HasRelatedSiteInstance(const GURL& url) { + return browsing_instance_->HasSiteInstance(url); +} + +SiteInstance* SiteInstance::GetRelatedSiteInstance(const GURL& url) { + return browsing_instance_->GetSiteInstanceForURL(url); +} + +/*static*/ +SiteInstance* SiteInstance::CreateSiteInstance(Profile* profile) { + return new SiteInstance(new BrowsingInstance(profile)); +} + +/*static*/ +GURL SiteInstance::GetSiteForURL(const GURL& url) { + // URLs with no host should have an empty site. + GURL site; + + // TODO(creis): For many protocols, we should just treat the scheme as the + // site, since there is no host. e.g., file:, about:, chrome: + + // If the url has a host, then determine the site. + if (url.has_host()) { + // Only keep the scheme and registered domain as given by GetOrigin. This + // may also include a port, which we need to drop. + site = url.GetOrigin(); + + // Remove port, if any. + if (site.has_port()) { + GURL::Replacements rep; + rep.ClearPort(); + site = site.ReplaceComponents(rep); + } + + // If this URL has a registered domain, we only want to remember that part. + std::string domain = + net::RegistryControlledDomainService::GetDomainAndRegistry(url); + if (!domain.empty()) { + GURL::Replacements rep; + rep.SetHostStr(domain); + site = site.ReplaceComponents(rep); + } + } + return site; +} + +/*static*/ +bool SiteInstance::IsSameWebSite(const GURL& url1, const GURL& url2) { + // We infer web site boundaries based on the registered domain name of the + // top-level page and the scheme. We do not pay attention to the port if + // one is present, because pages served from different ports can still + // access each other if they change their document.domain variable. + + // We must treat javascript: URLs as part of the same site, regardless of + // the site. + if (url1.SchemeIs("javascript") || url2.SchemeIs("javascript")) + return true; + + // We treat about:crash, about:hang, and about:shorthang as the same site as + // any URL, since they are used as demos for crashing/hanging a process. + GURL about_crash = GURL("about:crash"); + GURL about_hang = GURL("about:hang"); + GURL about_shorthang = GURL("about:shorthang"); + if (url1 == about_crash || url2 == about_crash || + url1 == about_hang || url2 == about_hang || + url1 == about_shorthang || url2 == about_shorthang) + return true; + + // If either URL is invalid, they aren't part of the same site. + if (!url1.is_valid() || !url2.is_valid()) { + return false; + } + + // If the schemes differ, they aren't part of the same site. + if (url1.scheme() != url2.scheme()) { + return false; + } + + return net::RegistryControlledDomainService::SameDomainOrHost(url1, url2); +} + diff --git a/chrome/browser/tab_contents/site_instance.h b/chrome/browser/tab_contents/site_instance.h new file mode 100644 index 0000000..6759fe3 --- /dev/null +++ b/chrome/browser/tab_contents/site_instance.h @@ -0,0 +1,156 @@ +// 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. + +#ifndef CHROME_BROWSER_SITE_INSTANCE_H__ +#define CHROME_BROWSER_SITE_INSTANCE_H__ + +#include "chrome/browser/browsing_instance.h" +#include "chrome/browser/render_process_host.h" +#include "googleurl/src/gurl.h" + +/////////////////////////////////////////////////////////////////////////////// +// +// SiteInstance class +// +// A SiteInstance is a data structure that is associated with all pages in a +// given instance of a web site. Here, a web site is identified by its +// registered domain name and scheme. An instance includes all pages +// that are connected (i.e., either a user or a script navigated from one +// to the other). We represent instances using the BrowsingInstance class. +// +// In --process-per-tab, one SiteInstance is created for each tab (i.e., in the +// WebContents constructor), unless the tab is created by script (i.e., in +// WebContents::CreateNewView). This corresponds to one process per +// BrowsingInstance. +// +// In process-per-site-instance (the current default process model), +// SiteInstances are created (1) when the user manually creates a new tab +// (which also creates a new BrowsingInstance), and (2) when the user navigates +// across site boundaries (which uses the same BrowsingInstance). If the user +// navigates within a site, or opens links in new tabs within a site, the same +// SiteInstance is used. +// +// In --process-per-site, we consolidate all SiteInstances for a given site, +// throughout the entire profile. This ensures that only one process will be +// dedicated to each site. +// +// Each NavigationEntry for a WebContents points to the SiteInstance that +// rendered it. Each RenderViewHost also points to the SiteInstance that it is +// associated with. A SiteInstance keeps track of the number of these +// references and deletes itself when the count goes to zero. This means that +// a SiteInstance is only live as long as it is accessible, either from new +// tabs with no NavigationEntries or in NavigationEntries in the history. +// +/////////////////////////////////////////////////////////////////////////////// +class SiteInstance : public base::RefCounted { + public: + // Virtual to allow tests to extend it. + virtual ~SiteInstance(); + + // Get the BrowsingInstance to which this SiteInstance belongs. + BrowsingInstance* browsing_instance() { return browsing_instance_; } + + // Set / Get the host ID for this SiteInstance's current RenderProcessHost. + void set_process_host_id(int process_host_id) { + process_host_id_ = process_host_id; + } + int process_host_id() const { return process_host_id_; } + + // Update / Get the max page ID for this SiteInstance. + void UpdateMaxPageID(int32 page_id) { + if (page_id > max_page_id_) + max_page_id_ = page_id; + } + int32 max_page_id() const { return max_page_id_; } + + // Returns the current process being used to render pages in this + // SiteInstance. If the process has crashed or otherwise gone away, then + // this method will create a new process and update our host ID accordingly. + RenderProcessHost* GetProcess(); + + // Set / Get the web site that this SiteInstance is rendering pages for. + // This includes the scheme and registered domain, but not the port. If the + // URL does not have a valid registered domain, then the full hostname is + // stored. + void SetSite(const GURL& url); + const GURL& site() const { return site_; } + bool has_site() const { return has_site_; } + + // Returns whether there is currently a related SiteInstance (registered with + // BrowsingInstance) for the site of the given url. If so, we should try to + // avoid dedicating an unused SiteInstance to it (e.g., in a new tab). + bool HasRelatedSiteInstance(const GURL& url); + + // Gets a SiteInstance for the given URL that shares the current + // BrowsingInstance, creating a new SiteInstance if necessary. This ensures + // that a BrowsingInstance only has one SiteInstance per site, so that pages + // in a BrowsingInstance have the ability to script each other. Callers + // should ensure that this SiteInstance becomes ref counted, by storing it in + // a scoped_refptr. (By having this method, we can hide the BrowsingInstance + // class from the rest of the codebase.) + // TODO(creis): This may be an argument to build a pass_refptr class, as + // Darin suggests. + SiteInstance* GetRelatedSiteInstance(const GURL& url); + + // Factory method to create a new SiteInstance. This will create a new + // new BrowsingInstance, so it should only be used when creating a new tab + // from scratch (or similar circumstances). Callers should ensure that + // this SiteInstance becomes ref counted, by storing it in a scoped_refptr. + // TODO(creis): This may be an argument to build a pass_refptr class, as + // Darin suggests. + static SiteInstance* CreateSiteInstance(Profile* profile); + + // Returns the site for the given URL, which includes only the scheme and + // registered domain. Returns an empty GURL if the URL has no host. + static GURL GetSiteForURL(const GURL& url); + + // Return whether both URLs are part of the same web site, for the purpose of + // assigning them to processes accordingly. The decision is currently based + // on the registered domain of the URLs (google.com, bbc.co.uk), as well as + // the scheme (https, http). This ensures that two pages will be in + // the same process if they can communicate with other via JavaScript. + // (e.g., docs.google.com and mail.google.com have DOM access to each other + // if they both set their document.domain properties to google.com.) + static bool IsSameWebSite(const GURL& url1, const GURL& url2); + + protected: + friend class BrowsingInstance; + + // Create a new SiteInstance. Protected to give access to BrowsingInstance + // and tests; most callers should use CreateSiteInstance or + // GetRelatedSiteInstance instead. + SiteInstance(BrowsingInstance* browsing_instance) + : browsing_instance_(browsing_instance), + process_host_id_(-1), + max_page_id_(-1), + has_site_(false) { + DCHECK(browsing_instance); + } + + private: + // BrowsingInstance to which this SiteInstance belongs. + scoped_refptr browsing_instance_; + + // Current host ID for the RenderProcessHost that is rendering pages for this + // SiteInstance. If the rendering process dies, this host ID can be + // replaced when a new process is created, without losing the association + // between all pages in this SiteInstance. + int process_host_id_; + + // The current max_page_id in the SiteInstance's RenderProcessHost. If the + // rendering process dies, its replacement should start issuing page IDs that + // are larger than this value. + int32 max_page_id_; + + // The web site that this SiteInstance is rendering pages for. + GURL site_; + + // Whether SetSite has been called. + bool has_site_; + + DISALLOW_EVIL_CONSTRUCTORS(SiteInstance); +}; + +#endif // CHROME_BROWSER_SITE_INSTANCE_H__ + diff --git a/chrome/browser/tab_contents/status_view.cc b/chrome/browser/tab_contents/status_view.cc new file mode 100644 index 0000000..349ac53 --- /dev/null +++ b/chrome/browser/tab_contents/status_view.cc @@ -0,0 +1,74 @@ +// 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/status_view.h" + +const int StatusView::kLayoutPadding = 5; +const int StatusView::kButtonWidth = 200; +const int StatusView::kButtonHeight = 30; + +StatusView::StatusView(TabContentsType type) : TabContents(type) { +} + +StatusView::~StatusView() { + for (size_t i = 0; i < buttons_.size(); ++i) + delete buttons_[i].button; +} + +void StatusView::CreateView() { + Create(GetDesktopWindow()); +} + +LRESULT StatusView::OnCreate(LPCREATESTRUCT create_struct) { + CRect rect(kLayoutPadding, kButtonHeight + kLayoutPadding * 2, 200, 200); + OnCreate(rect); + return 0; +} + +void StatusView::OnSize(WPARAM wParam, const CSize& size) { + int start_x = kLayoutPadding; + int start_y = kButtonHeight + kLayoutPadding * 2; + int end_x = size.cx - kLayoutPadding; + int end_y = size.cy - kLayoutPadding; + CRect rect(start_x, start_y, end_x, end_y); + OnSize(rect); +} + +LRESULT StatusView::OnEraseBkgnd(HDC hdc) { + HBRUSH brush = GetSysColorBrush(COLOR_3DFACE); + HGDIOBJ old_brush = SelectObject(hdc, brush); + + RECT rc; + GetClientRect(&rc); + FillRect(hdc, &rc, brush); + + SelectObject(hdc, old_brush); + return 1; +} + +void StatusView::CreateButton(int id, const wchar_t* title) { + int button_count = static_cast(buttons_.size()); + int width_offset = + kLayoutPadding + button_count * (kButtonWidth + kLayoutPadding); + CRect rect(0, 0, kButtonWidth, kButtonHeight); + rect.OffsetRect(width_offset, kLayoutPadding); + ButtonInfo bi; + bi.button = new CButton(); + bi.id = id; + bi.button->Create(m_hWnd, rect, NULL, WS_CHILD | WS_VISIBLE, 0, bi.id); + bi.button->SetWindowText(title); + buttons_.push_back(bi); +} + +void StatusView::SetButtonText(int id, const wchar_t* title) { + for (size_t i = 0; i < buttons_.size(); ++i) { + if (buttons_[i].id == id) { + buttons_[i].button->SetWindowText(title); + return; + } + } + + DLOG(INFO) << "No button with id " << id << " to set title " << title; +} + diff --git a/chrome/browser/tab_contents/status_view.h b/chrome/browser/tab_contents/status_view.h new file mode 100644 index 0000000..e1f0204 --- /dev/null +++ b/chrome/browser/tab_contents/status_view.h @@ -0,0 +1,84 @@ +// 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. + +#ifndef CHROME_BROWSER_STATUS_VIEW_H__ +#define CHROME_BROWSER_STATUS_VIEW_H__ + +#include +#include +#include +#include +#include +#include + +#include "base/basictypes.h" +#include "chrome/browser/tab_contents/tab_contents.h" + +typedef CWinTraits + StatusViewTraits; + +// A base class for about:network, about:ipc etc. It handles creating a row of +// buttons at the top of the page. Derived classes get a rect of the remaining +// area and can create their own controls there. +class StatusView : public TabContents, + public CWindowImpl { + public: + StatusView(TabContentsType type); + + BEGIN_MSG_MAP(StatusView) + MSG_WM_CREATE(OnCreate) + MSG_WM_ERASEBKGND(OnEraseBkgnd) + MSG_WM_SIZE(OnSize) + END_MSG_MAP() + + virtual void CreateView(); + virtual HWND GetContainerHWND() const { return m_hWnd; } + + // Derived classes should implement the following functions + // TabContents override, to set the page title. + // virtual const std::wstring GetDefaultTitle() = 0; + // Gives a rect whose top left corner is after the buttons. The size of the + // controls that are added by derived classes will be set in the next OnSize, + // for now can use any height/width. + virtual void OnCreate(const CRect& rect) = 0; + virtual void OnSize(const CRect& rect) = 0; + + protected: + // Should be deleted via CloseContents. + virtual ~StatusView(); + + // Creates and adds a button to the top row of the page. Button ids should + // be unique and start at 101. + void CreateButton(int id, const wchar_t* title); + void SetButtonText(int id, const wchar_t* title); + + static const int kLayoutPadding; + static const int kButtonWidth; + static const int kButtonHeight; + + private: + // FocusTraversal Implementation + // TODO (jcampan): make focus traversal work + views::View* FindNextFocusableView(views::View* starting_view, bool reverse, + bool dont_loop) { + return NULL; + } + + // Event handlers + LRESULT OnCreate(LPCREATESTRUCT create_struct); + void OnSize(UINT size_command, const CSize& new_size); + LRESULT OnEraseBkgnd(HDC hdc); + + struct ButtonInfo { + CButton* button; + int id; + }; + + std::vector buttons_; + + DISALLOW_EVIL_CONSTRUCTORS(StatusView); +}; + +#endif // #ifndef CHROME_BROWSER_STATUS_VIEW_H__ + diff --git a/chrome/browser/tab_contents/tab_contents.cc b/chrome/browser/tab_contents/tab_contents.cc new file mode 100644 index 0000000..70988e2 --- /dev/null +++ b/chrome/browser/tab_contents/tab_contents.cc @@ -0,0 +1,605 @@ +// 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/tab_contents.h" + +#include "chrome/browser/cert_store.h" +#include "chrome/browser/views/download_shelf_view.h" +#include "chrome/browser/views/download_started_animation.h" +#include "chrome/browser/views/blocked_popup_container.h" +#include "chrome/browser/tab_contents/infobar_delegate.h" +#include "chrome/browser/tab_contents/navigation_entry.h" +#include "chrome/browser/tab_contents/tab_contents_delegate.h" +#include "chrome/browser/tab_contents/web_contents.h" +#include "chrome/common/l10n_util.h" +#include "chrome/common/pref_names.h" +#include "chrome/common/pref_service.h" +#include "chrome/views/native_scroll_bar.h" +#include "chrome/views/root_view.h" +#include "chrome/views/view.h" +#include "chrome/views/view_storage.h" +#include "chrome/views/widget.h" + +#include "generated_resources.h" + +namespace { + +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; +} + +} // namespace + +TabContents::TabContents(TabContentsType type) + : type_(type), + delegate_(NULL), + controller_(NULL), + is_loading_(false), + is_active_(true), + is_crashed_(false), + waiting_for_response_(false), + shelf_visible_(false), + max_page_id_(-1), + blocked_popups_(NULL), + capturing_contents_(false), + is_being_destroyed_(false) { + last_focused_view_storage_id_ = + views::ViewStorage::GetSharedInstance()->CreateStorageID(); +} + +TabContents::~TabContents() { + // Makes sure to remove any stored view we may still have in the ViewStorage. + // + // It is possible the view went away before us, so we only do this if the + // view is registered. + views::ViewStorage* view_storage = views::ViewStorage::GetSharedInstance(); + if (view_storage->RetrieveView(last_focused_view_storage_id_) != NULL) + view_storage->RemoveView(last_focused_view_storage_id_); +} + +// static +void TabContents::RegisterUserPrefs(PrefService* prefs) { + prefs->RegisterBooleanPref(prefs::kBlockPopups, false); +} + +void TabContents::CloseContents() { + // Destroy our NavigationController, which will Destroy all tabs it owns. + controller_->Destroy(); + // Note that the controller may have deleted us at this point, + // so don't touch any member variables here. +} + +void TabContents::Destroy() { + DCHECK(!is_being_destroyed_); + is_being_destroyed_ = true; + + // 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. + int size = static_cast(child_windows_.size()); + for (int i = size - 1; i >= 0; --i) { + ConstrainedWindow* window = child_windows_[i]; + if (window) + window->CloseConstrainedWindow(); + } + + // Notify any observer that have a reference on this tab contents. + NotificationService::current()->Notify(NOTIFY_TAB_CONTENTS_DESTROYED, + Source(this), + NotificationService::NoDetails()); + + // If we still have a window handle, destroy it. GetContainerHWND can return + // NULL if this contents was part of a window that closed. + if (GetContainerHWND()) + ::DestroyWindow(GetContainerHWND()); + + // Notify our NavigationController. Make sure we are deleted first, so + // that the controller is the last to die. + NavigationController* controller = controller_; + TabContentsType type = this->type(); + + delete this; + + controller->TabContentsWasDestroyed(type); +} + +void TabContents::SetupController(Profile* profile) { + DCHECK(!controller_); + controller_ = new NavigationController(this, profile); +} + +bool TabContents::SupportsURL(GURL* url) { + GURL u(*url); + if (TabContents::TypeForURL(&u) == type()) { + *url = u; + return true; + } + return false; +} + +const GURL& TabContents::GetURL() const { + // We may not have a navigation entry yet + NavigationEntry* entry = controller_->GetActiveEntry(); + return entry ? entry->display_url() : GURL::EmptyGURL(); +} + +const std::wstring& TabContents::GetTitle() const { + // 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. + // The exception is with transient pages, for which we really want to use + // their title, as they are not committed. + NavigationEntry* entry = controller_->GetTransientEntry(); + if (entry) + return entry->GetTitleForDisplay(); + + entry = controller_->GetLastCommittedEntry(); + if (entry) + return entry->GetTitleForDisplay(); + else if (controller_->LoadingURLLazily()) + return controller_->GetLazyTitle(); + return EmptyWString(); +} + +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 WebContents will also have site instances, except during + // testing. + if (GetSiteInstance()) + GetSiteInstance()->UpdateMaxPageID(page_id); + + if (AsWebContents()) + AsWebContents()->process()->UpdateMaxPageID(page_id); + else + max_page_id_ = std::max(max_page_id_, page_id); +} + +const std::wstring TabContents::GetDefaultTitle() const { + return l10n_util::GetString(IDS_DEFAULT_TAB_TITLE); +} + +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(); + else if (controller_->LoadingURLLazily()) + return controller_->GetLazyFavIcon(); + return SkBitmap(); +} + +SecurityStyle TabContents::GetSecurityStyle() const { + // We may not have a navigation entry yet. + NavigationEntry* entry = controller_->GetActiveEntry(); + return entry ? entry->ssl().security_style() : SECURITY_STYLE_UNKNOWN; +} + +bool TabContents::GetSSLEVText(std::wstring* ev_text, + std::wstring* ev_tooltip_text) const { + DCHECK(ev_text && ev_tooltip_text); + ev_text->clear(); + ev_tooltip_text->clear(); + + NavigationEntry* entry = controller_->GetActiveEntry(); + if (!entry || + net::IsCertStatusError(entry->ssl().cert_status()) || + ((entry->ssl().cert_status() & net::CERT_STATUS_IS_EV) == 0)) + return false; + + scoped_refptr cert; + CertStore::GetSharedInstance()->RetrieveCert(entry->ssl().cert_id(), &cert); + if (!cert.get()) { + NOTREACHED(); + return false; + } + + return SSLManager::GetEVCertNames(*cert, ev_text, ev_tooltip_text); +} + +void TabContents::SetIsCrashed(bool state) { + if (state == is_crashed_) + return; + + is_crashed_ = state; + if (delegate_) + delegate_->ContentsStateChanged(this); +} + +void TabContents::NotifyNavigationStateChanged(unsigned changed_flags) { + if (delegate_) + delegate_->NavigationStateChanged(this, changed_flags); +} + +void TabContents::DidBecomeSelected() { + if (controller_) + controller_->SetActive(true); + + // Invalidate all descendants. (take care to exclude invalidating ourselves!) + EnumChildWindows(GetContainerHWND(), InvalidateWindow, 0); +} + +void TabContents::WasHidden() { + NotificationService::current()->Notify(NOTIFY_TAB_CONTENTS_HIDDEN, + Source(this), + NotificationService::NoDetails()); +} + +void TabContents::Activate() { + if (delegate_) + delegate_->ActivateContents(this); +} + +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(bool reload) { + // Our benavior is just to report that the entry was committed. + controller()->GetPendingEntry()->set_title(GetDefaultTitle()); + controller()->CommitPendingEntry(); + return true; +} + +ConstrainedWindow* TabContents::CreateConstrainedDialog( + views::WindowDelegate* window_delegate, + views::View* contents_view) { + ConstrainedWindow* window = + ConstrainedWindow::CreateConstrainedDialog( + this, gfx::Rect(), contents_view, window_delegate); + child_windows_.push_back(window); + return window; +} + +void TabContents::AddNewContents(TabContents* new_contents, + WindowOpenDisposition disposition, + const gfx::Rect& initial_pos, + bool user_gesture) { + if (!delegate_) + return; + + if ((disposition == NEW_POPUP) && !user_gesture) { + // Unrequested popups from normal pages are constrained. + TabContents* popup_owner = this; + TabContents* our_owner = delegate_->GetConstrainingContents(this); + if (our_owner) + popup_owner = our_owner; + popup_owner->AddConstrainedPopup(new_contents, initial_pos); + } else { + new_contents->DisassociateFromPopupCount(); + + delegate_->AddNewContents(this, new_contents, disposition, initial_pos, + user_gesture); + + PopupNotificationVisibilityChanged(ShowingBlockedPopupNotification()); + } +} + +void TabContents::AddConstrainedPopup(TabContents* new_contents, + const gfx::Rect& initial_pos) { + if (!blocked_popups_) { + CRect client_rect; + GetClientRect(GetContainerHWND(), &client_rect); + gfx::Point anchor_position( + client_rect.Width() - + views::NativeScrollBar::GetVerticalScrollBarWidth(), + client_rect.Height()); + + blocked_popups_ = BlockedPopupContainer::Create( + this, profile(), anchor_position); + child_windows_.push_back(blocked_popups_); + } + + blocked_popups_->AddTabContents(new_contents, initial_pos); + PopupNotificationVisibilityChanged(ShowingBlockedPopupNotification()); +} + +void TabContents::CloseAllSuppressedPopups() { + if (blocked_popups_) + blocked_popups_->CloseAllPopups(); +} + +void TabContents::Focus() { + HWND container_hwnd = GetContainerHWND(); + if (!container_hwnd) + return; + + views::FocusManager* focus_manager = + views::FocusManager::GetFocusManager(container_hwnd); + DCHECK(focus_manager); + views::View* v = focus_manager->GetViewForWindow(container_hwnd, true); + DCHECK(v); + if (v) + v->RequestFocus(); +} + +void TabContents::StoreFocus() { + views::ViewStorage* view_storage = + views::ViewStorage::GetSharedInstance(); + + if (view_storage->RetrieveView(last_focused_view_storage_id_) != NULL) + view_storage->RemoveView(last_focused_view_storage_id_); + + views::FocusManager* focus_manager = + views::FocusManager::GetFocusManager(GetContainerHWND()); + if (focus_manager) { + // |focus_manager| can be NULL if the tab has been detached but still + // exists. + views::View* focused_view = focus_manager->GetFocusedView(); + if (focused_view) + view_storage->StoreView(last_focused_view_storage_id_, focused_view); + + // If the focus was on the page, explicitly clear the focus so that we + // don't end up with the focused HWND not part of the window hierarchy. + // TODO(brettw) this should move to the view somehow. + HWND container_hwnd = GetContainerHWND(); + if (container_hwnd) { + views::View* focused_view = focus_manager->GetFocusedView(); + if (focused_view) { + HWND hwnd = focused_view->GetRootView()->GetWidget()->GetHWND(); + if (container_hwnd == hwnd || ::IsChild(container_hwnd, hwnd)) + focus_manager->ClearFocus(); + } + } + } +} + +void TabContents::RestoreFocus() { + views::ViewStorage* view_storage = + views::ViewStorage::GetSharedInstance(); + views::View* last_focused_view = + view_storage->RetrieveView(last_focused_view_storage_id_); + + if (!last_focused_view) { + SetInitialFocus(); + } else { + views::FocusManager* focus_manager = + views::FocusManager::GetFocusManager(GetContainerHWND()); + + // If you hit this DCHECK, please report it to Jay (jcampan). + DCHECK(focus_manager != NULL) << "No focus manager when restoring focus."; + + if (focus_manager && focus_manager->ContainsView(last_focused_view)) { + last_focused_view->RequestFocus(); + } else { + // The focused view may not belong to the same window hierarchy (for + // example if the location bar was focused and the tab is dragged out). + // In that case we default to the default focus. + SetInitialFocus(); + } + view_storage->RemoveView(last_focused_view_storage_id_); + } +} + +void TabContents::SetInitialFocus() { + ::SetFocus(GetContainerHWND()); +} + +void TabContents::AddInfoBar(InfoBarDelegate* delegate) { + // 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 (int i = 0; i < infobar_delegate_count(); ++i) { + if (GetInfoBarDelegateAt(i)->EqualsDelegate(delegate)) + return; + } + + infobar_delegates_.push_back(delegate); + NotificationService::current()->Notify(NOTIFY_TAB_CONTENTS_INFOBAR_ADDED, + Source(this), + Details(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) { + DCHECK(controller()); + registrar_.Add(this, NOTIFY_NAV_ENTRY_COMMITTED, + Source(controller())); + } +} + +void TabContents::RemoveInfoBar(InfoBarDelegate* delegate) { + std::vector::iterator it = + find(infobar_delegates_.begin(), infobar_delegates_.end(), delegate); + if (it != infobar_delegates_.end()) { + InfoBarDelegate* delegate = *it; + NotificationService::current()->Notify(NOTIFY_TAB_CONTENTS_INFOBAR_REMOVED, + Source(this), + Details(delegate)); + infobar_delegates_.erase(it); + + // Remove ourselves as an observer if we are tracking no more InfoBars. + if (infobar_delegates_.empty()) { + registrar_.Remove(this, NOTIFY_NAV_ENTRY_COMMITTED, + Source(controller())); + } + } +} + +void TabContents::SetDownloadShelfVisible(bool visible) { + if (shelf_visible_ != visible) { + if (visible) { + // Invoke GetDownloadShelfView to force the shelf to be created. + GetDownloadShelfView(); + } + shelf_visible_ = visible; + + if (delegate_) + delegate_->ContentsStateChanged(this); + } + + // SetShelfVisible can force-close the shelf, so make sure we lay out + // everything correctly, as if the animation had finished. This doesn't + // matter for showing the shelf, as the show animation will do it. + ToolbarSizeChanged(false); +} + +void TabContents::ToolbarSizeChanged(bool is_animating) { + TabContentsDelegate* d = delegate(); + if (d) + d->ToolbarSizeChanged(this, is_animating); +} + +void TabContents::OnStartDownload(DownloadItem* download) { + DCHECK(download); + TabContents* tab_contents = this; + + // Download in a constrained popup is shown in the tab that opened it. + TabContents* constraining_tab = delegate()->GetConstrainingContents(this); + if (constraining_tab) + tab_contents = constraining_tab; + + // GetDownloadShelfView creates the download shelf if it was not yet created. + tab_contents->GetDownloadShelfView()->AddDownload(download); + tab_contents->SetDownloadShelfVisible(true); + + // This animation will delete itself when it finishes, or if we become hidden + // or destroyed. + if (IsWindowVisible(GetContainerHWND())) { // For minimized windows, unit + // tests, etc. + new DownloadStartedAnimation(tab_contents); + } +} + +DownloadShelfView* TabContents::GetDownloadShelfView() { + if (!download_shelf_view_.get()) { + download_shelf_view_.reset(new DownloadShelfView(this)); + // The TabContents owns the download-shelf. + download_shelf_view_->SetParentOwned(false); + } + return download_shelf_view_.get(); +} + +void TabContents::MigrateShelfViewFrom(TabContents* tab_contents) { + download_shelf_view_.reset(tab_contents->GetDownloadShelfView()); + download_shelf_view_->ChangeTabContents(tab_contents, this); + tab_contents->ReleaseDownloadShelfView(); +} + +void TabContents::WillClose(ConstrainedWindow* window) { + ConstrainedWindowList::iterator it = + find(child_windows_.begin(), child_windows_.end(), window); + if (it != child_windows_.end()) + child_windows_.erase(it); + + if (window == blocked_popups_) + blocked_popups_ = NULL; + + if (::IsWindow(GetContainerHWND())) { + CRect client_rect; + GetClientRect(GetContainerHWND(), &client_rect); + RepositionSupressedPopupsToFit( + gfx::Size(client_rect.Width(), client_rect.Height())); + } +} + +void TabContents::DidMoveOrResize(ConstrainedWindow* window) { + UpdateWindow(GetContainerHWND()); +} + +void TabContents::Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details) { + DCHECK(type == NOTIFY_NAV_ENTRY_COMMITTED); + DCHECK(controller() == Source(source).ptr()); + + NavigationController::LoadCommittedDetails& committed_details = + *(Details(details).ptr()); + ExpireInfoBars(committed_details); +} + +// static +void TabContents::MigrateShelfView(TabContents* from, TabContents* to) { + bool was_shelf_visible = from->IsDownloadShelfVisible(); + if (was_shelf_visible) + to->MigrateShelfViewFrom(from); + to->SetDownloadShelfVisible(was_shelf_visible); +} + +void TabContents::SetIsLoading(bool is_loading, + LoadNotificationDetails* details) { + if (is_loading == is_loading_) + return; + + is_loading_ = is_loading; + waiting_for_response_ = is_loading; + + // Suppress notifications for this TabContents if we are not active. + if (!is_active_) + return; + + if (delegate_) + delegate_->LoadingStateChanged(this); + + NotificationService::current()-> + Notify((is_loading ? NOTIFY_LOAD_START : NOTIFY_LOAD_STOP), + Source(this->controller()), + details ? Details(details) : + NotificationService::NoDetails()); +} + +// TODO(brettw) This should be on the WebContentsView. +void TabContents::RepositionSupressedPopupsToFit(const gfx::Size& new_size) { + // TODO(erg): There's no way to detect whether scroll bars are + // visible, so for beta, we're just going to assume that the + // vertical scroll bar is visible, and not care about covering up + // the horizontal scroll bar. Fixing this is half of + // http://b/1118139. + gfx::Point anchor_position( + new_size.width() - + views::NativeScrollBar::GetVerticalScrollBarWidth(), + new_size.height()); + + if (blocked_popups_) + blocked_popups_->RepositionConstrainedWindowTo(anchor_position); +} + +void TabContents::ReleaseDownloadShelfView() { + download_shelf_view_.release(); +} + +bool TabContents::ShowingBlockedPopupNotification() const { + return blocked_popups_ != NULL && + blocked_popups_->GetTabContentsCount() != 0; +} + +namespace { +bool TransitionIsReload(PageTransition::Type transition) { + return PageTransition::StripQualifier(transition) == PageTransition::RELOAD; +} +} + +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; + + for (int i = infobar_delegate_count() - 1; i >= 0; --i) { + InfoBarDelegate* delegate = GetInfoBarDelegateAt(i); + if (delegate->ShouldExpire(details)) + RemoveInfoBar(delegate); + } +} diff --git a/chrome/browser/tab_contents/tab_contents.h b/chrome/browser/tab_contents/tab_contents.h new file mode 100644 index 0000000..41ef34a --- /dev/null +++ b/chrome/browser/tab_contents/tab_contents.h @@ -0,0 +1,560 @@ +// 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. + +#ifndef CHROME_BROWSER_TAB_CONTENTS_H_ +#define CHROME_BROWSER_TAB_CONTENTS_H_ + +#include +#include + +#include "chrome/browser/autocomplete/autocomplete_edit.h" +#include "chrome/browser/tab_contents/constrained_window.h" +#include "chrome/browser/tab_contents/infobar_delegate.h" +#include "chrome/browser/tab_contents/navigation_controller.h" +#include "chrome/browser/tab_contents/page_navigator.h" +#include "chrome/browser/tab_contents/tab_contents_type.h" +#include "chrome/common/navigation_types.h" +#include "chrome/common/notification_registrar.h" +#include "chrome/common/property_bag.h" + +namespace gfx { +class Rect; +class Size; +} +namespace views { +class RootView; +class WindowDelegate; +} + +class BlockedPopupContainer; +class DOMUIHost; +class DownloadItem; +class DownloadShelfView; +class InfoBarView; +class LoadNotificationDetails; +class Profile; +class TabContentsDelegate; +class TabContentsFactory; +class SkBitmap; +class SiteInstance; +class WebContents; + +// Describes what goes in the main content area of a tab. For example, +// the WebContents is one such thing. +// +// When instantiating a new TabContents explicitly, the TabContents will not +// have an associated NavigationController. To setup a NavigationController +// for the TabContents, its SetupController method should be called. +// +// Once they reside within a NavigationController, TabContents objects are +// owned by that NavigationController. When the active TabContents within that +// NavigationController is closed, that TabContents destroys the +// NavigationController, which then destroys all of the TabContentses in it. +// +// NOTE: When the NavigationController is navigated to an URL corresponding to +// a different type of TabContents (see the TabContents::TypeForURL method), +// the NavigationController makes the active TabContents inactive, notifies the +// TabContentsDelegate that the TabContents is being replaced, and then +// activates the new TabContents. +class TabContents : public PageNavigator, + public NotificationObserver { + 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, // The URL has changed. + INVALIDATE_TITLE = 2, // The title has changed. + INVALIDATE_FAVICON = 4, // The favicon has changed. + INVALIDATE_LOAD = 8, // The loading state has changed + + // Helper for forcing a refresh. + INVALIDATE_EVERYTHING = 0xFFFFFFFF + }; + + static void RegisterUserPrefs(PrefService* prefs); + + // Factory ------------------------------------------------------------------- + // (implemented in tab_contents_factory.cc) + + // Creates a new TabContents of the given type. Will reuse the given + // instance's renderer, if it is not null. + static TabContents* CreateWithType(TabContentsType type, + Profile* profile, + SiteInstance* instance); + + // Returns the type of TabContents needed to handle the URL. |url| may + // end up being modified to contain the _real_ url being loaded if the + // parameter was an alias (such as about: urls and chrome- urls). + static TabContentsType TypeForURL(GURL* url); + + // This method can be used to register a new TabContents type dynamically, + // which can be very useful for unit testing. If factory is null, then the + // tab contents type is unregistered. Returns the previously registered + // factory for the given type or null if there was none. + static TabContentsFactory* RegisterFactory(TabContentsType type, + TabContentsFactory* factory); + + // Creation & destruction ---------------------------------------------------- + + // Request this tab to shut down. This kills the tab's NavigationController, + // which then Destroy()s all tabs it controls. + void CloseContents(); + + // Unregister/shut down any pending tasks involving this tab. + // This is called as the tab is shutting down, before the + // NavigationController (and consequently profile) are gone. + // + // If you override this, be sure to call this implementation at the end + // of yours. + // See also Close(). + virtual void Destroy(); + + // Intrinsic tab state ------------------------------------------------------- + + // Returns the type of tab this is. See also the As* functions following. + TabContentsType type() const { return type_; } + + // 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_; } + + // Returns this object as a WebContents if it is one, and NULL otherwise. + virtual WebContents* AsWebContents() { return NULL; } + + // Const version of above for situations where const TabContents*'s are used. + WebContents* AsWebContents() const { + return const_cast(this)->AsWebContents(); + } + + // Returns this object as a DOMUIHost if it is one, and NULL otherwise. + virtual DOMUIHost* AsDOMUIHost() { return NULL; } + + TabContentsDelegate* delegate() const { return delegate_; } + void set_delegate(TabContentsDelegate* d) { delegate_ = d; } + + // This can only be null if the TabContents has been created but + // SetupController has not been called. The controller should always outlive + // its TabContents. + NavigationController* controller() const { return controller_; } + void set_controller(NavigationController* c) { controller_ = c; } + + // Sets up a new NavigationController for this TabContents. + // |profile| is the user profile that should be associated with + // the new controller. + // + // TODO(brettw) this seems bogus and I couldn't find any legitimate need for + // it. I think it should be passed in the constructor. + void SetupController(Profile* profile); + + // Returns the user profile associated with this TabContents (via the + // NavigationController). This will return NULL if there isn't yet a + // NavigationController on this TabContents. + // TODO(darin): make it so that controller_ can never be null + Profile* profile() const { + return controller_ ? controller_->profile() : NULL; + } + + // Returns whether this tab contents supports the provided URL. By default, + // this method matches the tab contents type with the result of TypeForURL(). + // |url| points to the actual URL that will be used. It can be modified as + // needed. + // Override this method if your TabContents subclass supports various URL + // schemes but doesn't want to be the default handler for these schemes. + // For example, the NewTabUIContents overrides this method to support + // javascript: URLs. + virtual bool SupportsURL(GURL* url); + + // 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). + const GURL& GetURL() const; + virtual const std::wstring& GetTitle() const; + + // 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 + // WebContents, 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. WebContents overrides this to provide proper + // access to its site instance. + virtual SiteInstance* GetSiteInstance() const { return NULL; } + + // Initial title assigned to NavigationEntries from Navigate. + virtual const std::wstring GetDefaultTitle() 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() { return true; } + + // 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. + virtual SkBitmap GetFavIcon() 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() { return true; } + + // SSL related states. + SecurityStyle GetSecurityStyle() const; + + // Sets |ev_text| to the text that should be displayed in the EV label of + // the location bar and |ev_tooltip_text| to the tooltip for that label. + // Returns false and sets these strings to empty if the current page is either + // not served over HTTPS or if HTTPS does not use an EV cert. + bool GetSSLEVText(std::wstring* ev_text, std::wstring* ev_tooltip_text) const; + + // Returns a human-readable description the tab's loading state. + virtual std::wstring GetStatusText() const { return std::wstring(); } + + // 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_; } + + // 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 is_crashed_; } + void SetIsCrashed(bool state); + + // Set whether this tab contents is active. A tab content is active for a + // given tab if it is currently being used to display some contents. Note that + // this is different from whether a tab is selected. + bool is_active() const { return is_active_; } + void set_is_active(bool active) { is_active_ = active; } + + // 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(); + + // 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. + virtual void Activate(); + + // 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(bool reload); + + // Stop any pending navigation. + virtual void Stop() {} + + // TODO(erg): HACK ALERT! This was thrown together for beta and + // needs to be completely removed after we ship it. Right now, the + // cut/copy/paste menu items are always enabled and will send a + // cut/copy/paste command to the currently visible + // TabContents. Post-beta, this needs to be replaced with a unified + // interface for supporting cut/copy/paste, and managing who has + // cut/copy/paste focus. (http://b/1117225) + virtual void Cut() { } + virtual void Copy() { } + virtual void Paste() { } + + // Called on a TabContents when it isn't a popup, but a new window. + virtual void DisassociateFromPopupCount() { } + + // 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. The window + // is sized according to the preferred size of the content_view, and centered + // within the contents. + ConstrainedWindow* CreateConstrainedDialog( + views::WindowDelegate* window_delegate, + views::View* contents_view); + + // 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); + + // Builds a ConstrainedWindow* for the incoming |new_contents| and + // adds it to child_windows_. + void AddConstrainedPopup(TabContents* new_contents, + const gfx::Rect& initial_pos); + + // When a tab is closed, this method is called for all the remaining tabs. If + // they all return false or if no tabs are left, the window is closed. The + // default is to return true + virtual bool ShouldPreventWindowClose() { return true; } + + // Closes all constrained windows that represent web popups that have not yet + // been activated by the user and are as such auto-positioned in the bottom + // right of the screen. This is a quick way for users to "clean up" a flurry + // of unwanted popups. + void CloseAllSuppressedPopups(); + + // Called when the blocked popup notification is shown or hidden. + virtual void PopupNotificationVisibilityChanged(bool visible) { } + + // Views and focus ----------------------------------------------------------- + + // Returns the actual window that is focused when this TabContents is shown. + virtual HWND GetContentHWND() { + return GetContainerHWND(); + } + + // Tell the subclass to set up the view (e.g. create the container HWND if + // applicable) and any other create-time setup. + virtual void CreateView() {} + + // Returns the HWND associated with this TabContents. Outside of automation + // in the context of the UI, this is required to be implemented. + virtual HWND GetContainerHWND() const { return NULL; } + + // Returns the bounds of this TabContents in the screen coordinate system. + virtual void GetContainerBounds(gfx::Rect *out) const { + out->SetRect(0, 0, 0, 0); + } + + // Make the tab the focused window. + virtual void Focus(); + + // Stores the currently focused view. + virtual void StoreFocus(); + + // Restores focus to the last focus view. If StoreFocus has not yet been + // invoked, SetInitialFocus is invoked. + virtual void RestoreFocus(); + + // Invoked the first time this tab is getting the focus through TAB traversal. + // By default this does nothing, but is overridden to set the focus for the + // first element in the page. + // + // |reverse| indicates if the user is going forward or backward, so we know + // whether to set the first or last element focus. + // + // See also SetInitialFocus(no arg). + // FIXME(brettw) having two SetInitialFocus that do different things is silly. + virtual void SetInitialFocus(bool reverse) { } + + // TabContents that contain View hierarchy (such as NativeUIContents) should + // return their RootView. Other TabContents (such as WebContents) should + // return NULL. + // This is used by the focus manager to figure out what to focus when the tab + // is focused (when a tab with no view hierarchy is focused, the + // TabContentsContainerView is focused) and how to process tab events. If + // this returns NULL, the TabContents is supposed to know how to process TAB + // key events and is just sent the key messages. If this returns a RootView, + // the focus is passed to the RootView. + virtual views::RootView* GetContentsRootView() { return NULL; } + + // Infobars ------------------------------------------------------------------ + + // Adds an InfoBar for the specified |delegate|. + void AddInfoBar(InfoBarDelegate* delegate); + + // Removes the InfoBar for the specified |delegate|. + void RemoveInfoBar(InfoBarDelegate* delegate); + + // Enumeration and access functions. + int infobar_delegate_count() const { return infobar_delegates_.size(); } + InfoBarDelegate* GetInfoBarDelegateAt(int index) { + return infobar_delegates_.at(index); + } + + // Toolbars and such --------------------------------------------------------- + + // Returns whether the bookmark bar should be visible. + virtual bool IsBookmarkBarAlwaysVisible() { return false; } + + // Whether or not the shelf view is visible. + virtual void SetDownloadShelfVisible(bool visible); + bool IsDownloadShelfVisible() { return shelf_visible_; } + + // Notify our delegate that some of our content has animated. + void ToolbarSizeChanged(bool is_animating); + + // Displays the download shelf and animation when a download occurs. + void OnStartDownload(DownloadItem* download); + + // Returns the DownloadShelfView, creating it if necessary. + DownloadShelfView* GetDownloadShelfView(); + + // Transfer the shelf view from |tab_contents| to the receiving TabContents. + // |tab_contents| no longer owns the shelf after this call. The shelf is owned + // by the receiving TabContents. + void MigrateShelfViewFrom(TabContents* tab_contents); + + // Migrate the shelf view between 2 TabContents. This helper function is + // currently called by NavigationController::DiscardPendingEntry. We may + // want to generalize this if we need to migrate some other state. + static void MigrateShelfView(TabContents* from, TabContents* to); + + // Called when a ConstrainedWindow we own is about to be closed. + void WillClose(ConstrainedWindow* window); + + // Called when a ConstrainedWindow we own is moved or resized. + void DidMoveOrResize(ConstrainedWindow* window); + + protected: + // NotificationObserver implementation: + virtual void Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details); + + friend class NavigationController; + // Used to access the child_windows_ (ConstrainedWindowList) for testing + // automation purposes. + friend class AutomationProvider; + + explicit TabContents(TabContentsType type); + + // Some tab contents types need to override the type. + void set_type(TabContentsType type) { type_ = type; } + + // NOTE: the TabContents destructor can run after the NavigationController + // has gone away, so any complicated unregistering that expects the profile + // or other shared objects to still be around does not belong in a + // destructor. + // For those purposes, instead see Destroy(). + // Protected so that others don't try to delete this directly. + virtual ~TabContents(); + + // Sets focus to the tab contents window, but doesn't actuall set focus to + // a particular element in it (see also SetInitialFocus(bool) which does + // that in different circumstances). + // FIXME(brettw) having two SetInitialFocus that do different things is silly. + virtual void SetInitialFocus(); + + // 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. + virtual void SetIsLoading(bool is_loading, LoadNotificationDetails* details); + + // Called by a derived class when the TabContents is resized, causing + // suppressed constrained web popups to be repositioned to the new bounds + // if necessary. + void RepositionSupressedPopupsToFit(const gfx::Size& new_size); + + // Releases the download shelf. This method is used by MigrateShelfViewFrom. + // Sub-classes should clear any pointer they might keep to the shelf view and + // invoke TabContents::ReleaseDownloadShelfView(). + virtual void ReleaseDownloadShelfView(); + + // 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; } + + typedef std::vector ConstrainedWindowList; + ConstrainedWindowList child_windows_; + + // Whether we have a notification AND the notification owns popups windows. + // (We keep the notification object around even when it's not shown since it + // determines whether to show itself). + bool ShowingBlockedPopupNotification() const; + + private: + // 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); + + // Data ---------------------------------------------------------------------- + + TabContentsType type_; + + TabContentsDelegate* delegate_; + NavigationController* controller_; + + PropertyBag property_bag_; + + NotificationRegistrar registrar_; + + // Indicates whether we're currently loading a resource. + bool is_loading_; + + // See is_active() getter above. + bool is_active_; + + bool is_crashed_; // true if the tab is considered crashed. + + // See waiting_for_response() above. + bool waiting_for_response_; + + // The download shelf view (view at the bottom of the page). + scoped_ptr download_shelf_view_; + + // Whether the shelf view is visible. + bool shelf_visible_; + + // Indicates the largest PageID we've seen. This field is ignored if we are + // a WebContents, in which case the max page ID is stored separately with + // each SiteInstance. + int32 max_page_id_; + + // The id used in the ViewStorage to store the last focused view. + int last_focused_view_storage_id_; + + // See capturing_contents() above. + bool capturing_contents_; + + // ConstrainedWindow with additional methods for managing blocked + // popups. This pointer alsog goes in |child_windows_| for ownership, + // repositioning, etc. + BlockedPopupContainer* blocked_popups_; + + // Delegates for InfoBars associated with this TabContents. + std::vector infobar_delegates_; + + // See getter above. + bool is_being_destroyed_; + + DISALLOW_COPY_AND_ASSIGN(TabContents); +}; + +#endif // CHROME_BROWSER_TAB_CONTENTS_H_ diff --git a/chrome/browser/tab_contents/tab_contents_delegate.h b/chrome/browser/tab_contents/tab_contents_delegate.h new file mode 100644 index 0000000..773bb41 --- /dev/null +++ b/chrome/browser/tab_contents/tab_contents_delegate.h @@ -0,0 +1,150 @@ +// 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. + +#ifndef CHROME_BROWSER_TAB_CONTENTS_DELEGATE_H_ +#define CHROME_BROWSER_TAB_CONTENTS_DELEGATE_H_ + +// TODO(maruel): Remove once UINT and HWND are replaced / typedef. +#include + +#include "chrome/browser/tab_contents/page_navigator.h" +#include "chrome/common/navigation_types.h" + +namespace gfx { +class Point; +class Rect; +} + +class TabContents; +class HtmlDialogContentsDelegate; + +// Objects implement this interface to get notified about changes in the +// TabContents and to provide necessary functionality. +class TabContentsDelegate : public PageNavigator { + public: + // Opens a new URL inside the passed in TabContents, if source is 0 open + // in the current front-most tab. + virtual void OpenURLFromTab(TabContents* source, + const GURL& url, const GURL& referrer, + WindowOpenDisposition disposition, + PageTransition::Type transition) = 0; + + virtual void OpenURL(const GURL& url, const GURL& referrer, + WindowOpenDisposition disposition, + PageTransition::Type transition) + { + OpenURLFromTab(NULL, url, referrer, disposition, transition); + } + + // 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; + + // Called to cause the delegate to replace the source contents with the new + // contents. + virtual void ReplaceContents(TabContents* source, + TabContents* new_contents) = 0; + + // 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; + + // 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; + + // 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; + + // Called to determine if the TabContents is contained in a popup window. + virtual bool IsPopup(TabContents* source) = 0; + + // Returns the tab which contains the specified tab content if it is + // constrained, NULL otherwise. + virtual TabContents* GetConstrainingContents(TabContents* source) { + return NULL; + } + + // 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 starredness of the current URL changed. + virtual void URLStarredChanged(TabContents* source, bool starred) = 0; + + // Notification that the target URL has changed + virtual void UpdateTargetURL(TabContents* source, const GURL& url) = 0; + + // Notification that the target URL has changed + virtual void ContentsMouseEvent(TabContents* source, UINT message) { } + + // Request the delegate to change the zoom level of the current tab. + virtual void ContentsZoomChange(bool zoom_in) { } + + // Check whether this contents is inside a window dedicated to running a web + // application. + virtual bool IsApplication() { return false; } + + // Detach the given tab and convert it to a "webapp" view. The tab must be + // a WebContents with a valid WebApp set. + virtual void ConvertContentsToApplication(TabContents* source) { } + + // Informs the TabContentsDelegate that some of our state has changed + // for this tab. + virtual void ContentsStateChanged(TabContents* source) {} + + // Return whether this tab contents should have a URL bar. Only web contents + // opened with a minimal chrome and their popups can be displayed without a + // URL bar. + virtual bool ShouldDisplayURLField() { return true; } + + // Whether this tab can be blurred through a javascript obj.blur() + // call. ConstrainedWindows shouldn't be able to be blurred. + virtual bool CanBlur() const { return true; } + + // 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(HtmlDialogContentsDelegate* delegate, + void* parent_window) { } + + // 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) { + *proceed_to_fire_unload = true; + } + + // Send IPC to external host. Default implementation is do nothing. + virtual void ForwardMessageToExternalHost(const std::string& receiver, + const std::string& message) {}; + + // If the delegate is hosting tabs externally. + virtual bool IsExternalTabContainer() const { return false; } +}; + +#endif // CHROME_BROWSER_TAB_CONTENTS_DELEGATE_H_ diff --git a/chrome/browser/tab_contents/tab_contents_factory.cc b/chrome/browser/tab_contents/tab_contents_factory.cc new file mode 100644 index 0000000..5151555 --- /dev/null +++ b/chrome/browser/tab_contents/tab_contents_factory.cc @@ -0,0 +1,161 @@ +// 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 "base/string_util.h" +#include "chrome/browser/browser_about_handler.h" +#include "chrome/browser/browser_url_handler.h" +#include "chrome/browser/dom_ui/dom_ui_contents.h" +#include "chrome/browser/dom_ui/html_dialog_contents.h" +#include "chrome/browser/dom_ui/new_tab_ui.h" +#include "chrome/browser/profile.h" +#include "chrome/browser/render_process_host.h" +#include "chrome/browser/debugger/debugger_contents.h" +#include "chrome/browser/tab_contents/about_internets_status_view.h" +#include "chrome/browser/tab_contents/ipc_status_view.h" +#include "chrome/browser/tab_contents/native_ui_contents.h" +#include "chrome/browser/tab_contents/network_status_view.h" +#include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/tab_contents/tab_contents_factory.h" +#include "chrome/browser/tab_contents/view_source_contents.h" +#include "chrome/browser/tab_contents/web_contents.h" +#include "net/base/net_util.h" + +typedef std::map TabContentsFactoryMap; +static TabContentsFactoryMap* g_extra_types; // Only allocated if needed. + +// static +TabContentsType TabContentsFactory::NextUnusedType() { + int type = static_cast(TAB_CONTENTS_NUM_TYPES); + if (g_extra_types) { + for (TabContentsFactoryMap::iterator i = g_extra_types->begin(); + i != g_extra_types->end(); ++i) { + type = std::max(type, static_cast(i->first)); + } + } + return static_cast(type + 1); +} + +/*static*/ +TabContents* TabContents::CreateWithType(TabContentsType type, + Profile* profile, + SiteInstance* instance) { + TabContents* contents; + + switch (type) { + case TAB_CONTENTS_WEB: + contents = new WebContents(profile, instance, NULL, MSG_ROUTING_NONE, NULL); + break; + case TAB_CONTENTS_NETWORK_STATUS_VIEW: + contents = new NetworkStatusView(); + break; +#ifdef IPC_MESSAGE_LOG_ENABLED + case TAB_CONTENTS_IPC_STATUS_VIEW: + contents = new IPCStatusView(); + break; +#endif + case TAB_CONTENTS_NEW_TAB_UI: + contents = new NewTabUIContents(profile, instance, NULL); + break; + case TAB_CONTENTS_HTML_DIALOG: + contents = new HtmlDialogContents(profile, instance, NULL); + break; + case TAB_CONTENTS_NATIVE_UI: + contents = new NativeUIContents(profile); + break; + case TAB_CONTENTS_ABOUT_INTERNETS_STATUS_VIEW: + contents = new AboutInternetsStatusView(); + break; + case TAB_CONTENTS_VIEW_SOURCE: + contents = new ViewSourceContents(profile, instance); + break; + case TAB_CONTENTS_ABOUT_UI: + contents = new BrowserAboutHandler(profile, instance, NULL); + break; + case TAB_CONTENTS_DEBUGGER: + contents = new DebuggerContents(profile, instance); + break; + case TAB_CONTENTS_DOM_UI: + contents = new DOMUIContents(profile, instance, NULL); + break; + default: + if (g_extra_types) { + TabContentsFactoryMap::const_iterator it = g_extra_types->find(type); + if (it != g_extra_types->end()) { + contents = it->second->CreateInstance(); + break; + } + } + NOTREACHED() << "Don't know how to create tab contents of type " << type; + contents = NULL; + } + + if (contents) + contents->CreateView(); + + return contents; +} + +/*static*/ +TabContentsType TabContents::TypeForURL(GURL* url) { + DCHECK(url); + if (g_extra_types) { + TabContentsFactoryMap::const_iterator it = g_extra_types->begin(); + for (; it != g_extra_types->end(); ++it) { + if (it->second->CanHandleURL(*url)) + return it->first; + } + } + + // Try to handle as a browser URL. If successful, |url| will end up + // containing the real url being loaded (browser url's are just an alias). + TabContentsType type(TAB_CONTENTS_UNKNOWN_TYPE); + if (BrowserURLHandler::HandleBrowserURL(url, &type)) + return type; + + if (url->SchemeIs(NativeUIContents::GetScheme().c_str())) + return TAB_CONTENTS_NATIVE_UI; + + if (HtmlDialogContents::IsHtmlDialogUrl(*url)) + return TAB_CONTENTS_HTML_DIALOG; + + if (DebuggerContents::IsDebuggerUrl(*url)) + return TAB_CONTENTS_DEBUGGER; + + if (url->SchemeIs(DOMUIContents::GetScheme().c_str())) + return TAB_CONTENTS_DOM_UI; + + if (url->SchemeIs("view-source")) { + // Load the inner URL instead, but render it using a ViewSourceContents. + *url = GURL(url->path()); + return TAB_CONTENTS_VIEW_SOURCE; + } + + // NOTE: Even the empty string can be loaded by a WebContents. + return TAB_CONTENTS_WEB; +} + +/*static*/ +TabContentsFactory* TabContents::RegisterFactory(TabContentsType type, + TabContentsFactory* factory) { + if (!g_extra_types) + g_extra_types = new TabContentsFactoryMap; + + TabContentsFactory* prev_factory = NULL; + TabContentsFactoryMap::const_iterator prev = g_extra_types->find(type); + if (prev != g_extra_types->end()) + prev_factory = prev->second; + + if (factory) { + g_extra_types->insert(TabContentsFactoryMap::value_type(type, factory)); + } else { + g_extra_types->erase(type); + if (g_extra_types->empty()) { + delete g_extra_types; + g_extra_types = NULL; + } + } + + return prev_factory; +} + diff --git a/chrome/browser/tab_contents/tab_contents_factory.h b/chrome/browser/tab_contents/tab_contents_factory.h new file mode 100644 index 0000000..615c01d --- /dev/null +++ b/chrome/browser/tab_contents/tab_contents_factory.h @@ -0,0 +1,28 @@ +// 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. + +#ifndef CHROME_BROWSER_TAB_CONTENTS_FACTORY_H_ +#define CHROME_BROWSER_TAB_CONTENTS_FACTORY_H_ + +#include +#include "chrome/browser/tab_contents/tab_contents_type.h" + +class TabContents; + +// Extend from this class to implement a custom tab contents type. See +// TabContents::RegisterFactory. +class TabContentsFactory { + public: + // Returns the next unused TabContentsType after TAB_CONTENTS_NUM_TYPES. + static TabContentsType NextUnusedType(); + + // Returns a new TabContents instance of the associated type. + virtual TabContents* CreateInstance() = 0; + + // Returns true if this factory can be used to create a TabContents instance + // capable of handling the given URL. NOTE: the given url can be empty. + virtual bool CanHandleURL(const GURL& url) = 0; +}; + +#endif // CHROME_BROWSER_TAB_CONTENTS_FACTORY_H_ \ No newline at end of file diff --git a/chrome/browser/tab_contents/tab_contents_type.h b/chrome/browser/tab_contents/tab_contents_type.h new file mode 100644 index 0000000..86f38cc --- /dev/null +++ b/chrome/browser/tab_contents/tab_contents_type.h @@ -0,0 +1,31 @@ +// 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. + +#ifndef CHROME_BROWSER_TAB_CONTENTS_TYPE_H__ +#define CHROME_BROWSER_TAB_CONTENTS_TYPE_H__ + +// The different kinds of tab contents we support. This is declared outside of +// TabContents to eliminate the circular dependency between NavigationEntry +// (which requires a tab type) and TabContents (which requires a +// NavigationEntry). +enum TabContentsType { + TAB_CONTENTS_UNKNOWN_TYPE = 0, + TAB_CONTENTS_WEB, + TAB_CONTENTS_DOWNLOAD_VIEW, + TAB_CONTENTS_NETWORK_STATUS_VIEW, + TAB_CONTENTS_IPC_STATUS_VIEW, + TAB_CONTENTS_CHROME_VIEW_CONTENTS, + TAB_CONTENTS_NEW_TAB_UI, + TAB_CONTENTS_NATIVE_UI, + TAB_CONTENTS_ABOUT_INTERNETS_STATUS_VIEW, + TAB_CONTENTS_VIEW_SOURCE, + TAB_CONTENTS_HTML_DIALOG, + TAB_CONTENTS_ABOUT_UI, + TAB_CONTENTS_DEBUGGER, + TAB_CONTENTS_DOM_UI, + TAB_CONTENTS_NUM_TYPES +}; + +#endif // CHROME_BROWSER_TAB_CONTENTS_TYPE_H__ + diff --git a/chrome/browser/tab_contents/tab_util.cc b/chrome/browser/tab_contents/tab_util.cc new file mode 100644 index 0000000..a1a2f4e --- /dev/null +++ b/chrome/browser/tab_contents/tab_util.cc @@ -0,0 +1,39 @@ +// 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/tab_util.h" + +#include "chrome/browser/render_view_host.h" +#include "chrome/browser/render_process_host.h" +#include "chrome/browser/renderer_host/resource_dispatcher_host.h" +#include "chrome/browser/tab_contents/web_contents.h" +#include "net/url_request/url_request.h" + +bool tab_util::GetTabContentsID(URLRequest* request, + int* render_process_id, + int* render_view_id) { + + if (!request || !render_process_id || !render_view_id) + return false; + + ResourceDispatcherHost::ExtraRequestInfo* info = + ResourceDispatcherHost::ExtraInfoForRequest(request); + if (!info) + return false; + + *render_process_id = info->render_process_host_id; + *render_view_id = info->render_view_id; + return true; +} + +WebContents* tab_util::GetWebContentsByID(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 static_cast(render_view_host->delegate()); +} + diff --git a/chrome/browser/tab_contents/tab_util.h b/chrome/browser/tab_contents/tab_util.h new file mode 100644 index 0000000..6aa96f3 --- /dev/null +++ b/chrome/browser/tab_contents/tab_util.h @@ -0,0 +1,26 @@ +// 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. + +#ifndef CHROME_BROWSER_TAB_UTIL_H__ +#define CHROME_BROWSER_TAB_UTIL_H__ + +class URLRequest; +class WebContents; + +namespace tab_util { + +// Helper to get the IDs necessary for looking up a TabContents. +// Should only be called from the IO thread, since it accesses an URLRequest. +bool GetTabContentsID(URLRequest* request, int* render_process_host_id, + int* routing_id); + +// Helper to find the WebContents that originated the given request. Can be +// NULL if the tab has been closed or some other error occurs. +// Should only be called from the UI thread, since it accesses TabContent. +WebContents* GetWebContentsByID(int render_process_host_id, int routing_id); + +} // namespace tab_util + +#endif // CHROME_BROWSER_TAB_UTIL_H__ + diff --git a/chrome/browser/tab_contents/view_source_contents.cc b/chrome/browser/tab_contents/view_source_contents.cc new file mode 100644 index 0000000..849a005 --- /dev/null +++ b/chrome/browser/tab_contents/view_source_contents.cc @@ -0,0 +1,19 @@ +// 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/view_source_contents.h" + +#include "chrome/browser/tab_contents/navigation_entry.h" +#include "chrome/browser/render_view_host.h" + +ViewSourceContents::ViewSourceContents(Profile* profile, SiteInstance* instance) + : WebContents(profile, instance, NULL, MSG_ROUTING_NONE, NULL) { + set_type(TAB_CONTENTS_VIEW_SOURCE); +} + +void ViewSourceContents::RendererCreated(RenderViewHost* host) { + // Make sure the renderer is in view source mode. + host->Send(new ViewMsg_EnableViewSourceMode(host->routing_id())); +} + diff --git a/chrome/browser/tab_contents/view_source_contents.h b/chrome/browser/tab_contents/view_source_contents.h new file mode 100644 index 0000000..baeade6 --- /dev/null +++ b/chrome/browser/tab_contents/view_source_contents.h @@ -0,0 +1,27 @@ +// 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. + +#ifndef CHROME_BROWSER_VIEW_SOURCE_CONTENTS_H__ +#define CHROME_BROWSER_VIEW_SOURCE_CONTENTS_H__ + +#include "chrome/browser/tab_contents/web_contents.h" + +// We use this class to implement view-source: URLs. +class ViewSourceContents : public WebContents { + public: + ViewSourceContents(Profile* profile, SiteInstance* instance); + + protected: + // RenderViewHostDelegate overrides: + virtual void RendererCreated(RenderViewHost* host); + + // WebContents overrides: + // We override updating history with a no-op so these pages + // are not saved to history. + virtual void UpdateHistoryForNavigation(const GURL& url, + const ViewHostMsg_FrameNavigate_Params& params) { } +}; + +#endif // CHROME_BROWSER_VIEW_SOURCE_CONTENTS_H__ + diff --git a/chrome/browser/tab_contents/view_source_uitest.cc b/chrome/browser/tab_contents/view_source_uitest.cc new file mode 100644 index 0000000..73cc875 --- /dev/null +++ b/chrome/browser/tab_contents/view_source_uitest.cc @@ -0,0 +1,110 @@ +// 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/app/chrome_dll_resource.h" +#include "chrome/test/automation/browser_proxy.h" +#include "chrome/test/automation/tab_proxy.h" +#include "chrome/test/ui/ui_test.h" +#include "net/url_request/url_request_unittest.h" + +namespace { + +const wchar_t kDocRoot[] = L"chrome/test/data"; + +class ViewSourceTest : public UITest { + protected: + ViewSourceTest() : UITest() { + test_html_ = L"files/viewsource/test.html"; + } + + bool IsPageMenuCommandEnabled(int command) { + scoped_ptr window_proxy(automation()->GetBrowserWindow(0)); + if (!window_proxy.get()) + return false; + + bool timed_out; + return window_proxy->IsPageMenuCommandEnabledWithTimeout( + command, 5000, &timed_out) && !timed_out; + } + + protected: + std::wstring test_html_; +}; + +} // namespace + +// This test renders a page in view-source and then checks to see if a cookie +// set in the html was set successfully (it shouldn't because we rendered the +// page in view source) +TEST_F(ViewSourceTest, DoesBrowserRenderInViewSource) { + scoped_refptr server = + HTTPTestServer::CreateServer(kDocRoot); + ASSERT_TRUE(NULL != server.get()); + std::string cookie = "viewsource_cookie"; + std::string cookie_data = "foo"; + + // First we navigate to our view-source test page + GURL url = server->TestServerPageW(test_html_); + url = GURL("view-source:" + url.spec()); + scoped_ptr tab(GetActiveTab()); + tab->NavigateToURL(url); + Sleep(kWaitForActionMsec); + + // Try to retrieve the cookie that the page sets + // It should not be there (because we are in view-source mode + std::string cookie_found; + tab->GetCookieByName(url, cookie, &cookie_found); + EXPECT_NE(cookie_data, cookie_found); +} + +// This test renders a page normally and then renders the same page in +// view-source mode. This is done since we had a problem at one point during +// implementation of the view-source: prefix being consumed (removed from the +// URL) if the URL was not changed (apart from adding the view-source prefix) +TEST_F(ViewSourceTest, DoesBrowserConsumeViewSourcePrefix) { + scoped_refptr server = + HTTPTestServer::CreateServer(kDocRoot); + ASSERT_TRUE(NULL != server.get()); + + // First we navigate to google.html + GURL url = server->TestServerPageW(test_html_); + NavigateToURL(url); + + // Then we navigate to the SAME url but with the view-source: prefix + GURL url_viewsource = GURL("view-source:" + url.spec()); + NavigateToURL(url_viewsource); + + // The URL should still be prefixed with view-source: + EXPECT_EQ(url_viewsource.spec(), GetActiveTabURL().spec()); +} + +// Make sure that when looking at the actual page, we can select +// "View Source" from the Page menu. +TEST_F(ViewSourceTest, ViewSourceInPageMenuEnabledOnANormalPage) { + scoped_refptr server = + HTTPTestServer::CreateServer(kDocRoot); + ASSERT_TRUE(NULL != server.get()); + + // First we navigate to google.html + GURL url = server->TestServerPageW(test_html_); + NavigateToURL(url); + + EXPECT_TRUE(IsPageMenuCommandEnabled(IDC_VIEW_SOURCE)); +} + +// Make sure that when looking at the page source, we can't select +// "View Source" from the Page menu. +TEST_F(ViewSourceTest, ViewSourceInPageMenuDisabledWhileViewingSource) { + scoped_refptr server = + HTTPTestServer::CreateServer(kDocRoot); + ASSERT_TRUE(NULL != server.get()); + + // First we navigate to google.html + GURL url = server->TestServerPageW(test_html_); + GURL url_viewsource = GURL("view-source:" + url.spec()); + NavigateToURL(url_viewsource); + + EXPECT_FALSE(IsPageMenuCommandEnabled(IDC_VIEW_SOURCE)); +} + diff --git a/chrome/browser/tab_contents/web_contents.cc b/chrome/browser/tab_contents/web_contents.cc new file mode 100644 index 0000000..512c35a --- /dev/null +++ b/chrome/browser/tab_contents/web_contents.cc @@ -0,0 +1,1796 @@ +// 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/web_contents.h" + +#include "base/command_line.h" +#include "base/compiler_specific.h" +#include "base/file_version_info.h" +#include "base/process_util.h" +#include "chrome/app/locales/locale_settings.h" +#include "chrome/browser/autofill_manager.h" +#include "chrome/browser/bookmarks/bookmark_model.h" +#include "chrome/browser/browser.h" +#include "chrome/browser/cache_manager_host.h" +#include "chrome/browser/character_encoding.h" +#include "chrome/browser/dom_operation_notification_details.h" +#include "chrome/browser/download/download_manager.h" +#include "chrome/browser/download/download_request_manager.h" +#include "chrome/browser/find_notification_details.h" +#include "chrome/browser/google_util.h" +#include "chrome/browser/js_before_unload_handler.h" +#include "chrome/browser/jsmessage_box_handler.h" +#include "chrome/browser/load_from_memory_cache_details.h" +#include "chrome/browser/load_notification_details.h" +#include "chrome/browser/modal_html_dialog_delegate.h" +#include "chrome/browser/password_manager.h" +#include "chrome/browser/plugin_installer.h" +#include "chrome/browser/plugin_service.h" +#include "chrome/browser/printing/print_job.h" +#include "chrome/browser/render_view_host.h" +#include "chrome/browser/render_widget_host_view_win.h" // TODO(brettw) delete me. +#include "chrome/browser/tab_contents/navigation_entry.h" +#include "chrome/browser/tab_contents/web_contents_view.h" +#include "chrome/browser/tab_contents/web_contents_view_win.h" +#include "chrome/browser/template_url_fetcher.h" +#include "chrome/browser/template_url_model.h" +#include "chrome/browser/views/hung_renderer_view.h" // TODO(brettw) delete me. +#include "chrome/common/chrome_switches.h" +#include "chrome/common/l10n_util.h" +#include "chrome/common/pref_names.h" +#include "chrome/common/pref_service.h" +#include "chrome/common/resource_bundle.h" +#include "net/base/mime_util.h" +#include "net/base/registry_controlled_domain.h" +#include "webkit/glue/webkit_glue.h" + +#include "generated_resources.h" + +// Cross-Site Navigations +// +// If a WebContents 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 WebContents. 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 WebContents 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. + +using base::TimeDelta; +using base::TimeTicks; + +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; + +// Minimum amount of time in ms that has to elapse since the download shelf was +// shown for us to hide it when navigating away from the current page. +const int kDownloadShelfHideDelay = 5000; + +const wchar_t kLinkDoctorBaseURL[] = + L"http://linkhelp.clients.google.com/tbproxy/lh/fixurl"; + +// The printer icon in shell32.dll. That's a standard icon user will quickly +// recognize. +const int kShell32PrinterIcon = 17; + +// The list of prefs we want to observe. +const wchar_t* kPrefsToObserve[] = { + prefs::kAlternateErrorPagesEnabled, + prefs::kWebKitJavaEnabled, + prefs::kWebKitJavascriptEnabled, + prefs::kWebKitLoadsImagesAutomatically, + prefs::kWebKitPluginsEnabled, + prefs::kWebKitUsesUniversalDetector, + prefs::kWebKitSerifFontFamily, + prefs::kWebKitSansSerifFontFamily, + prefs::kWebKitFixedFontFamily, + prefs::kWebKitDefaultFontSize, + prefs::kWebKitDefaultFixedFontSize, + 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); + +// Limit on the number of suggestions to appear in the pop-up menu under an +// text input element in a form. +const int kMaxAutofillMenuItems = 6; + +void InitWebContentsClass() { + static bool web_contents_class_initialized = false; + if (!web_contents_class_initialized) { + ResourceBundle& rb = ResourceBundle::GetSharedInstance(); + web_contents_class_initialized = true; + } +} + +// Returns true if the entry's transition type is FORM_SUBMIT. +bool IsFormSubmit(const NavigationEntry* entry) { + return (PageTransition::StripQualifier(entry->transition_type()) == + PageTransition::FORM_SUBMIT); +} + +} // namespace + +class WebContents::GearsCreateShortcutCallbackFunctor { + public: + explicit GearsCreateShortcutCallbackFunctor(WebContents* contents) + : contents_(contents) {} + + void Run(const GearsShortcutData& shortcut_data, bool success) { + if (contents_) + contents_->OnGearsCreateShortcutDone(shortcut_data, success); + delete this; + } + void Cancel() { + contents_ = NULL; + } + + private: + WebContents* contents_; +}; + +WebContents::WebContents(Profile* profile, + SiteInstance* site_instance, + RenderViewHostFactory* render_view_factory, + int routing_id, + HANDLE modal_dialog_event) + : TabContents(TAB_CONTENTS_WEB), + view_(new WebContentsViewWin(this)), + ALLOW_THIS_IN_INITIALIZER_LIST( + render_manager_(render_view_factory, this, this)), + render_view_factory_(render_view_factory), + received_page_title_(false), + is_starred_(false), + printing_(*this), + notify_disconnection_(false), + message_box_active_(CreateEvent(NULL, TRUE, FALSE, NULL)), + ALLOW_THIS_IN_INITIALIZER_LIST(fav_icon_helper_(this)), + suppress_javascript_messages_(false), + load_state_(net::LOAD_STATE_IDLE) { + InitWebContentsClass(); + + pending_install_.page_id = 0; + pending_install_.callback_functor = NULL; + + render_manager_.Init(profile, site_instance, routing_id, modal_dialog_event); + + // Register for notifications about all interested prefs change. + PrefService* prefs = profile->GetPrefs(); + if (prefs) { + for (int i = 0; i < kPrefsToObserveLength; ++i) + prefs->AddPrefObserver(kPrefsToObserve[i], this); + } + + // Register for notifications about URL starredness changing on any profile. + NotificationService::current()-> + AddObserver(this, NOTIFY_URLS_STARRED, NotificationService::AllSources()); + NotificationService::current()-> + AddObserver(this, NOTIFY_BOOKMARK_MODEL_LOADED, + NotificationService::AllSources()); + NotificationService::current()-> + AddObserver(this, NOTIFY_RENDER_WIDGET_HOST_DESTROYED, + NotificationService::AllSources()); +} + +WebContents::~WebContents() { + if (web_app_.get()) + web_app_->RemoveObserver(this); + if (pending_install_.callback_functor) + pending_install_.callback_functor->Cancel(); + NotificationService::current()-> + RemoveObserver(this, NOTIFY_RENDER_WIDGET_HOST_DESTROYED, + NotificationService::AllSources()); +} + +// static +void WebContents::RegisterUserPrefs(PrefService* prefs) { + prefs->RegisterBooleanPref(prefs::kAlternateErrorPagesEnabled, true); + + WebPreferences pref_defaults; + prefs->RegisterBooleanPref(prefs::kWebKitJavascriptEnabled, + pref_defaults.javascript_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->RegisterBooleanPref(prefs::kWebKitDeveloperExtrasEnabled, + true); + prefs->RegisterBooleanPref(prefs::kWebKitTextAreasAreResizable, + pref_defaults.text_areas_are_resizable); + prefs->RegisterBooleanPref(prefs::kWebKitJavaEnabled, + pref_defaults.java_enabled); + + 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); +} + +AutofillManager* WebContents::GetAutofillManager() { + if (autofill_manager_.get() == NULL) + autofill_manager_.reset(new AutofillManager(this)); + return autofill_manager_.get(); +} + +PasswordManager* WebContents::GetPasswordManager() { + if (password_manager_.get() == NULL) + password_manager_.reset(new PasswordManager(this)); + return password_manager_.get(); +} + +PluginInstaller* WebContents::GetPluginInstaller() { + if (plugin_installer_.get() == NULL) + plugin_installer_.reset(new PluginInstaller(this)); + return plugin_installer_.get(); +} + +void WebContents::Destroy() { + // Tell the notification service we no longer want notifications. + NotificationService::current()-> + RemoveObserver(this, NOTIFY_URLS_STARRED, + NotificationService::AllSources()); + NotificationService::current()-> + RemoveObserver(this, NOTIFY_BOOKMARK_MODEL_LOADED, + NotificationService::AllSources()); + + // Destroy the print manager right now since a Print command may be pending. + printing_.Destroy(); + + // Unregister the notifications of all observed prefs change. + PrefService* prefs = profile()->GetPrefs(); + if (prefs) { + for (int i = 0; i < kPrefsToObserveLength; ++i) + prefs->RemovePrefObserver(kPrefsToObserve[i], this); + } + + cancelable_consumer_.CancelAllRequests(); + + // Clean up subwindows like plugins and the find in page bar. + view_->OnContentsDestroy(); + + NotifyDisconnected(); + HungRendererWarning::HideForWebContents(this); + render_manager_.Shutdown(); + TabContents::Destroy(); +} + +SiteInstance* WebContents::GetSiteInstance() const { + return render_manager_.current_host()->site_instance(); +} + +SkBitmap WebContents::GetFavIcon() { + if (web_app_.get() && IsWebApplicationActive()) { + SkBitmap app_icon = web_app_->GetFavIcon(); + if (!app_icon.isNull()) + return app_icon; + } + return TabContents::GetFavIcon(); +} + +std::wstring WebContents::GetStatusText() const { + if (!is_loading() || load_state_ == net::LOAD_STATE_IDLE) + return std::wstring(); + + switch (load_state_) { + case net::LOAD_STATE_WAITING_FOR_CACHE: + return l10n_util::GetString(IDS_LOAD_STATE_WAITING_FOR_CACHE); + case net::LOAD_STATE_RESOLVING_PROXY_FOR_URL: + return l10n_util::GetString(IDS_LOAD_STATE_RESOLVING_PROXY_FOR_URL); + case net::LOAD_STATE_RESOLVING_HOST: + return l10n_util::GetString(IDS_LOAD_STATE_RESOLVING_HOST); + case net::LOAD_STATE_CONNECTING: + return l10n_util::GetString(IDS_LOAD_STATE_CONNECTING); + case net::LOAD_STATE_SENDING_REQUEST: + return l10n_util::GetString(IDS_LOAD_STATE_SENDING_REQUEST); + case net::LOAD_STATE_WAITING_FOR_RESPONSE: + return l10n_util::GetStringF(IDS_LOAD_STATE_WAITING_FOR_RESPONSE, + load_state_host_); + // Ignore net::LOAD_STATE_READING_RESPONSE and net::LOAD_STATE_IDLE + } + + return std::wstring(); +} + +bool WebContents::NavigateToPendingEntry(bool reload) { + NavigationEntry* entry = controller()->GetPendingEntry(); + RenderViewHost* dest_render_view_host = render_manager_.Navigate(*entry); + if (!dest_render_view_host) + return false; // Unable to create the desired render view host. + + // Used for page load time metrics. + current_load_start_ = TimeTicks::Now(); + + // Navigate in the desired RenderViewHost. + dest_render_view_host->NavigateToEntry(*entry, reload); + + 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("javascript")) + return false; + } + + // Clear any provisional password saves - this stops password infobars + // showing up on pages the user navigates to while the right page is + // loading. + GetPasswordManager()->ClearProvisionalSave(); + + if (reload && !profile()->IsOffTheRecord()) { + HistoryService* history = + profile()->GetHistoryService(Profile::IMPLICIT_ACCESS); + if (history) + history->SetFavIconOutOfDateForPage(entry->url()); + } + + return true; +} + +void WebContents::Stop() { + render_manager_.Stop(); + printing_.Stop(); +} + +void WebContents::Cut() { + render_view_host()->Cut(); +} + +void WebContents::Copy() { + render_view_host()->Copy(); +} + +void WebContents::Paste() { + render_view_host()->Paste(); +} + +void WebContents::DisassociateFromPopupCount() { + render_view_host()->DisassociateFromPopupCount(); +} + +void WebContents::DidBecomeSelected() { + TabContents::DidBecomeSelected(); + + if (render_widget_host_view()) + render_widget_host_view()->DidBecomeSelected(); + + CacheManagerHost::GetInstance()->ObserveActivity(process()->host_id()); +} + +void WebContents::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 WebContents::Destroy(), which removes + // the |render_view_host()|; then when we actually destroy the window, + // OnWindowPosChanged() notices and calls HideContents() (which calls us). + if (render_widget_host_view()) + render_widget_host_view()->WasHidden(); + + // Loop through children and send WasHidden to them, too. + int count = static_cast(child_windows_.size()); + for (int i = count - 1; i >= 0; --i) { + ConstrainedWindow* window = child_windows_.at(i); + window->WasHidden(); + } + } + + TabContents::WasHidden(); +} + +void WebContents::ShowContents() { + if (render_widget_host_view()) + render_widget_host_view()->DidBecomeSelected(); + + // Loop through children and send DidBecomeSelected to them, too. + int count = static_cast(child_windows_.size()); + for (int i = count - 1; i >= 0; --i) { + ConstrainedWindow* window = child_windows_.at(i); + window->DidBecomeSelected(); + } +} + +void WebContents::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 WebContents. + WasHidden(); +} + +void WebContents::SetDownloadShelfVisible(bool visible) { + TabContents::SetDownloadShelfVisible(visible); + if (visible) { + // Always set this value as it reflects the last time the download shelf + // was made visible (even if it was already visible). + last_download_shelf_show_ = TimeTicks::Now(); + } +} + +void WebContents::PopupNotificationVisibilityChanged(bool visible) { + render_view_host()->PopupNotificationVisibilityChanged(visible); +} + +// Stupid view pass-throughs +void WebContents::CreateView() { + view_->CreateView(); +} +HWND WebContents::GetContainerHWND() const { + return view_->GetContainerHWND(); +} +HWND WebContents::GetContentHWND() { + return view_->GetContentHWND(); +} +void WebContents::GetContainerBounds(gfx::Rect *out) const { + view_->GetContainerBounds(out); +} + +void WebContents::SetWebApp(WebApp* web_app) { + if (web_app_.get()) { + web_app_->RemoveObserver(this); + web_app_->SetWebContents(NULL); + } + + web_app_ = web_app; + if (web_app) { + web_app->AddObserver(this); + web_app_->SetWebContents(this); + } +} + +bool WebContents::IsWebApplication() const { + return (web_app_.get() != NULL); +} + +void WebContents::CreateShortcut() { + NavigationEntry* entry = controller()->GetLastCommittedEntry(); + if (!entry) + return; + + // We only allow one pending install request. By resetting the page id we + // effectively cancel the pending install request. + pending_install_.page_id = entry->page_id(); + pending_install_.icon = GetFavIcon(); + pending_install_.title = GetTitle(); + pending_install_.url = GetURL(); + if (pending_install_.callback_functor) { + pending_install_.callback_functor->Cancel(); + pending_install_.callback_functor = NULL; + } + DCHECK(!pending_install_.icon.isNull()) << "Menu item should be disabled."; + if (pending_install_.title.empty()) + pending_install_.title = UTF8ToWide(GetURL().spec()); + + // Request the application info. When done OnDidGetApplicationInfo is invoked + // and we'll create the shortcut. + render_view_host()->GetApplicationInfo(pending_install_.page_id); +} + +void WebContents::OnJavaScriptMessageBoxClosed(IPC::Message* reply_msg, + bool success, + const std::wstring& prompt) { + last_javascript_message_dismissal_ = TimeTicks::Now(); + render_manager_.OnJavaScriptMessageBoxClosed(reply_msg, success, prompt); +} + +void WebContents::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; + } + + // Get our user preference state. + PrefService* prefs = profile()->GetPrefs(); + DCHECK(prefs); + + std::wstring suggest_name = + SavePackage::GetSuggestNameForSaveAs(prefs, GetTitle()); + + SavePackage::SavePackageParam param(contents_mime_type()); + param.prefs = prefs; + + // TODO(rocking): Use new asynchronous dialog boxes to prevent the SaveAs + // dialog blocking the UI thread. See bug: http://b/issue?id=1129694. + if (SavePackage::GetSaveInfo(suggest_name, GetContainerHWND(), ¶m, + profile()->GetDownloadManager())) + SavePage(param.saved_main_file_path, param.dir, param.save_type); +} + +void WebContents::SavePage(const std::wstring& main_file, + const std::wstring& dir_path, + SavePackage::SavePackageType save_type) { + // Stop the page from navigating. + Stop(); + + save_package_ = new SavePackage(this, save_type, main_file, dir_path); + save_package_->Init(); +} + +void WebContents::PrintPreview() { + // We can't print interstitial page for now. + if (showing_interstitial_page()) + return; + + // If we have a find bar it needs to hide as well. + view_->HideFindBar(false); + + // We don't show the print preview for the beta, only the print dialog. + printing_.ShowPrintDialog(); +} + +bool WebContents::PrintNow() { + // We can't print interstitial page for now. + if (showing_interstitial_page()) + return false; + + // If we have a find bar it needs to hide as well. + view_->HideFindBar(false); + + return printing_.PrintNow(); +} + +bool WebContents::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 WebContents::SetInitialFocus(bool reverse) { + render_view_host()->SetInitialFocus(reverse); +} + +// Notifies the RenderWidgetHost instance about the fact that the page is +// loading, or done loading and calls the base implementation. +void WebContents::SetIsLoading(bool is_loading, + LoadNotificationDetails* details) { + if (!is_loading) { + load_state_ = net::LOAD_STATE_IDLE; + load_state_host_.clear(); + } + + TabContents::SetIsLoading(is_loading, details); + render_manager_.SetIsLoading(is_loading); +} + +RenderViewHostDelegate::View* WebContents::GetViewDelegate() const { + return view_.get(); +} + +RenderViewHostDelegate::Save* WebContents::GetSaveDelegate() const { + return save_package_.get(); // May be NULL, but we can return NULL. +} + +Profile* WebContents::GetProfile() const { + return profile(); +} + +void WebContents::RendererReady(RenderViewHost* rvh) { + if (rvh != render_view_host()) { + // Don't notify the world, since this came from a renderer in the + // background. + return; + } + + NotifyConnected(); + SetIsCrashed(false); +} + +void WebContents::RendererGone(RenderViewHost* rvh) { + // Ask the print preview if this renderer was valuable. + if (!printing_.OnRendererGone(rvh)) + return; + if (rvh != render_view_host()) { + // The pending page's RenderViewHost is gone. + return; + } + + SetIsLoading(false, NULL); + NotifyDisconnected(); + SetIsCrashed(true); + + // Force an invalidation to render sad tab. The view will notice we crashed + // when it paints. + view_->Invalidate(); + + // Hide any visible hung renderer warning for this web contents' process. + HungRendererWarning::HideForWebContents(this); +} + +void WebContents::DidNavigate(RenderViewHost* rvh, + const ViewHostMsg_FrameNavigate_Params& params) { + if (PageTransition::IsMainFrame(params.transition)) + render_manager_.DidNavigateMainFrame(rvh); + + // We can't do anything about navigations when we're inactive. + if (!controller() || !is_active()) + return; + + // 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; + if (!controller()->RendererDidNavigate(params, &details)) + 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 WebContents::UpdateState(RenderViewHost* rvh, + int32 page_id, + const std::string& state) { + DCHECK(rvh == render_view_host()); + if (!controller()) + return; + + // 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( + type(), 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 WebContents::UpdateTitle(RenderViewHost* rvh, + int32 page_id, const std::wstring& title) { + if (!controller()) + return; + + // 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(type(), + GetSiteInstance(), + 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 WebContents::UpdateEncoding(RenderViewHost* render_view_host, + const std::wstring& encoding) { + set_encoding(encoding); +} + +void WebContents::UpdateTargetURL(int32 page_id, const GURL& url) { + if (delegate()) + delegate()->UpdateTargetURL(this, url); +} + +void WebContents::UpdateThumbnail(const GURL& url, + const SkBitmap& bitmap, + const ThumbnailScore& score) { + // Tell History about this thumbnail + HistoryService* hs; + if (!profile()->IsOffTheRecord() && + (hs = profile()->GetHistoryService(Profile::IMPLICIT_ACCESS))) { + hs->SetPageThumbnail(url, bitmap, score); + } +} + +void WebContents::Close(RenderViewHost* rvh) { + // Ignore this if it comes from a RenderViewHost that we aren't showing. + if (delegate() && rvh == render_view_host()) + delegate()->CloseContents(this); +} + +void WebContents::RequestMove(const gfx::Rect& new_bounds) { + if (delegate() && delegate()->IsPopup(this)) + delegate()->MoveContents(this, new_bounds); +} + +void WebContents::DidStartLoading(RenderViewHost* rvh, int32 page_id) { + SetIsLoading(true, NULL); +} + +void WebContents::DidStopLoading(RenderViewHost* rvh, int32 page_id) { + scoped_ptr details; + if (controller()) { + 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) { + scoped_ptr metrics( + base::ProcessMetrics::CreateProcessMetrics( + process()->process().handle())); + + TimeDelta elapsed = TimeTicks::Now() - current_load_start_; + + details.reset(new LoadNotificationDetails( + entry->display_url(), + entry->transition_type(), + elapsed, + controller(), + controller()->GetCurrentEntryIndex())); + } + } + + // Tell PasswordManager we've finished a page load, which serves as a + // green light to save pending passwords and reset itself. + GetPasswordManager()->DidStopLoading(); + + SetIsLoading(false, details.get()); +} + +void WebContents::DidStartProvisionalLoadForFrame( + RenderViewHost* render_view_host, + bool is_main_frame, + const GURL& url) { + ProvisionalLoadDetails details(is_main_frame, + controller()->IsURLInPageNavigation(url), + url, std::string(), false); + NotificationService::current()-> + Notify(NOTIFY_FRAME_PROVISIONAL_LOAD_START, + Source(controller()), + Details(&details)); +} + +void WebContents::DidRedirectProvisionalLoad(int32 page_id, + const GURL& source_url, + const GURL& target_url) { + NavigationEntry* entry; + if (page_id == -1) { + entry = controller()->GetPendingEntry(); + } else { + entry = controller()->GetEntryWithPageID(type(), GetSiteInstance(), + page_id); + } + if (!entry || entry->tab_type() != type() || entry->url() != source_url) + return; + entry->set_url(target_url); +} + +void WebContents::DidLoadResourceFromMemoryCache( + const GURL& url, + const std::string& security_info) { + if (!controller()) + return; + + // Send out a notification that we loaded a resource from our memory cache. + int cert_id, cert_status, security_bits; + SSLManager::DeserializeSecurityInfo(security_info, + &cert_id, &cert_status, + &security_bits); + LoadFromMemoryCacheDetails details(url, cert_id, cert_status); + + NotificationService::current()-> + Notify(NOTIFY_LOAD_FROM_MEMORY_CACHE, + Source(controller()), + Details(&details)); +} + +void WebContents::DidFailProvisionalLoadWithError( + RenderViewHost* render_view_host, + bool is_main_frame, + int error_code, + const GURL& url) { + if (!controller()) + return; + + 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()->GetPendingEntry(); + if (pending_entry && pending_entry->url() == url) + controller()->DiscardNonCommittedEntries(); + + 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(url), + url, std::string(), false); + details.set_error_code(error_code); + + NotificationService::current()-> + Notify(NOTIFY_FAIL_PROVISIONAL_LOAD_WITH_ERROR, + Source(controller()), + Details(&details)); +} + +void WebContents::UpdateFavIconURL(RenderViewHost* render_view_host, + int32 page_id, + const GURL& icon_url) { + fav_icon_helper_.SetFavIconURL(icon_url); +} + +void WebContents::DidDownloadImage( + RenderViewHost* render_view_host, + int id, + const GURL& image_url, + bool errored, + const SkBitmap& image) { + // A notification for downloading would be more flexible, but for now I'm + // forwarding to the two places that could possibly have initiated the + // request. If we end up with another place invoking DownloadImage, probably + // best to refactor out into notification service, or something similar. + if (errored) + fav_icon_helper_.FavIconDownloadFailed(id); + else + fav_icon_helper_.SetFavIcon(id, image_url, image); + if (web_app_.get() && !errored) + web_app_->SetImage(image_url, image); +} + +void WebContents::RequestOpenURL(const GURL& url, const GURL& referrer, + WindowOpenDisposition disposition) { + OpenURL(url, referrer, disposition, PageTransition::LINK); +} + +void WebContents::DomOperationResponse(const std::string& json_string, + int automation_id) { + DomOperationNotificationDetails details(json_string, automation_id); + NotificationService::current()->Notify( + NOTIFY_DOM_OPERATION_RESPONSE, Source(this), + Details(&details)); +} + +void WebContents::ProcessExternalHostMessage(const std::string& receiver, + const std::string& message) { + if (delegate()) + delegate()->ForwardMessageToExternalHost(receiver, message); +} + +void WebContents::GoToEntryAtOffset(int offset) { + if (!controller()) + return; + controller()->GoToOffset(offset); +} + +void WebContents::GetHistoryListCount(int* back_list_count, + int* forward_list_count) { + *back_list_count = 0; + *forward_list_count = 0; + + if (controller()) { + int current_index = controller()->GetLastCommittedEntryIndex(); + *back_list_count = current_index; + *forward_list_count = controller()->GetEntryCount() - current_index - 1; + } +} + +void WebContents::RunFileChooser(bool multiple_files, + const std::wstring& title, + const std::wstring& default_file, + const std::wstring& filter) { + HWND toplevel_hwnd = GetAncestor(GetContainerHWND(), GA_ROOT); + if (!select_file_dialog_.get()) + select_file_dialog_ = SelectFileDialog::Create(this); + SelectFileDialog::Type dialog_type = + multiple_files ? SelectFileDialog::SELECT_OPEN_MULTI_FILE : + SelectFileDialog::SELECT_OPEN_FILE; + select_file_dialog_->SelectFile(dialog_type, title, default_file, filter, + std::wstring(), toplevel_hwnd, NULL); +} + +void WebContents::RunJavaScriptMessage( + const std::wstring& message, + const std::wstring& default_prompt, + 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). + bool suppress_this_message = suppress_javascript_messages_; + if (delegate()) + suppress_this_message |= + (delegate()->GetConstrainingContents(this) != NULL); + + *did_suppress_message = suppress_this_message; + + if (!suppress_this_message) { + TimeDelta time_since_last_message( + 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 < + TimeDelta::FromMilliseconds(kJavascriptMessageExpectedDelay)) + show_suppress_checkbox = true; + + JavascriptMessageBoxHandler::RunJavascriptMessageBox(this, + 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". + OnJavaScriptMessageBoxClosed(reply_msg, false, L""); + } +} + +void WebContents::RunBeforeUnloadConfirm(const std::wstring& message, + IPC::Message* reply_msg) { + JavascriptBeforeUnloadHandler::RunBeforeUnloadDialog(this, message, + reply_msg); +} + +void WebContents::ShowModalHTMLDialog(const GURL& url, int width, int height, + const std::string& json_arguments, + IPC::Message* reply_msg) { + if (delegate()) { + ModalHtmlDialogDelegate* dialog_delegate = + new ModalHtmlDialogDelegate(url, width, height, json_arguments, + reply_msg, this); + delegate()->ShowHtmlDialog(dialog_delegate, NULL); + } +} + +void WebContents::PasswordFormsSeen( + const std::vector& forms) { + GetPasswordManager()->PasswordFormsSeen(forms); +} + +void WebContents::AutofillFormSubmitted( + const AutofillForm& form) { + GetAutofillManager()->AutofillFormSubmitted(form); +} + +void WebContents::GetAutofillSuggestions(const std::wstring& field_name, + const std::wstring& user_text, int64 node_id, int request_id) { + GetAutofillManager()->FetchValuesForName(field_name, user_text, + kMaxAutofillMenuItems, node_id, request_id); +} + +// Checks to see if we should generate a keyword based on the OSDD, and if +// necessary uses TemplateURLFetcher to download the OSDD and create a keyword. +void WebContents::PageHasOSDD(RenderViewHost* render_view_host, + int32 page_id, const GURL& url, + bool autodetected) { + // Make sure page_id is the current page, and the TemplateURLModel is loaded. + DCHECK(url.is_valid()); + if (!controller() || !IsActiveEntry(page_id)) + return; + TemplateURLModel* url_model = profile()->GetTemplateURLModel(); + if (!url_model) + return; + if (!url_model->loaded()) { + url_model->Load(); + return; + } + if (!profile()->GetTemplateURLFetcher()) + return; + + if (profile()->IsOffTheRecord()) + return; + + const NavigationEntry* entry = controller()->GetLastCommittedEntry(); + DCHECK(entry); + + const NavigationEntry* base_entry = entry; + if (IsFormSubmit(base_entry)) { + // If the current page is a form submit, find the last page that was not + // a form submit and use its url to generate the keyword from. + int index = controller()->GetLastCommittedEntryIndex() - 1; + while (index >= 0 && IsFormSubmit(controller()->GetEntryAtIndex(index))) + index--; + if (index >= 0) + base_entry = controller()->GetEntryAtIndex(index); + else + base_entry = NULL; + } + + // We want to use the user typed URL if available since that represents what + // the user typed to get here, and fall back on the regular URL if not. + if (!base_entry) + return; + GURL keyword_url = base_entry->user_typed_url().is_valid() ? + base_entry->user_typed_url() : base_entry->url(); + if (!keyword_url.is_valid()) + return; + std::wstring keyword = TemplateURLModel::GenerateKeyword(keyword_url, + autodetected); + if (keyword.empty()) + return; + const TemplateURL* template_url = + url_model->GetTemplateURLForKeyword(keyword); + if (template_url && (!template_url->safe_for_autoreplace() || + template_url->originating_url() == url)) { + // Either there is a user created TemplateURL for this keyword, or the + // keyword has the same OSDD url and we've parsed it. + return; + } + + // Download the OpenSearch description document. If this is successful a + // new keyword will be created when done. + profile()->GetTemplateURLFetcher()->ScheduleDownload( + keyword, + url, + base_entry->favicon().url(), + GetAncestor(view_->GetContainerHWND(), GA_ROOT), + autodetected); +} + +void WebContents::InspectElementReply(int num_resources) { + // We have received reply from inspect element request. Notify the + // automation provider in case we need to notify automation client. + NotificationService::current()-> + Notify(NOTIFY_DOM_INSPECT_ELEMENT_RESPONSE, Source(this), + Details(&num_resources)); +} + +void WebContents::DidGetPrintedPagesCount(int cookie, int number_pages) { + printing_.DidGetPrintedPagesCount(cookie, number_pages); +} + +void WebContents::DidPrintPage(const ViewHostMsg_DidPrintPage_Params& params) { + printing_.DidPrintPage(params); +} + +GURL WebContents::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(kLinkDoctorBaseURL)); + url = google_util::AppendGoogleTLDParam(url); + } + return url; +} + +WebPreferences WebContents::GetWebkitPrefs() { + // Initialize web_preferences_ to chrome defaults. + WebPreferences web_prefs; + PrefService* prefs = profile()->GetPrefs(); + + web_prefs.fixed_font_family = + prefs->GetString(prefs::kWebKitFixedFontFamily); + web_prefs.serif_font_family = + prefs->GetString(prefs::kWebKitSerifFontFamily); + web_prefs.sans_serif_font_family = + prefs->GetString(prefs::kWebKitSansSerifFontFamily); + if (prefs->GetBoolean(prefs::kWebKitStandardFontIsSerif)) + web_prefs.standard_font_family = web_prefs.serif_font_family; + else + web_prefs.standard_font_family = web_prefs.sans_serif_font_family; + web_prefs.cursive_font_family = + prefs->GetString(prefs::kWebKitCursiveFontFamily); + web_prefs.fantasy_font_family = + prefs->GetString(prefs::kWebKitFantasyFontFamily); + + web_prefs.default_font_size = + prefs->GetInteger(prefs::kWebKitDefaultFontSize); + web_prefs.default_fixed_font_size = + prefs->GetInteger(prefs::kWebKitDefaultFixedFontSize); + web_prefs.minimum_font_size = + prefs->GetInteger(prefs::kWebKitMinimumFontSize); + web_prefs.minimum_logical_font_size = + prefs->GetInteger(prefs::kWebKitMinimumLogicalFontSize); + + web_prefs.default_encoding = prefs->GetString(prefs::kDefaultCharset); + + web_prefs.javascript_can_open_windows_automatically = + prefs->GetBoolean(prefs::kWebKitJavascriptCanOpenWindowsAutomatically); + web_prefs.dom_paste_enabled = + prefs->GetBoolean(prefs::kWebKitDomPasteEnabled); + web_prefs.shrinks_standalone_images_to_fit = + prefs->GetBoolean(prefs::kWebKitShrinksStandaloneImagesToFit); + + { // Command line switches are used for preferences with no user interface. + CommandLine command_line; + web_prefs.developer_extras_enabled = + !command_line.HasSwitch(switches::kDisableDevTools) && + prefs->GetBoolean(prefs::kWebKitDeveloperExtrasEnabled); + web_prefs.javascript_enabled = + !command_line.HasSwitch(switches::kDisableJavaScript) && + prefs->GetBoolean(prefs::kWebKitJavascriptEnabled); + web_prefs.plugins_enabled = + !command_line.HasSwitch(switches::kDisablePlugins) && + prefs->GetBoolean(prefs::kWebKitPluginsEnabled); + web_prefs.java_enabled = + !command_line.HasSwitch(switches::kDisableJava) && + prefs->GetBoolean(prefs::kWebKitJavaEnabled); + web_prefs.loads_images_automatically = + !command_line.HasSwitch(switches::kDisableImages) && + prefs->GetBoolean(prefs::kWebKitLoadsImagesAutomatically); + web_prefs.uses_page_cache = + command_line.HasSwitch(switches::kEnableFastback); + } + + web_prefs.uses_universal_detector = + prefs->GetBoolean(prefs::kWebKitUsesUniversalDetector); + web_prefs.text_areas_are_resizable = + prefs->GetBoolean(prefs::kWebKitTextAreasAreResizable); + + // User CSS is currently disabled because it crashes chrome. See + // webkit/glue/webpreferences.h for more details. + + // Make sure we will set the default_encoding with canonical encoding name. + web_prefs.default_encoding = + CharacterEncoding::GetCanonicalEncodingNameByAliasName( + web_prefs.default_encoding); + if (web_prefs.default_encoding.empty()) { + prefs->ClearPref(prefs::kDefaultCharset); + web_prefs.default_encoding = prefs->GetString( + prefs::kDefaultCharset); + } + DCHECK(!web_prefs.default_encoding.empty()); + return web_prefs; +} + +void WebContents::OnMissingPluginStatus(int status) { + GetPluginInstaller()->OnMissingPluginStatus(status); +} + +void WebContents::OnCrashedPlugin(const FilePath& plugin_path) { + DCHECK(!plugin_path.value().empty()); + + std::wstring plugin_name = plugin_path.ToWStringHack(); + scoped_ptr version_info( + FileVersionInfo::CreateFileVersionInfo(plugin_path)); + if (version_info.get()) { + const std::wstring& product_name = version_info->product_name(); + if (!product_name.empty()) + plugin_name = product_name; + } + AddInfoBar(new SimpleAlertInfoBarDelegate( + this, l10n_util::GetStringF(IDS_PLUGIN_CRASHED_PROMPT, plugin_name), + NULL)); +} + +void WebContents::OnJSOutOfMemory() { + AddInfoBar(new SimpleAlertInfoBarDelegate( + this, l10n_util::GetString(IDS_JS_OUT_OF_MEMORY_PROMPT), NULL)); +} + +bool WebContents::CanBlur() const { + return delegate() ? delegate()->CanBlur() : true; +} + +void WebContents::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->UnloadListenerHasFired(); + + 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()) + HungRendererWarning::ShowForWebContents(this); +} + +void WebContents::RendererResponsive(RenderViewHost* render_view_host) { + HungRendererWarning::HideForWebContents(this); +} + +void WebContents::LoadStateChanged(const GURL& url, + net::LoadState load_state) { + load_state_ = load_state; + load_state_host_ = UTF8ToWide(url.host()); + if (load_state_ == net::LOAD_STATE_READING_RESPONSE) + SetNotWaitingForResponse(); + if (is_loading()) + NotifyNavigationStateChanged(INVALIDATE_LOAD); +} + +void WebContents::OnDidGetApplicationInfo( + int32 page_id, + const webkit_glue::WebApplicationInfo& info) { + if (pending_install_.page_id != page_id) + return; // The user clicked create on a separate page. Ignore this. + + pending_install_.callback_functor = + new GearsCreateShortcutCallbackFunctor(this); + GearsCreateShortcut( + info, pending_install_.title, pending_install_.url, pending_install_.icon, + NewCallback(pending_install_.callback_functor, + &GearsCreateShortcutCallbackFunctor::Run)); +} + +void WebContents::OnEnterOrSpace() { + // See comment in RenderViewHostDelegate::OnEnterOrSpace as to why we do this. + DownloadRequestManager* drm = g_browser_process->download_request_manager(); + if (drm) + drm->OnUserGesture(this); +} + +bool WebContents::CanTerminate() const { + if (!delegate()) + return true; + + return !delegate()->IsExternalTabContainer(); +} + +void WebContents::FileSelected(const std::wstring& path, void* params) { + render_view_host()->FileSelected(path); +} + +void WebContents::MultiFilesSelected(const std::vector& files, + void* params) { + render_view_host()->MultiFilesSelected(files); +} + + +void WebContents::FileSelectionCanceled(void* params) { + // If the user cancels choosing a file to upload we pass back an + // empty vector. + render_view_host()->MultiFilesSelected(std::vector()); +} + +void WebContents::BeforeUnloadFiredFromRenderManager( + bool proceed, + bool* proceed_to_fire_unload) { + if (delegate()) + delegate()->BeforeUnloadFired(this, proceed, proceed_to_fire_unload); +} + +void WebContents::UpdateRenderViewSizeForRenderManager() { + // TODO(brettw) this is a hack. See WebContentsView::SizeContents. + view_->SizeContents(view_->GetContainerSize()); +} + +bool WebContents::CreateRenderViewForRenderManager( + RenderViewHost* render_view_host) { + RenderWidgetHostView* rvh_view = view_->CreateViewForWidget(render_view_host); + + bool ok = render_view_host->CreateRenderView(); + if (ok) { + // TODO(brettw) hack alert. Do this in some cross platform way, or move + // to the view? + RenderWidgetHostViewWin* rvh_view_win = + static_cast(rvh_view); + rvh_view->SetSize(view_->GetContainerSize()); + UpdateMaxPageIDIfNecessary(render_view_host->site_instance(), + render_view_host); + } + return ok; +} + +void WebContents::Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details) { + switch (type) { + case NOTIFY_BOOKMARK_MODEL_LOADED: // BookmarkModel finished loading, fall + // through to update starred state. + case NOTIFY_URLS_STARRED: { // Somewhere, a URL has been starred. + // Ignore notifications for profiles other than our current one. + Profile* source_profile = Source(source).ptr(); + if (!source_profile->IsSameProfile(profile())) + return; + + UpdateStarredStateForCurrentURL(); + break; + } + case NOTIFY_PREF_CHANGED: { + std::wstring* pref_name_in = Details(details).ptr(); + DCHECK(Source(source).ptr() == profile()->GetPrefs()); + if (*pref_name_in == prefs::kAlternateErrorPagesEnabled) { + UpdateAlternateErrorPageURL(); + } else if (*pref_name_in == prefs::kDefaultCharset || + StartsWithASCII(WideToUTF8(*pref_name_in), "webkit.webprefs.", true) + ) { + UpdateWebPreferences(); + } else { + NOTREACHED() << "unexpected pref change notification" << *pref_name_in; + } + break; + } + case NOTIFY_RENDER_WIDGET_HOST_DESTROYED: + view_->RenderWidgetHostDestroyed(Source(source).ptr()); + break; + default: { + TabContents::Observe(type, source, details); + break; + } + } +} + +void WebContents::DidNavigateMainFramePostCommit( + const NavigationController::LoadCommittedDetails& details, + const ViewHostMsg_FrameNavigate_Params& params) { + // Hide the download shelf if all the following conditions are true: + // - there are no active downloads. + // - this is a navigation to a different TLD. + // - at least 5 seconds have elapsed since the download shelf was shown. + // TODO(jcampan): bug 1156075 when user gestures are reliable, they should + // be used to ensure we are hiding only on user initiated + // navigations. + DownloadManager* download_manager = profile()->GetDownloadManager(); + // download_manager can be NULL in unit test context. + if (download_manager && download_manager->in_progress_count() == 0 && + !details.previous_url.is_empty() && + !net::RegistryControlledDomainService::SameDomainOrHost( + details.previous_url, details.entry->url())) { + TimeDelta time_delta( + TimeTicks::Now() - last_download_shelf_show_); + if (time_delta > + TimeDelta::FromMilliseconds(kDownloadShelfHideDelay)) { + SetDownloadShelfVisible(false); + } + } + + 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()); + + // UpdateHelpersForDidNavigate will handle the case where the password_form + // origin is valid. + // TODO(brettw) bug 1343111: Password manager stuff in here needs to be + // cleaned up and covered by tests. + if (!params.password_form.origin.is_valid()) + GetPasswordManager()->DidNavigate(); + } + + // The keyword generator uses the navigation entries, so must be called after + // the commit. + GenerateKeywordIfNecessary(params); + + // 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()); + + // Close constrained popups if necessary. + MaybeCloseChildWindows(details.previous_url, details.entry->url()); + + // We hide the FindInPage window when the user navigates away, except on + // reload. + if (PageTransition::StripQualifier(params.transition) != + PageTransition::RELOAD) + view_->HideFindBar(true); + + // Update the starred state. + UpdateStarredStateForCurrentURL(); +} + +void WebContents::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; + + // 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. + UpdateHistoryForNavigation(GetURL(), params); + } + + // Notify the password manager of the navigation or form submit. + // TODO(brettw) bug 1343111: Password manager stuff in here needs to be + // cleaned up and covered by tests. + if (params.password_form.origin.is_valid()) + GetPasswordManager()->ProvisionallySavePassword(params.password_form); +} + +void WebContents::MaybeCloseChildWindows(const GURL& previous_url, + const GURL& current_url) { + if (net::RegistryControlledDomainService::SameDomainOrHost( + previous_url, current_url)) + return; + + // Clear out any child windows since we are leaving this page entirely. + // We use indices instead of iterators in case CloseWindow does something + // that may invalidate an iterator. + int size = static_cast(child_windows_.size()); + for (int i = size - 1; i >= 0; --i) { + ConstrainedWindow* window = child_windows_[i]; + if (window) + window->CloseConstrainedWindow(); + } +} + +void WebContents::UpdateStarredStateForCurrentURL() { + BookmarkModel* model = profile()->GetBookmarkModel(); + const bool old_state = is_starred_; + is_starred_ = (model && model->IsBookmarked(GetURL())); + + if (is_starred_ != old_state && delegate()) + delegate()->URLStarredChanged(this, is_starred_); +} + +void WebContents::UpdateAlternateErrorPageURL() { + GURL url = GetAlternateErrorPageURL(); + render_view_host()->SetAlternateErrorPageURL(url); +} + +void WebContents::UpdateWebPreferences() { + render_view_host()->UpdateWebPreferences(GetWebkitPrefs()); +} + +bool WebContents::IsWebApplicationActive() const { + if (!web_app_.get()) + return false; + + // If we are inside an application, the application is always active. For + // example, this allows us to display the GMail icon even when we are bounced + // the login page. + if (delegate() && delegate()->IsApplication()) + return true; + + return (GetURL() == web_app_->url()); +} + +void WebContents::WebAppImagesChanged(WebApp* web_app) { + DCHECK(web_app == web_app_.get()); + if (delegate() && IsWebApplicationActive()) + delegate()->NavigationStateChanged(this, TabContents::INVALIDATE_FAVICON); +} + +void WebContents::OnGearsCreateShortcutDone( + const GearsShortcutData& shortcut_data, bool success) { + NavigationEntry* current_entry = controller()->GetLastCommittedEntry(); + bool same_page = + current_entry && pending_install_.page_id == current_entry->page_id(); + + if (success && same_page) { + // Only switch to app mode if the user chose to create a shortcut and + // we're still on the same page that it corresponded to. + SetWebApp(new WebApp(profile(), shortcut_data)); + if (delegate()) + delegate()->ConvertContentsToApplication(this); + } + + // Reset the page id to indicate no requests are pending. + pending_install_.page_id = 0; + pending_install_.callback_functor = NULL; +} + +void WebContents::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); + } + } +} + +void WebContents::UpdateHistoryForNavigation(const GURL& display_url, + const ViewHostMsg_FrameNavigate_Params& params) { + if (profile()->IsOffTheRecord()) + return; + + // Add to history service. + HistoryService* hs = profile()->GetHistoryService(Profile::IMPLICIT_ACCESS); + if (hs) { + if (PageTransition::IsMainFrame(params.transition) && + display_url != params.url) { + // Hack on the "display" 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 display URL as a redirect. + // This only applies to the main frame, as the display URL doesn't apply + // to sub-frames. + std::vector redirects = params.redirects; + if (!redirects.empty()) + redirects.back() = display_url; + hs->AddPage(display_url, this, params.page_id, params.referrer, + params.transition, redirects); + } else { + hs->AddPage(params.url, this, params.page_id, params.referrer, + params.transition, params.redirects); + } + } +} + +bool WebContents::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." + std::wstring final_title; + bool explicit_set; + if (entry->url().SchemeIsFile() && title.empty()) { + final_title = UTF8ToWide(entry->url().ExtractFileName()); + explicit_set = false; // Don't count synthetic titles toward the set limit. + } else { + TrimWhitespace(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); + + // Update the history system for this page. + if (!profile()->IsOffTheRecord() && !received_page_title_) { + HistoryService* hs = + profile()->GetHistoryService(Profile::IMPLICIT_ACCESS); + if (hs) + hs->SetPageTitle(entry->display_url(), final_title); + + // Don't allow the title to be saved again for explicitly set ones. + received_page_title_ = explicit_set; + } + + // Lastly, set the title for the view. + view_->SetPageTitle(final_title); + + return true; +} + +void WebContents::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(NOTIFY_WEB_CONTENTS_SWAPPED, + Source(this), + NotificationService::NoDetails()); +} + +void WebContents::NotifyConnected() { + notify_disconnection_ = true; + NotificationService::current()-> + Notify(NOTIFY_WEB_CONTENTS_CONNECTED, + Source(this), + NotificationService::NoDetails()); +} + +void WebContents::NotifyDisconnected() { + if (!notify_disconnection_) + return; + + notify_disconnection_ = false; + NotificationService::current()-> + Notify(NOTIFY_WEB_CONTENTS_DISCONNECTED, + Source(this), + NotificationService::NoDetails()); +} + +void WebContents::GenerateKeywordIfNecessary( + const ViewHostMsg_FrameNavigate_Params& params) { + DCHECK(controller()); + if (!params.searchable_form_url.is_valid()) + return; + + if (profile()->IsOffTheRecord()) + return; + + const int last_index = controller()->GetLastCommittedEntryIndex(); + // When there was no previous page, the last index will be 0. This is + // normally due to a form submit that opened in a new tab. + // TODO(brettw) bug 916126: we should support keywords when form submits + // happen in new tabs. + if (last_index <= 0) + return; + const NavigationEntry* previous_entry = + controller()->GetEntryAtIndex(last_index - 1); + if (IsFormSubmit(previous_entry)) { + // Only generate a keyword if the previous page wasn't itself a form + // submit. + return; + } + + GURL keyword_url = previous_entry->user_typed_url().is_valid() ? + previous_entry->user_typed_url() : previous_entry->url(); + std::wstring keyword = + TemplateURLModel::GenerateKeyword(keyword_url, true); // autodetected + if (keyword.empty()) + return; + + TemplateURLModel* url_model = profile()->GetTemplateURLModel(); + if (!url_model) + return; + + if (!url_model->loaded()) { + url_model->Load(); + return; + } + + const TemplateURL* current_url; + std::wstring url = UTF8ToWide(params.searchable_form_url.spec()); + if (!url_model->CanReplaceKeyword(keyword, url, ¤t_url)) + return; + + if (current_url) { + if (current_url->originating_url().is_valid()) { + // The existing keyword was generated from an OpenSearch description + // document, don't regenerate. + return; + } + url_model->Remove(current_url); + } + TemplateURL* new_url = new TemplateURL(); + new_url->set_keyword(keyword); + new_url->set_short_name(keyword); + new_url->SetURL(url, 0, 0); + new_url->add_input_encoding(params.searchable_form_encoding); + DCHECK(controller()->GetLastCommittedEntry()); + const GURL& favicon_url = + controller()->GetLastCommittedEntry()->favicon().url(); + if (favicon_url.is_valid()) { + new_url->SetFavIconURL(favicon_url); + } else { + // The favicon url isn't valid. This means there really isn't a favicon, + // or the favicon url wasn't obtained before the load started. This assumes + // the later. + // TODO(sky): Need a way to set the favicon that doesn't involve generating + // its url. + new_url->SetFavIconURL(TemplateURL::GenerateFaviconURL(params.referrer)); + } + new_url->set_safe_for_autoreplace(true); + url_model->Add(new_url); +} diff --git a/chrome/browser/tab_contents/web_contents.h b/chrome/browser/tab_contents/web_contents.h new file mode 100644 index 0000000..7b44e79 --- /dev/null +++ b/chrome/browser/tab_contents/web_contents.h @@ -0,0 +1,572 @@ +// 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. + +#ifndef CHROME_BROWSER_WEB_CONTENTS_H_ +#define CHROME_BROWSER_WEB_CONTENTS_H_ + +#include "base/hash_tables.h" +#include "chrome/browser/download/save_package.h" +#include "chrome/browser/fav_icon_helper.h" +#include "chrome/browser/printing/print_view_manager.h" +#include "chrome/browser/render_view_host_delegate.h" +#include "chrome/browser/render_view_host_manager.h" +#include "chrome/browser/shell_dialogs.h" +#include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/web_app.h" + +class AutofillManager; +class InterstitialPageDelegate; +class PasswordManager; +class PluginInstaller; +class RenderViewHost; +class RenderViewHostFactory; +class RenderWidgetHost; +class WebContentsView; + +// WebContents represents the contents of a tab that shows web pages. It embeds +// a RenderViewHost (via RenderViewHostManager) to actually display the page. +class WebContents : public TabContents, + public RenderViewHostDelegate, + public RenderViewHostManager::Delegate, + public SelectFileDialog::Listener, + public WebApp::Observer { + public: + // If instance is NULL, then creates a new process for this view. Otherwise + // initialize with a process already created for a different WebContents. + // This will share the process between views in the same instance. If + // render_view_factory is NULL, this will create RenderViewHost objects + // directly. + WebContents(Profile* profile, + SiteInstance* instance, + RenderViewHostFactory* render_view_factory, + int routing_id, + HANDLE modal_dialog_event); + + static void RegisterUserPrefs(PrefService* prefs); + + // Getters ------------------------------------------------------------------- + + // Returns the AutofillManager, creating it if necessary. + AutofillManager* GetAutofillManager(); + + // Returns the PasswordManager, creating it if necessary. + PasswordManager* GetPasswordManager(); + + // Returns the PluginInstaller, creating it if necessary. + PluginInstaller* GetPluginInstaller(); + + // 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* process() const { + return render_manager_.current_host()->process(); + } + RenderViewHost* render_view_host() const { + return render_manager_.current_host(); + } + + // The WebContentsView will never change and is guaranteed non-NULL. + WebContentsView* view() const { + return view_.get(); + } + + bool is_starred() const { return is_starred_; } + + const std::wstring& encoding() const { return encoding_; } + void set_encoding(const std::wstring& encoding) { + encoding_ = encoding; + } + + // TabContents (public overrides) -------------------------------------------- + + virtual void Destroy(); + virtual WebContents* AsWebContents() { return this; } + virtual SiteInstance* GetSiteInstance() const; + virtual SkBitmap GetFavIcon(); + virtual std::wstring GetStatusText() const; + virtual bool NavigateToPendingEntry(bool reload); + virtual void Stop(); + virtual void Cut(); + virtual void Copy(); + virtual void Paste(); + virtual void DisassociateFromPopupCount(); + virtual void DidBecomeSelected(); + virtual void WasHidden(); + virtual void ShowContents(); + virtual void HideContents(); + virtual void SetDownloadShelfVisible(bool visible); + virtual void PopupNotificationVisibilityChanged(bool visible); + + // Retarded pass-throughs to the view. + // TODO(brettw) fix this, tab contents shouldn't have these methods, probably + // it should be killed altogether. + virtual void CreateView(); + virtual HWND GetContainerHWND() const; + virtual HWND GetContentHWND(); + virtual void GetContainerBounds(gfx::Rect *out) const; + + // Web apps ------------------------------------------------------------------ + + // Sets the WebApp for this WebContents. + void SetWebApp(WebApp* web_app); + WebApp* web_app() { return web_app_.get(); } + + // Return whether this tab contents was created to contain an application. + bool IsWebApplication() const; + + // Tell Gears to create a shortcut for the current page. + void CreateShortcut(); + + // 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; + } + + // JavascriptMessageBoxHandler calls this when the dialog is closed. + void OnJavaScriptMessageBoxClosed(IPC::Message* reply_msg, + bool success, + const std::wstring& prompt); + + // Prepare for saving page. + 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. + void SavePage(const std::wstring& main_file, const std::wstring& dir_path, + SavePackage::SavePackageType save_type); + + // 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(); + + // 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 WebContents 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 override_encoding(const std::wstring& encoding) { + set_encoding(encoding); + render_view_host()->SetPageEncoding(encoding); + } + + void CrossSiteNavigationCanceled() { + render_manager_.CrossSiteNavigationCanceled(); + } + + protected: + // Should be deleted via CloseContents. + virtual ~WebContents(); + + RenderWidgetHostView* render_widget_host_view() const { + return render_manager_.current_view(); + } + + // TabContents (private overrides) ------------------------------------------- + + virtual void SetInitialFocus(bool reverse); + virtual void SetIsLoading(bool is_loading, LoadNotificationDetails* details); + + // RenderViewHostDelegate ---------------------------------------------------- + + virtual RenderViewHostDelegate::View* GetViewDelegate() const; + virtual RenderViewHostDelegate::Save* GetSaveDelegate() const; + virtual Profile* GetProfile() const; + virtual void RendererReady(RenderViewHost* render_view_host); + virtual void RendererGone(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::wstring& encoding); + virtual void UpdateTargetURL(int32 page_id, const GURL& url); + virtual void UpdateThumbnail(const GURL& url, + const SkBitmap& bitmap, + const ThumbnailScore& score); + virtual void Close(RenderViewHost* render_view_host); + virtual void RequestMove(const gfx::Rect& new_bounds); + virtual void DidStartLoading(RenderViewHost* render_view_host, int32 page_id); + virtual void DidStopLoading(RenderViewHost* render_view_host, int32 page_id); + virtual void DidStartProvisionalLoadForFrame(RenderViewHost* render_view_host, + bool is_main_frame, + const GURL& url); + virtual void DidRedirectProvisionalLoad(int32 page_id, + const GURL& source_url, + const GURL& target_url); + virtual void DidLoadResourceFromMemoryCache(const GURL& url, + const std::string& security_info); + virtual void DidFailProvisionalLoadWithError(RenderViewHost* render_view_host, + bool is_main_frame, + int error_code, + const GURL& url); + virtual void UpdateFavIconURL(RenderViewHost* render_view_host, + int32 page_id, const GURL& icon_url); + virtual void DidDownloadImage(RenderViewHost* render_view_host, + int id, + const GURL& image_url, + bool errored, + const SkBitmap& image); + virtual void RequestOpenURL(const GURL& url, const GURL& referrer, + WindowOpenDisposition disposition); + virtual void DomOperationResponse(const std::string& json_string, + int automation_id); + virtual void ProcessExternalHostMessage(const std::string& receiver, + const std::string& message); + virtual void GoToEntryAtOffset(int offset); + virtual void GetHistoryListCount(int* back_list_count, + int* forward_list_count); + virtual void RunFileChooser(bool multiple_files, + const std::wstring& title, + const std::wstring& default_file, + const std::wstring& filter); + virtual void RunJavaScriptMessage(const std::wstring& message, + const std::wstring& default_prompt, + 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 void PasswordFormsSeen(const std::vector& forms); + virtual void AutofillFormSubmitted(const AutofillForm& form); + virtual void GetAutofillSuggestions(const std::wstring& field_name, + const std::wstring& user_text, int64 node_id, int request_id); + virtual void PageHasOSDD(RenderViewHost* render_view_host, + int32 page_id, const GURL& url, bool autodetected); + virtual void InspectElementReply(int num_resources); + virtual void DidGetPrintedPagesCount(int cookie, int number_pages); + virtual void DidPrintPage(const ViewHostMsg_DidPrintPage_Params& params); + virtual GURL GetAlternateErrorPageURL() const; + virtual WebPreferences GetWebkitPrefs(); + virtual void OnMissingPluginStatus(int status); + virtual void OnCrashedPlugin(const FilePath& plugin_path); + virtual void OnJSOutOfMemory(); + virtual void ShouldClosePage(bool proceed) { + render_manager_.ShouldClosePage(proceed); + } + // Allows the WebContents 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. + void OnCrossSiteResponse(int new_render_process_host_id, + int new_request_id) { + render_manager_.OnCrossSiteResponse(new_render_process_host_id, + new_request_id); + } + virtual bool CanBlur() const; + 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); + virtual void OnDidGetApplicationInfo( + int32 page_id, + const webkit_glue::WebApplicationInfo& info); + virtual void OnEnterOrSpace(); + virtual bool CanTerminate() const; + + + // SelectFileDialog::Listener ------------------------------------------------ + + virtual void FileSelected(const std::wstring& path, void* params); + virtual void MultiFilesSelected(const std::vector& files, + void* params); + virtual void FileSelectionCanceled(void* params); + + // RenderViewHostManager::Delegate ------------------------------------------- + + virtual void BeforeUnloadFiredFromRenderManager( + bool proceed, + bool* proceed_to_fire_unload); + virtual void DidStartLoadingFromRenderManager( + RenderViewHost* render_view_host, int32 page_id) { + DidStartLoading(render_view_host, page_id); + } + virtual void RendererGoneFromRenderManager(RenderViewHost* render_view_host) { + RendererGone(render_view_host); + } + virtual void UpdateRenderViewSizeForRenderManager(); + virtual void NotifySwappedFromRenderManager() { + NotifySwapped(); + } + virtual NavigationController* GetControllerForRenderManager() { + return controller(); + } + + // 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 WebContents 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. + // + // TODO(brettw) clean this up! This logic seems out of place. This is called + // by the RenderViewHostManager, but also overridden by the DOMUIHost. Any + // logic that has to be here should have a more clear name. + virtual bool CreateRenderViewForRenderManager( + RenderViewHost* render_view_host); + + private: + FRIEND_TEST(WebContentsTest, UpdateTitle); + friend class TestWebContents; + + // Temporary until the view/contents separation is complete. + friend class WebContentsViewWin; + + // So InterstitialPage can access SetIsLoading. + friend class InterstitialPage; + + // When CreateShortcut is invoked RenderViewHost::GetApplicationInfo is + // invoked. CreateShortcut caches the state of the page needed to create the + // shortcut in PendingInstall. When OnDidGetApplicationInfo is invoked, it + // uses the information from PendingInstall and the WebApplicationInfo + // to create the shortcut. + class GearsCreateShortcutCallbackFunctor; + struct PendingInstall { + int32 page_id; + SkBitmap icon; + std::wstring title; + GURL url; + // This object receives the GearsCreateShortcutCallback and routes the + // message back to the WebContents, if we haven't been deleted. + GearsCreateShortcutCallbackFunctor* callback_functor; + }; + + + // NotificationObserver ------------------------------------------------------ + + virtual void Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details); + + // 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 child windows (constrained popups) when the domain changes. + // Supply the new and old URLs, and this function will figure out when the + // domain changing conditions are met. + void MaybeCloseChildWindows(const GURL& previous_url, + const GURL& current_url); + + // Updates the starred state from the bookmark bar model. If the state has + // changed, the delegate is notified. + void UpdateStarredStateForCurrentURL(); + + // 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(); + + // Return whether the optional web application is active for the current URL. + // Call this method to check if web app properties are in effect. + // + // Note: This method should be used for presentation but not security. The app + // is always active if the containing window is a web application. + bool IsWebApplicationActive() const; + + // WebApp::Observer method. Invoked when the set of images contained in the + // web app changes. Notifies the delegate our favicon has changed. + virtual void WebAppImagesChanged(WebApp* web_app); + + // Called when the user dismisses the shortcut creation dialog. 'success' is + // true if the shortcut was created. + void OnGearsCreateShortcutDone(const GearsShortcutData& shortcut_data, + bool success); + + // 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); + + // Called by OnMsgNavigate to update history state. Overridden by subclasses + // that don't want to be added to history. + virtual void UpdateHistoryForNavigation(const GURL& display_url, + 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); + + // Misc non-view stuff ------------------------------------------------------- + + // Helper functions for sending notifications. + void NotifySwapped(); + void NotifyConnected(); + void NotifyDisconnected(); + + // If params has a searchable form, this tries to create a new keyword. + void GenerateKeywordIfNecessary( + const ViewHostMsg_FrameNavigate_Params& params); + + // Data ---------------------------------------------------------------------- + + // The corresponding view. + scoped_ptr view_; + + // Manages creation and swapping of render views. + RenderViewHostManager render_manager_; + + // For testing, passed to new RenderViewHost managers. + RenderViewHostFactory* render_view_factory_; + + // Handles print preview and print job for this contents. + printing::PrintViewManager printing_; + + // Indicates whether we should notify about disconnection of this + // WebContents. 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 HistoryRequestMap; + HistoryRequestMap history_requests_; + + // System time at which the current load was started. + base::TimeTicks current_load_start_; + + // 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_; + + // SavePackage, lazily created. + scoped_refptr save_package_; + + // Tracks our pending CancelableRequests. This maps pending requests to + // page IDs so that we know whether a given callback still applies. The + // page ID -1 means no page ID was set. + CancelableRequestConsumerT cancelable_consumer_; + + // Whether the current URL is starred + bool is_starred_; + + // 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. + ScopedHandle message_box_active_; + + // AutofillManager, lazily created. + scoped_ptr autofill_manager_; + + // PasswordManager, lazily created. + scoped_ptr password_manager_; + + // PluginInstaller, lazily created. + scoped_ptr plugin_installer_; + + // Handles downloading favicons. + FavIconHelper fav_icon_helper_; + + // Dialog box used for choosing files to upload from file form fields. + scoped_refptr select_file_dialog_; + + // 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_; + + // 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. TODO(jungshik) : convert to std::string + std::wstring encoding_; + + PendingInstall pending_install_; + + // The last time that the download shelf was made visible. + base::TimeTicks last_download_shelf_show_; + + // The current load state and the URL associated with it. + net::LoadState load_state_; + std::wstring load_state_host_; + + // Non-null if we're displaying content for a web app. + scoped_refptr web_app_; + + DISALLOW_COPY_AND_ASSIGN(WebContents); +}; + +#endif // CHROME_BROWSER_WEB_CONTENTS_H_ diff --git a/chrome/browser/tab_contents/web_contents_unittest.cc b/chrome/browser/tab_contents/web_contents_unittest.cc new file mode 100644 index 0000000..df018c1 --- /dev/null +++ b/chrome/browser/tab_contents/web_contents_unittest.cc @@ -0,0 +1,1271 @@ +// 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 "base/logging.h" +#include "chrome/browser/render_view_host.h" +#include "chrome/browser/render_widget_host_view.h" +#include "chrome/browser/tab_contents/interstitial_page.h" +#include "chrome/browser/tab_contents/navigation_controller.h" +#include "chrome/browser/tab_contents/navigation_entry.h" +#include "chrome/browser/tab_contents/web_contents.h" +#include "chrome/common/chrome_paths.h" +#include "chrome/common/ipc_channel.h" +#include "chrome/common/pref_service.h" +#include "chrome/common/render_messages.h" +#include "chrome/test/testing_profile.h" +#include "testing/gtest/include/gtest/gtest.h" + +static void InitNavigateParams(ViewHostMsg_FrameNavigate_Params* params, + int page_id, + const GURL& url) { + params->page_id = page_id; + params->url = url; + params->referrer = GURL::EmptyGURL(); + params->transition = PageTransition::TYPED; + params->redirects = std::vector(); + params->should_update_history = false; + params->searchable_form_url = GURL::EmptyGURL(); + params->searchable_form_element_name = std::wstring(); + params->searchable_form_encoding = std::string(); + params->password_form = PasswordForm(); + params->security_info = std::string(); + params->gesture = NavigationGestureUser; + params->is_post = false; +} + +// Subclass the RenderViewHost's view so that we can call Show(), etc., +// without having side-effects. +class TestRenderWidgetHostView : public RenderWidgetHostView { + public: + TestRenderWidgetHostView() : is_showing_(false) {} + + virtual RenderWidgetHost* GetRenderWidgetHost() const { return NULL; } + virtual void DidBecomeSelected() {} + virtual void WasHidden() {} + virtual void SetSize(const gfx::Size& size) {} + virtual HWND GetPluginHWND() { return NULL; } + virtual HANDLE ModalDialogEvent() { return NULL; } + virtual void ForwardMouseEventToRenderer(UINT message, + WPARAM wparam, + LPARAM lparam) {} + virtual void Focus() {} + virtual void Blur() {} + virtual bool HasFocus() { return true; } + virtual void AdvanceFocus(bool reverse) {} + virtual void Show() { is_showing_ = true; } + virtual void Hide() { is_showing_ = false; } + virtual gfx::Rect GetViewBounds() const { return gfx::Rect(); } + virtual void UpdateCursor(const WebCursor& cursor) {} + virtual void UpdateCursorIfOverSelf() {} + // Indicates if the page has finished loading. + virtual void SetIsLoading(bool is_loading) {} + virtual void IMEUpdateStatus(ViewHostMsg_ImeControl control, + const gfx::Rect& caret_rect) {} + virtual void DidPaintRect(const gfx::Rect& rect) {} + virtual void DidScrollRect(const gfx::Rect& rect, int dx, int dy) {} + virtual void RendererGone() {} + virtual void Destroy() {} + virtual void PrepareToDestroy() {} + virtual void SetTooltipText(const std::wstring& tooltip_text) {} + + bool is_showing() const { return is_showing_; } + + private: + bool is_showing_; +}; + +// Subclass RenderViewHost so that it does not create a process. +class TestRenderViewHost : public RenderViewHost { + public: + TestRenderViewHost( + SiteInstance* instance, + RenderViewHostDelegate* delegate, + int routing_id, + HANDLE modal_dialog_event) + : RenderViewHost(instance, delegate, routing_id, modal_dialog_event), + is_loading(false), + is_created(false), + immediate_before_unload(true), + delete_counter_(NULL) { + set_view(new TestRenderWidgetHostView()); + } + ~TestRenderViewHost() { + // Track the delete if we've been asked to. + if (delete_counter_) + ++*delete_counter_; + + // Since this isn't a traditional view, we have to delete it. + delete view_; + } + + // If set, *delete_counter is incremented when this object destructs. + void set_delete_counter(int* delete_counter) { + delete_counter_ = delete_counter; + } + + bool CreateRenderView() { + is_created = true; + return true; + } + + bool IsRenderViewLive() const { return is_created; } + + bool IsNavigationSuspended() { return navigations_suspended_; } + + void NavigateToEntry(const NavigationEntry& entry, bool is_reload) { + is_loading = true; + } + + void LoadAlternateHTMLString(const std::string& html_text, + bool new_navigation, + const GURL& display_url, + const std::string& security_info) { + is_loading = true; + } + + // Support for onbeforeunload, onunload + void FirePageBeforeUnload() { + is_waiting_for_unload_ack_ = true; + if (immediate_before_unload) + delegate()->ShouldClosePage(true); + } + void ClosePage(int new_render_process_host_id, int new_request_id) { + // Nothing to do here... This would cause a ClosePage_ACK to be sent to + // ResourceDispatcherHost, so we can simulate that manually. + } + void TestOnMsgShouldClose(bool proceed) { + OnMsgShouldCloseACK(proceed); + } + + bool is_loading; + bool is_created; + bool immediate_before_unload; + int* delete_counter_; +}; + +// Factory to create TestRenderViewHosts. +class TestRenderViewHostFactory : public RenderViewHostFactory { + public: + static TestRenderViewHostFactory* GetInstance() { + static TestRenderViewHostFactory instance; + return &instance; + } + + virtual RenderViewHost* CreateRenderViewHost( + SiteInstance* instance, + RenderViewHostDelegate* delegate, + int routing_id, + HANDLE modal_dialog_event) { + return new TestRenderViewHost( + instance, delegate, routing_id, modal_dialog_event); + } + + private: + TestRenderViewHostFactory() {} +}; + +// Subclass the TestingProfile so that it can return certain services we need. +class WebContentsTestingProfile : public TestingProfile { + public: + WebContentsTestingProfile() : TestingProfile() { } + + virtual PrefService* GetPrefs() { + if (!prefs_.get()) { + std::wstring source_path; + PathService::Get(chrome::DIR_TEST_DATA, &source_path); + file_util::AppendToPath(&source_path, L"profiles"); + file_util::AppendToPath(&source_path, L"chrome_prefs"); + file_util::AppendToPath(&source_path, L"Preferences"); + + prefs_.reset(new PrefService(source_path)); + Profile::RegisterUserPrefs(prefs_.get()); + browser::RegisterAllPrefs(prefs_.get(), prefs_.get()); + } + return prefs_.get(); + } +}; + +// Subclass WebContents to ensure it creates TestRenderViewHosts and does +// not do anything involving views. +class TestWebContents : public WebContents { + public: + TestWebContents(Profile* profile, SiteInstance* instance) + : WebContents(profile, + instance, + TestRenderViewHostFactory::GetInstance(), + MSG_ROUTING_NONE, + NULL), + transition_cross_site(false) {} + + // Accessors for interesting fields + TestRenderViewHost* rvh() { + return static_cast( + render_manager_.render_view_host_); + } + TestRenderViewHost* pending_rvh() { + return static_cast( + render_manager_.pending_render_view_host_); + } + + // State accessor. + bool cross_navigation_pending() { + return render_manager_.cross_navigation_pending_; + } + + // Ensure we create TestRenderViewHosts that don't spawn processes. + RenderViewHost* CreateRenderViewHost(SiteInstance* instance, + RenderViewHostDelegate* delegate, + int routing_id, + HANDLE modal_dialog_event) { + return new TestRenderViewHost( + instance, delegate, routing_id, modal_dialog_event); + } + + // Overrides WebContents::ShouldTransitionCrossSite so that we can test both + // alternatives without using command-line switches. + bool ShouldTransitionCrossSite() { return transition_cross_site; } + + // Promote DidNavigate to public. + void TestDidNavigate(TestRenderViewHost* render_view_host, + const ViewHostMsg_FrameNavigate_Params& params) { + DidNavigate(render_view_host, params); + render_view_host->is_loading = false; + } + + // Promote GetWebkitPrefs to public. + WebPreferences TestGetWebkitPrefs() { + return GetWebkitPrefs(); + } + + // Prevent interaction with views. + bool CreateRenderViewForRenderManager(RenderViewHost* render_view_host) { + // This will go to a TestRenderViewHost. + render_view_host->CreateRenderView(); + return true; + } + void UpdateRenderViewSizeForRenderManager() {} + + // Set by individual tests. + bool transition_cross_site; +}; + +class TestInterstitialPage : public InterstitialPage { + public: + enum InterstitialState { + UNDECIDED = 0, // No decision taken yet. + OKED, // Proceed was called. + CANCELED // DontProceed was called. + }; + + class Delegate { + public: + virtual void TestInterstitialPageDeleted( + TestInterstitialPage* interstitial) = 0; + }; + + // IMPORTANT NOTE: if you pass stack allocated values for |state| and + // |deleted| (like all interstitial related tests do at this point), make sure + // to create an instance of the TestInterstitialPageStateGuard class on the + // stack in your test. This will ensure that the TestInterstitialPage states + // are cleared when the test finishes. + // Not doing so will cause stack trashing if your test does not hide the + // interstitial, as in such a case it will be destroyed in the test TearDown + // method and will dereference the |deleted| local variable which by then is + // out of scope. + TestInterstitialPage(WebContents* tab, + bool new_navigation, + const GURL& url, + InterstitialState* state, + bool* deleted) + : InterstitialPage(tab, new_navigation, url), + state_(state), + deleted_(deleted), + command_received_count_(0), + delegate_(NULL) { + *state_ = UNDECIDED; + *deleted_ = false; + } + + virtual ~TestInterstitialPage() { + if (deleted_) + *deleted_ = true; + if (delegate_) + delegate_->TestInterstitialPageDeleted(this); + } + + virtual void DontProceed() { + if (state_) + *state_ = CANCELED; + InterstitialPage::DontProceed(); + } + virtual void Proceed() { + if (state_) + *state_ = OKED; + InterstitialPage::Proceed(); + } + + int command_received_count() const { + return command_received_count_; + } + + void TestDomOperationResponse(const std::string& json_string) { + DomOperationResponse(json_string, 1); + } + + void TestDidNavigate(int page_id, const GURL& url) { + ViewHostMsg_FrameNavigate_Params params; + InitNavigateParams(¶ms, page_id, url); + DidNavigate(render_view_host(), params); + } + + void TestRendererGone() { + RendererGone(render_view_host()); + } + + bool is_showing() const { + return static_cast(render_view_host()->view())-> + is_showing(); + } + + void ClearStates() { + state_ = NULL; + deleted_ = NULL; + delegate_ = NULL; + } + + void set_delegate(Delegate* delegate) { + delegate_ = delegate; + } + + protected: + virtual RenderViewHost* CreateRenderViewHost() { + return new TestRenderViewHost( + SiteInstance::CreateSiteInstance(tab()->profile()), + this, MSG_ROUTING_NONE, NULL); + } + + virtual void CommandReceived(const std::string& command) { + command_received_count_++; + } + + private: + InterstitialState* state_; + bool* deleted_; + int command_received_count_; + Delegate* delegate_; +}; + +class TestInterstitialPageStateGuard : public TestInterstitialPage::Delegate { + public: + explicit TestInterstitialPageStateGuard( + TestInterstitialPage* interstitial_page) + : interstitial_page_(interstitial_page) { + DCHECK(interstitial_page_); + interstitial_page_->set_delegate(this); + } + ~TestInterstitialPageStateGuard() { + if (interstitial_page_) + interstitial_page_->ClearStates(); + } + + virtual void TestInterstitialPageDeleted(TestInterstitialPage* interstitial) { + DCHECK(interstitial_page_ == interstitial); + interstitial_page_ = NULL; + } + + private: + TestInterstitialPage* interstitial_page_; +}; + +class WebContentsTest : public testing::Test { + public: + WebContentsTest() : contents(NULL) {} + + // testing::Test methods: + + virtual void SetUp() { + profile.reset(new WebContentsTestingProfile()); + + // This will be deleted when the WebContents goes away + SiteInstance* instance = SiteInstance::CreateSiteInstance(profile.get()); + + contents = new TestWebContents(profile.get(), instance); + contents->SetupController(profile.get()); + } + + virtual void TearDown() { + // This will delete the contents. + if (contents) + contents->CloseContents(); + + // Make sure that we flush any messages related to WebContents destruction + // before we destroy the profile. + MessageLoop::current()->RunAllPending(); + } + + void Navigate(int page_id, const GURL& url) { + DCHECK(contents); + ViewHostMsg_FrameNavigate_Params params; + InitNavigateParams(¶ms, page_id, url); + contents->TestDidNavigate(contents->rvh(), params); + } + + scoped_ptr profile; + TestWebContents* contents; + + private: + MessageLoopForUI message_loop_; +}; + +// Test to make sure that title updates get stripped of whitespace. +TEST_F(WebContentsTest, UpdateTitle) { + ViewHostMsg_FrameNavigate_Params params; + InitNavigateParams(¶ms, 0, GURL("about:blank")); + + NavigationController::LoadCommittedDetails details; + contents->controller()->RendererDidNavigate(params, &details); + + contents->UpdateTitle(contents->rvh(), 0, L" Lots O' Whitespace\n"); + EXPECT_EQ(std::wstring(L"Lots O' Whitespace"), contents->GetTitle()); +} + +// Test simple same-SiteInstance navigation. +TEST_F(WebContentsTest, SimpleNavigation) { + TestRenderViewHost* orig_rvh = contents->rvh(); + SiteInstance* instance1 = contents->GetSiteInstance(); + EXPECT_TRUE(contents->pending_rvh() == NULL); + EXPECT_FALSE(orig_rvh->is_loading); + + // Navigate to URL + const GURL url("http://www.google.com"); + contents->controller()->LoadURL(url, GURL(), PageTransition::TYPED); + EXPECT_FALSE(contents->cross_navigation_pending()); + EXPECT_TRUE(orig_rvh->is_loading); + EXPECT_EQ(instance1, orig_rvh->site_instance()); + // Controller's pending entry will have a NULL site instance until we assign + // it in DidNavigate. + EXPECT_TRUE( + contents->controller()->GetActiveEntry()->site_instance() == NULL); + + // DidNavigate from the page + ViewHostMsg_FrameNavigate_Params params; + InitNavigateParams(¶ms, 1, url); + contents->TestDidNavigate(orig_rvh, params); + EXPECT_FALSE(contents->cross_navigation_pending()); + EXPECT_EQ(orig_rvh, contents->render_view_host()); + EXPECT_EQ(instance1, orig_rvh->site_instance()); + // Controller's entry should now have the SiteInstance, or else we won't be + // able to find it later. + EXPECT_EQ(instance1, + contents->controller()->GetActiveEntry()->site_instance()); +} + +// Test that navigating across a site boundary creates a new RenderViewHost +// with a new SiteInstance. Going back should do the same. +TEST_F(WebContentsTest, CrossSiteBoundaries) { + contents->transition_cross_site = true; + TestRenderViewHost* orig_rvh = contents->rvh(); + int orig_rvh_delete_count = 0; + orig_rvh->set_delete_counter(&orig_rvh_delete_count); + SiteInstance* instance1 = contents->GetSiteInstance(); + + // Navigate to URL. First URL should use first RenderViewHost. + const GURL url("http://www.google.com"); + contents->controller()->LoadURL(url, GURL(), PageTransition::TYPED); + ViewHostMsg_FrameNavigate_Params params1; + InitNavigateParams(¶ms1, 1, url); + contents->TestDidNavigate(orig_rvh, params1); + + EXPECT_FALSE(contents->cross_navigation_pending()); + EXPECT_EQ(orig_rvh, contents->render_view_host()); + + // Navigate to new site + const GURL url2("http://www.yahoo.com"); + contents->controller()->LoadURL(url2, GURL(), PageTransition::TYPED); + EXPECT_TRUE(contents->cross_navigation_pending()); + TestRenderViewHost* pending_rvh = contents->pending_rvh(); + int pending_rvh_delete_count = 0; + pending_rvh->set_delete_counter(&pending_rvh_delete_count); + + // DidNavigate from the pending page + ViewHostMsg_FrameNavigate_Params params2; + InitNavigateParams(¶ms2, 1, url2); + contents->TestDidNavigate(pending_rvh, params2); + SiteInstance* instance2 = contents->GetSiteInstance(); + + EXPECT_FALSE(contents->cross_navigation_pending()); + EXPECT_EQ(pending_rvh, contents->render_view_host()); + EXPECT_NE(instance1, instance2); + EXPECT_TRUE(contents->pending_rvh() == NULL); + EXPECT_EQ(orig_rvh_delete_count, 1); + + // Going back should switch SiteInstances again. The first SiteInstance is + // stored in the NavigationEntry, so it should be the same as at the start. + contents->controller()->GoBack(); + TestRenderViewHost* goback_rvh = contents->pending_rvh(); + EXPECT_TRUE(contents->cross_navigation_pending()); + + // DidNavigate from the back action + contents->TestDidNavigate(goback_rvh, params1); + EXPECT_FALSE(contents->cross_navigation_pending()); + EXPECT_EQ(goback_rvh, contents->render_view_host()); + EXPECT_EQ(pending_rvh_delete_count, 1); + EXPECT_EQ(instance1, contents->GetSiteInstance()); +} + +// Test that navigating across a site boundary after a crash creates a new +// RVH without requiring a cross-site transition (i.e., PENDING state). +TEST_F(WebContentsTest, CrossSiteBoundariesAfterCrash) { + contents->transition_cross_site = true; + TestRenderViewHost* orig_rvh = contents->rvh(); + int orig_rvh_delete_count = 0; + orig_rvh->set_delete_counter(&orig_rvh_delete_count); + SiteInstance* instance1 = contents->GetSiteInstance(); + + // Navigate to URL. First URL should use first RenderViewHost. + const GURL url("http://www.google.com"); + contents->controller()->LoadURL(url, GURL(), PageTransition::TYPED); + ViewHostMsg_FrameNavigate_Params params1; + InitNavigateParams(¶ms1, 1, url); + contents->TestDidNavigate(orig_rvh, params1); + + EXPECT_FALSE(contents->cross_navigation_pending()); + EXPECT_EQ(orig_rvh, contents->render_view_host()); + + // Crash the renderer. + orig_rvh->is_created = false; + + // Navigate to new site. We should not go into PENDING. + const GURL url2("http://www.yahoo.com"); + contents->controller()->LoadURL(url2, GURL(), PageTransition::TYPED); + TestRenderViewHost* new_rvh = contents->rvh(); + EXPECT_FALSE(contents->cross_navigation_pending()); + EXPECT_TRUE(contents->pending_rvh() == NULL); + EXPECT_NE(orig_rvh, new_rvh); + EXPECT_EQ(orig_rvh_delete_count, 1); + + // DidNavigate from the new page + ViewHostMsg_FrameNavigate_Params params2; + InitNavigateParams(¶ms2, 1, url2); + contents->TestDidNavigate(new_rvh, params2); + SiteInstance* instance2 = contents->GetSiteInstance(); + + EXPECT_FALSE(contents->cross_navigation_pending()); + EXPECT_EQ(new_rvh, contents->render_view_host()); + EXPECT_NE(instance1, instance2); + EXPECT_TRUE(contents->pending_rvh() == NULL); +} + +// Test that opening a new tab in the same SiteInstance and then navigating +// both tabs to a new site will place both tabs in a single SiteInstance. +TEST_F(WebContentsTest, NavigateTwoTabsCrossSite) { + contents->transition_cross_site = true; + TestRenderViewHost* orig_rvh = contents->rvh(); + SiteInstance* instance1 = contents->GetSiteInstance(); + + // Navigate to URL. First URL should use first RenderViewHost. + const GURL url("http://www.google.com"); + contents->controller()->LoadURL(url, GURL(), PageTransition::TYPED); + ViewHostMsg_FrameNavigate_Params params1; + InitNavigateParams(¶ms1, 1, url); + contents->TestDidNavigate(orig_rvh, params1); + + // Open a new tab with the same SiteInstance, navigated to the same site. + TestWebContents* contents2 = new TestWebContents(profile.get(), instance1); + params1.page_id = 2; // Need this since the site instance is the same (which + // is the scope of page IDs) and we want to consider + // this a new page. + contents2->transition_cross_site = true; + contents2->SetupController(profile.get()); + contents2->controller()->LoadURL(url, GURL(), PageTransition::TYPED); + contents2->TestDidNavigate(contents2->rvh(), params1); + + // Navigate first tab to a new site + const GURL url2a("http://www.yahoo.com"); + contents->controller()->LoadURL(url2a, GURL(), PageTransition::TYPED); + TestRenderViewHost* pending_rvh_a = contents->pending_rvh(); + ViewHostMsg_FrameNavigate_Params params2a; + InitNavigateParams(¶ms2a, 1, url2a); + contents->TestDidNavigate(pending_rvh_a, params2a); + SiteInstance* instance2a = contents->GetSiteInstance(); + EXPECT_NE(instance1, instance2a); + + // Navigate second tab to the same site as the first tab + const GURL url2b("http://mail.yahoo.com"); + contents2->controller()->LoadURL(url2b, GURL(), PageTransition::TYPED); + TestRenderViewHost* pending_rvh_b = contents2->pending_rvh(); + EXPECT_TRUE(pending_rvh_b != NULL); + EXPECT_TRUE(contents2->cross_navigation_pending()); + + // NOTE(creis): We used to be in danger of showing a sad tab page here if the + // second tab hadn't navigated somewhere first (bug 1145430). That case is + // now covered by the CrossSiteBoundariesAfterCrash test. + + ViewHostMsg_FrameNavigate_Params params2b; + InitNavigateParams(¶ms2b, 2, url2b); + contents2->TestDidNavigate(pending_rvh_b, params2b); + SiteInstance* instance2b = contents2->GetSiteInstance(); + EXPECT_NE(instance1, instance2b); + + // Both tabs should now be in the same SiteInstance. + EXPECT_EQ(instance2a, instance2b); + + contents2->CloseContents(); +} + +// Tests that WebContents uses the current URL, not the SiteInstance's site, to +// determine whether a navigation is cross-site. +TEST_F(WebContentsTest, CrossSiteComparesAgainstCurrentPage) { + contents->transition_cross_site = true; + TestRenderViewHost* orig_rvh = contents->rvh(); + SiteInstance* instance1 = contents->GetSiteInstance(); + + // Navigate to URL. + const GURL url("http://www.google.com"); + contents->controller()->LoadURL(url, GURL(), PageTransition::TYPED); + ViewHostMsg_FrameNavigate_Params params1; + InitNavigateParams(¶ms1, 1, url); + contents->TestDidNavigate(orig_rvh, params1); + + // Open a related tab to a second site. + TestWebContents* contents2 = new TestWebContents(profile.get(), instance1); + contents2->transition_cross_site = true; + contents2->SetupController(profile.get()); + const GURL url2("http://www.yahoo.com"); + contents2->controller()->LoadURL(url2, GURL(), PageTransition::TYPED); + // The first RVH in contents2 isn't live yet, so we shortcut the cross site + // pending. + TestRenderViewHost* rvh2 = contents2->rvh(); + EXPECT_FALSE(contents2->cross_navigation_pending()); + ViewHostMsg_FrameNavigate_Params params2; + InitNavigateParams(¶ms2, 2, url2); + contents2->TestDidNavigate(rvh2, params2); + SiteInstance* instance2 = contents2->GetSiteInstance(); + EXPECT_NE(instance1, instance2); + EXPECT_FALSE(contents2->cross_navigation_pending()); + + // Simulate a link click in first tab to second site. Doesn't switch + // SiteInstances, because we don't intercept WebKit navigations. + ViewHostMsg_FrameNavigate_Params params3; + InitNavigateParams(¶ms3, 2, url2); + contents->TestDidNavigate(orig_rvh, params3); + SiteInstance* instance3 = contents->GetSiteInstance(); + EXPECT_EQ(instance1, instance3); + EXPECT_FALSE(contents->cross_navigation_pending()); + + // Navigate to the new site. Doesn't switch SiteInstancees, because we + // compare against the current URL, not the SiteInstance's site. + const GURL url3("http://mail.yahoo.com"); + contents->controller()->LoadURL(url3, GURL(), PageTransition::TYPED); + EXPECT_FALSE(contents->cross_navigation_pending()); + ViewHostMsg_FrameNavigate_Params params4; + InitNavigateParams(¶ms4, 3, url3); + contents->TestDidNavigate(orig_rvh, params4); + SiteInstance* instance4 = contents->GetSiteInstance(); + EXPECT_EQ(instance1, instance4); + + contents2->CloseContents(); +} + +// Test that the onbeforeunload and onunload handlers run when navigating +// across site boundaries. +TEST_F(WebContentsTest, CrossSiteUnloadHandlers) { + contents->transition_cross_site = true; + TestRenderViewHost* orig_rvh = contents->rvh(); + SiteInstance* instance1 = contents->GetSiteInstance(); + + // Navigate to URL. First URL should use first RenderViewHost. + const GURL url("http://www.google.com"); + contents->controller()->LoadURL(url, GURL(), PageTransition::TYPED); + ViewHostMsg_FrameNavigate_Params params1; + InitNavigateParams(¶ms1, 1, url); + contents->TestDidNavigate(orig_rvh, params1); + EXPECT_FALSE(contents->cross_navigation_pending()); + EXPECT_EQ(orig_rvh, contents->render_view_host()); + + // Navigate to new site, but simulate an onbeforeunload denial. + const GURL url2("http://www.yahoo.com"); + orig_rvh->immediate_before_unload = false; + contents->controller()->LoadURL(url2, GURL(), PageTransition::TYPED); + orig_rvh->TestOnMsgShouldClose(false); + EXPECT_FALSE(contents->cross_navigation_pending()); + EXPECT_EQ(orig_rvh, contents->render_view_host()); + + // Navigate again, but simulate an onbeforeunload approval. + contents->controller()->LoadURL(url2, GURL(), PageTransition::TYPED); + orig_rvh->TestOnMsgShouldClose(true); + EXPECT_TRUE(contents->cross_navigation_pending()); + TestRenderViewHost* pending_rvh = contents->pending_rvh(); + + // We won't hear DidNavigate until the onunload handler has finished running. + // (No way to simulate that here, but it involves a call from RDH to + // WebContents::OnCrossSiteResponse.) + + // DidNavigate from the pending page + ViewHostMsg_FrameNavigate_Params params2; + InitNavigateParams(¶ms2, 1, url2); + contents->TestDidNavigate(pending_rvh, params2); + SiteInstance* instance2 = contents->GetSiteInstance(); + EXPECT_FALSE(contents->cross_navigation_pending()); + EXPECT_EQ(pending_rvh, contents->render_view_host()); + EXPECT_NE(instance1, instance2); + EXPECT_TRUE(contents->pending_rvh() == NULL); +} + +// Test that NavigationEntries have the correct content state after going +// forward and back. Prevents regression for bug 1116137. +TEST_F(WebContentsTest, NavigationEntryContentState) { + TestRenderViewHost* orig_rvh = contents->rvh(); + + // Navigate to URL. There should be no committed entry yet. + const GURL url("http://www.google.com"); + contents->controller()->LoadURL(url, GURL(), PageTransition::TYPED); + NavigationEntry* entry = contents->controller()->GetLastCommittedEntry(); + EXPECT_TRUE(entry == NULL); + + // Committed entry should have content state after DidNavigate. + ViewHostMsg_FrameNavigate_Params params1; + InitNavigateParams(¶ms1, 1, url); + contents->TestDidNavigate(orig_rvh, params1); + entry = contents->controller()->GetLastCommittedEntry(); + EXPECT_FALSE(entry->content_state().empty()); + + // Navigate to same site. + const GURL url2("http://images.google.com"); + contents->controller()->LoadURL(url2, GURL(), PageTransition::TYPED); + entry = contents->controller()->GetLastCommittedEntry(); + EXPECT_FALSE(entry->content_state().empty()); + + // Committed entry should have content state after DidNavigate. + ViewHostMsg_FrameNavigate_Params params2; + InitNavigateParams(¶ms2, 2, url2); + contents->TestDidNavigate(orig_rvh, params2); + entry = contents->controller()->GetLastCommittedEntry(); + EXPECT_FALSE(entry->content_state().empty()); + + // Now go back. Committed entry should still have content state. + contents->controller()->GoBack(); + contents->TestDidNavigate(orig_rvh, params1); + entry = contents->controller()->GetLastCommittedEntry(); + EXPECT_FALSE(entry->content_state().empty()); +} + +// Test that NavigationEntries have the correct content state after opening +// a new window to about:blank. Prevents regression for bug 1116137. +TEST_F(WebContentsTest, NavigationEntryContentStateNewWindow) { + TestRenderViewHost* orig_rvh = contents->rvh(); + + // When opening a new window, it is navigated to about:blank internally. + // Currently, this results in two DidNavigate events. + const GURL url("about:blank"); + ViewHostMsg_FrameNavigate_Params params1; + InitNavigateParams(¶ms1, 1, url); + contents->TestDidNavigate(orig_rvh, params1); + contents->TestDidNavigate(orig_rvh, params1); + + // Should have a content state here. + NavigationEntry* entry = contents->controller()->GetLastCommittedEntry(); + EXPECT_FALSE(entry->content_state().empty()); +} + +// Tests to see that webkit preferences are properly loaded and copied over +// to a WebPreferences object. +TEST_F(WebContentsTest, WebKitPrefs) { + WebPreferences webkit_prefs = contents->TestGetWebkitPrefs(); + + // These values have been overridden by the profile preferences. + EXPECT_EQ(L"UTF-8", webkit_prefs.default_encoding); + EXPECT_EQ(20, webkit_prefs.default_font_size); + EXPECT_EQ(false, webkit_prefs.text_areas_are_resizable); + EXPECT_EQ(true, webkit_prefs.uses_universal_detector); + + // These should still be the default values. + EXPECT_EQ(L"Times New Roman", webkit_prefs.standard_font_family); + EXPECT_EQ(true, webkit_prefs.javascript_enabled); +} + +//////////////////////////////////////////////////////////////////////////////// +// Interstitial Tests +//////////////////////////////////////////////////////////////////////////////// + +// Test navigating to a page (with the navigation initiated from the browser, +// as when a URL is typed in the location bar) that shows an interstitial and +// creates a new navigation entry, then hiding it without proceeding. +TEST_F(WebContentsTest, + ShowInterstitialFromBrowserWithNewNavigationDontProceed) { + // Navigate to a page. + GURL url1("http://www.google.com"); + Navigate(1, url1); + EXPECT_EQ(1, contents->controller()->GetEntryCount()); + + // Initiate a browser navigation that will trigger the interstitial + contents->controller()->LoadURL(GURL("http://www.evil.com"), GURL(), + PageTransition::TYPED); + + // Show an interstitial. + TestInterstitialPage::InterstitialState state = + TestInterstitialPage::UNDECIDED; + bool deleted = false; + GURL url2("http://interstitial"); + TestInterstitialPage* interstitial = + new TestInterstitialPage(contents, true, url2, &state, &deleted); + TestInterstitialPageStateGuard state_guard(interstitial); + interstitial->Show(); + // The interstitial should not show until its navigation has committed. + EXPECT_FALSE(interstitial->is_showing()); + EXPECT_FALSE(contents->showing_interstitial_page()); + EXPECT_TRUE(contents->interstitial_page() == NULL); + // Let's commit the interstitial navigation. + interstitial->TestDidNavigate(1, url2); + EXPECT_TRUE(interstitial->is_showing()); + EXPECT_TRUE(contents->showing_interstitial_page()); + EXPECT_TRUE(contents->interstitial_page() == interstitial); + NavigationEntry* entry = contents->controller()->GetActiveEntry(); + ASSERT_TRUE(entry != NULL); + EXPECT_TRUE(entry->url() == url2); + + // Now don't proceed. + interstitial->DontProceed(); + EXPECT_TRUE(deleted); + EXPECT_EQ(TestInterstitialPage::CANCELED, state); + EXPECT_FALSE(contents->showing_interstitial_page()); + EXPECT_TRUE(contents->interstitial_page() == NULL); + entry = contents->controller()->GetActiveEntry(); + ASSERT_TRUE(entry != NULL); + EXPECT_TRUE(entry->url() == url1); + EXPECT_EQ(1, contents->controller()->GetEntryCount()); +} + +// Test navigating to a page (with the navigation initiated from the renderer, +// as when clicking on a link in the page) that shows an interstitial and +// creates a new navigation entry, then hiding it without proceeding. +TEST_F(WebContentsTest, + ShowInterstitiaFromRendererlWithNewNavigationDontProceed) { + // Navigate to a page. + GURL url1("http://www.google.com"); + Navigate(1, url1); + EXPECT_EQ(1, contents->controller()->GetEntryCount()); + + // Show an interstitial (no pending entry, the interstitial would have been + // triggered by clicking on a link). + TestInterstitialPage::InterstitialState state = + TestInterstitialPage::UNDECIDED; + bool deleted = false; + GURL url2("http://interstitial"); + TestInterstitialPage* interstitial = + new TestInterstitialPage(contents, true, url2, &state, &deleted); + TestInterstitialPageStateGuard state_guard(interstitial); + interstitial->Show(); + // The interstitial should not show until its navigation has committed. + EXPECT_FALSE(interstitial->is_showing()); + EXPECT_FALSE(contents->showing_interstitial_page()); + EXPECT_TRUE(contents->interstitial_page() == NULL); + // Let's commit the interstitial navigation. + interstitial->TestDidNavigate(1, url2); + EXPECT_TRUE(interstitial->is_showing()); + EXPECT_TRUE(contents->showing_interstitial_page()); + EXPECT_TRUE(contents->interstitial_page() == interstitial); + NavigationEntry* entry = contents->controller()->GetActiveEntry(); + ASSERT_TRUE(entry != NULL); + EXPECT_TRUE(entry->url() == url2); + + // Now don't proceed. + interstitial->DontProceed(); + EXPECT_TRUE(deleted); + EXPECT_EQ(TestInterstitialPage::CANCELED, state); + EXPECT_FALSE(contents->showing_interstitial_page()); + EXPECT_TRUE(contents->interstitial_page() == NULL); + entry = contents->controller()->GetActiveEntry(); + ASSERT_TRUE(entry != NULL); + EXPECT_TRUE(entry->url() == url1); + EXPECT_EQ(1, contents->controller()->GetEntryCount()); +} + +// Test navigating to a page that shows an interstitial without creating a new +// navigation entry (this happens when the interstitial is triggered by a +// sub-resource in the page), then hiding it without proceeding. +TEST_F(WebContentsTest, ShowInterstitialNoNewNavigationDontProceed) { + // Navigate to a page. + GURL url1("http://www.google.com"); + Navigate(1, url1); + EXPECT_EQ(1, contents->controller()->GetEntryCount()); + + // Show an interstitial. + TestInterstitialPage::InterstitialState state = + TestInterstitialPage::UNDECIDED; + bool deleted = false; + GURL url2("http://interstitial"); + TestInterstitialPage* interstitial = + new TestInterstitialPage(contents, false, url2, &state, &deleted); + TestInterstitialPageStateGuard state_guard(interstitial); + interstitial->Show(); + // The interstitial should not show until its navigation has committed. + EXPECT_FALSE(interstitial->is_showing()); + EXPECT_FALSE(contents->showing_interstitial_page()); + EXPECT_TRUE(contents->interstitial_page() == NULL); + // Let's commit the interstitial navigation. + interstitial->TestDidNavigate(1, url2); + EXPECT_TRUE(interstitial->is_showing()); + EXPECT_TRUE(contents->showing_interstitial_page()); + EXPECT_TRUE(contents->interstitial_page() == interstitial); + NavigationEntry* entry = contents->controller()->GetActiveEntry(); + ASSERT_TRUE(entry != NULL); + // The URL specified to the interstitial should have been ignored. + EXPECT_TRUE(entry->url() == url1); + + // Now don't proceed. + interstitial->DontProceed(); + EXPECT_TRUE(deleted); + EXPECT_EQ(TestInterstitialPage::CANCELED, state); + EXPECT_FALSE(contents->showing_interstitial_page()); + EXPECT_TRUE(contents->interstitial_page() == NULL); + entry = contents->controller()->GetActiveEntry(); + ASSERT_TRUE(entry != NULL); + EXPECT_TRUE(entry->url() == url1); + EXPECT_EQ(1, contents->controller()->GetEntryCount()); +} + +// Test navigating to a page (with the navigation initiated from the browser, +// as when a URL is typed in the location bar) that shows an interstitial and +// creates a new navigation entry, then proceeding. +TEST_F(WebContentsTest, + ShowInterstitialFromBrowserNewNavigationProceed) { + // Navigate to a page. + GURL url1("http://www.google.com"); + Navigate(1, url1); + EXPECT_EQ(1, contents->controller()->GetEntryCount()); + + // Initiate a browser navigation that will trigger the interstitial + contents->controller()->LoadURL(GURL("http://www.evil.com"), GURL(), + PageTransition::TYPED); + + // Show an interstitial. + TestInterstitialPage::InterstitialState state = + TestInterstitialPage::UNDECIDED; + bool deleted = false; + GURL url2("http://interstitial"); + TestInterstitialPage* interstitial = + new TestInterstitialPage(contents, true, url2, &state, &deleted); + TestInterstitialPageStateGuard state_guard(interstitial); + interstitial->Show(); + // The interstitial should not show until its navigation has committed. + EXPECT_FALSE(interstitial->is_showing()); + EXPECT_FALSE(contents->showing_interstitial_page()); + EXPECT_TRUE(contents->interstitial_page() == NULL); + // Let's commit the interstitial navigation. + interstitial->TestDidNavigate(1, url2); + EXPECT_TRUE(interstitial->is_showing()); + EXPECT_TRUE(contents->showing_interstitial_page()); + EXPECT_TRUE(contents->interstitial_page() == interstitial); + NavigationEntry* entry = contents->controller()->GetActiveEntry(); + ASSERT_TRUE(entry != NULL); + EXPECT_TRUE(entry->url() == url2); + + // Then proceed. + interstitial->Proceed(); + // The interstitial should show until the new navigation commits. + ASSERT_FALSE(deleted); + EXPECT_EQ(TestInterstitialPage::OKED, state); + EXPECT_TRUE(contents->showing_interstitial_page()); + EXPECT_TRUE(contents->interstitial_page() == interstitial); + + // Simulate the navigation to the page, that's when the interstitial gets + // hidden. + GURL url3("http://www.thepage.com"); + Navigate(2, url3); + + EXPECT_TRUE(deleted); + EXPECT_FALSE(contents->showing_interstitial_page()); + EXPECT_TRUE(contents->interstitial_page() == NULL); + entry = contents->controller()->GetActiveEntry(); + ASSERT_TRUE(entry != NULL); + EXPECT_TRUE(entry->url() == url3); + + EXPECT_EQ(2, contents->controller()->GetEntryCount()); +} + +// Test navigating to a page (with the navigation initiated from the renderer, +// as when clicking on a link in the page) that shows an interstitial and +// creates a new navigation entry, then proceeding. +TEST_F(WebContentsTest, + ShowInterstitialFromRendererNewNavigationProceed) { + // Navigate to a page. + GURL url1("http://www.google.com"); + Navigate(1, url1); + EXPECT_EQ(1, contents->controller()->GetEntryCount()); + + // Show an interstitial. + TestInterstitialPage::InterstitialState state = + TestInterstitialPage::UNDECIDED; + bool deleted = false; + GURL url2("http://interstitial"); + TestInterstitialPage* interstitial = + new TestInterstitialPage(contents, true, url2, &state, &deleted); + TestInterstitialPageStateGuard state_guard(interstitial); + interstitial->Show(); + // The interstitial should not show until its navigation has committed. + EXPECT_FALSE(interstitial->is_showing()); + EXPECT_FALSE(contents->showing_interstitial_page()); + EXPECT_TRUE(contents->interstitial_page() == NULL); + // Let's commit the interstitial navigation. + interstitial->TestDidNavigate(1, url2); + EXPECT_TRUE(interstitial->is_showing()); + EXPECT_TRUE(contents->showing_interstitial_page()); + EXPECT_TRUE(contents->interstitial_page() == interstitial); + NavigationEntry* entry = contents->controller()->GetActiveEntry(); + ASSERT_TRUE(entry != NULL); + EXPECT_TRUE(entry->url() == url2); + + // Then proceed. + interstitial->Proceed(); + // The interstitial should show until the new navigation commits. + ASSERT_FALSE(deleted); + EXPECT_EQ(TestInterstitialPage::OKED, state); + EXPECT_TRUE(contents->showing_interstitial_page()); + EXPECT_TRUE(contents->interstitial_page() == interstitial); + + // Simulate the navigation to the page, that's when the interstitial gets + // hidden. + GURL url3("http://www.thepage.com"); + Navigate(2, url3); + + EXPECT_TRUE(deleted); + EXPECT_FALSE(contents->showing_interstitial_page()); + EXPECT_TRUE(contents->interstitial_page() == NULL); + entry = contents->controller()->GetActiveEntry(); + ASSERT_TRUE(entry != NULL); + EXPECT_TRUE(entry->url() == url3); + + EXPECT_EQ(2, contents->controller()->GetEntryCount()); +} + +// Test navigating to a page that shows an interstitial without creating a new +// navigation entry (this happens when the interstitial is triggered by a +// sub-resource in the page), then proceeding. +TEST_F(WebContentsTest, ShowInterstitialNoNewNavigationProceed) { + // Navigate to a page so we have a navigation entry in the controller. + GURL url1("http://www.google.com"); + Navigate(1, url1); + EXPECT_EQ(1, contents->controller()->GetEntryCount()); + + // Show an interstitial. + TestInterstitialPage::InterstitialState state = + TestInterstitialPage::UNDECIDED; + bool deleted = false; + GURL url2("http://interstitial"); + TestInterstitialPage* interstitial = + new TestInterstitialPage(contents, false, url2, &state, &deleted); + TestInterstitialPageStateGuard state_guard(interstitial); + interstitial->Show(); + // The interstitial should not show until its navigation has committed. + EXPECT_FALSE(interstitial->is_showing()); + EXPECT_FALSE(contents->showing_interstitial_page()); + EXPECT_TRUE(contents->interstitial_page() == NULL); + // Let's commit the interstitial navigation. + interstitial->TestDidNavigate(1, url2); + EXPECT_TRUE(interstitial->is_showing()); + EXPECT_TRUE(contents->showing_interstitial_page()); + EXPECT_TRUE(contents->interstitial_page() == interstitial); + NavigationEntry* entry = contents->controller()->GetActiveEntry(); + ASSERT_TRUE(entry != NULL); + // The URL specified to the interstitial should have been ignored. + EXPECT_TRUE(entry->url() == url1); + + // Then proceed. + interstitial->Proceed(); + // Since this is not a new navigation, the previous page is dismissed right + // away and shows the original page. + EXPECT_TRUE(deleted); + EXPECT_EQ(TestInterstitialPage::OKED, state); + EXPECT_FALSE(contents->showing_interstitial_page()); + EXPECT_TRUE(contents->interstitial_page() == NULL); + entry = contents->controller()->GetActiveEntry(); + ASSERT_TRUE(entry != NULL); + EXPECT_TRUE(entry->url() == url1); + + EXPECT_EQ(1, contents->controller()->GetEntryCount()); +} + +// Test navigating to a page that shows an interstitial, then navigating away. +TEST_F(WebContentsTest, ShowInterstitialThenNavigate) { + // Show interstitial. + TestInterstitialPage::InterstitialState state = + TestInterstitialPage::UNDECIDED; + bool deleted = false; + GURL url("http://interstitial"); + TestInterstitialPage* interstitial = + new TestInterstitialPage(contents, true, url, &state, &deleted); + TestInterstitialPageStateGuard state_guard(interstitial); + interstitial->Show(); + interstitial->TestDidNavigate(1, url); + + // While interstitial showing, navigate to a new URL. + const GURL url2("http://www.yahoo.com"); + Navigate(1, url2); + + EXPECT_TRUE(deleted); + EXPECT_EQ(TestInterstitialPage::CANCELED, state); +} + +// Test navigating to a page that shows an interstitial, then close the tab. +TEST_F(WebContentsTest, ShowInterstitialThenCloseTab) { + // Show interstitial. + TestInterstitialPage::InterstitialState state = + TestInterstitialPage::UNDECIDED; + bool deleted = false; + GURL url("http://interstitial"); + TestInterstitialPage* interstitial = + new TestInterstitialPage(contents, true, url, &state, &deleted); + TestInterstitialPageStateGuard state_guard(interstitial); + interstitial->Show(); + interstitial->TestDidNavigate(1, url); + + // Now close the tab. + contents->CloseContents(); + contents = NULL; // So we don't detroy it again on TearDown. + EXPECT_TRUE(deleted); + EXPECT_EQ(TestInterstitialPage::CANCELED, state); +} + +// Test that after Proceed is called and an interstitial is still shown, no more +// commands get executed. +TEST_F(WebContentsTest, ShowInterstitialProceedMultipleCommands) { + // Navigate to a page so we have a navigation entry in the controller. + GURL url1("http://www.google.com"); + Navigate(1, url1); + EXPECT_EQ(1, contents->controller()->GetEntryCount()); + + // Show an interstitial. + TestInterstitialPage::InterstitialState state = + TestInterstitialPage::UNDECIDED; + bool deleted = false; + GURL url2("http://interstitial"); + TestInterstitialPage* interstitial = + new TestInterstitialPage(contents, true, url2, &state, &deleted); + TestInterstitialPageStateGuard state_guard(interstitial); + interstitial->Show(); + interstitial->TestDidNavigate(1, url2); + + // Run a command. + EXPECT_EQ(0, interstitial->command_received_count()); + interstitial->TestDomOperationResponse("toto"); + EXPECT_EQ(1, interstitial->command_received_count()); + + // Then proceed. + interstitial->Proceed(); + ASSERT_FALSE(deleted); + + // While the navigation to the new page is pending, send other commands, they + // should be ignored. + interstitial->TestDomOperationResponse("hello"); + interstitial->TestDomOperationResponse("hi"); + EXPECT_EQ(1, interstitial->command_received_count()); +} + +// Test showing an interstitial while another interstitial is already showing. +TEST_F(WebContentsTest, ShowInterstitialOnInterstitial) { + // Navigate to a page so we have a navigation entry in the controller. + GURL start_url("http://www.google.com"); + Navigate(1, start_url); + EXPECT_EQ(1, contents->controller()->GetEntryCount()); + + // Show an interstitial. + TestInterstitialPage::InterstitialState state1 = + TestInterstitialPage::UNDECIDED; + bool deleted1 = false; + GURL url1("http://interstitial1"); + TestInterstitialPage* interstitial1 = + new TestInterstitialPage(contents, true, url1, &state1, &deleted1); + TestInterstitialPageStateGuard state_guard1(interstitial1); + interstitial1->Show(); + interstitial1->TestDidNavigate(1, url1); + + // Now show another interstitial. + TestInterstitialPage::InterstitialState state2 = + TestInterstitialPage::UNDECIDED; + bool deleted2 = false; + GURL url2("http://interstitial2"); + TestInterstitialPage* interstitial2 = + new TestInterstitialPage(contents, true, url2, &state2, &deleted2); + TestInterstitialPageStateGuard state_guard2(interstitial2); + interstitial2->Show(); + interstitial2->TestDidNavigate(1, url2); + + // Showing interstitial2 should have caused interstitial1 to go away. + EXPECT_TRUE(deleted1); + EXPECT_EQ(TestInterstitialPage::CANCELED, state1); + + // Let's make sure interstitial2 is working as intended. + ASSERT_FALSE(deleted2); + EXPECT_EQ(TestInterstitialPage::UNDECIDED, state2); + interstitial2->Proceed(); + GURL landing_url("http://www.thepage.com"); + Navigate(2, landing_url); + + EXPECT_TRUE(deleted2); + EXPECT_FALSE(contents->showing_interstitial_page()); + EXPECT_TRUE(contents->interstitial_page() == NULL); + NavigationEntry* entry = contents->controller()->GetActiveEntry(); + ASSERT_TRUE(entry != NULL); + EXPECT_TRUE(entry->url() == landing_url); + EXPECT_EQ(2, contents->controller()->GetEntryCount()); +} + +// Test that navigating away from an interstitial while it's loading cause it +// not to show. +TEST_F(WebContentsTest, NavigateBeforeInterstitialShows) { + // Show an interstitial. + TestInterstitialPage::InterstitialState state = + TestInterstitialPage::UNDECIDED; + bool deleted = false; + GURL interstitial_url("http://interstitial"); + TestInterstitialPage* interstitial = + new TestInterstitialPage(contents, true, interstitial_url, + &state, &deleted); + TestInterstitialPageStateGuard state_guard(interstitial); + interstitial->Show(); + + // Let's simulate a navigation initiated from the browser before the + // interstitial finishes loading. + const GURL url("http://www.google.com"); + contents->controller()->LoadURL(url, GURL(), PageTransition::TYPED); + ASSERT_FALSE(deleted); + EXPECT_FALSE(interstitial->is_showing()); + + // Now let's make the interstitial navigation commit. + interstitial->TestDidNavigate(1, interstitial_url); + + // After it loaded the interstitial should be gone. + EXPECT_TRUE(deleted); + EXPECT_EQ(TestInterstitialPage::CANCELED, state); +} + +// Test showing an interstitial and have its renderer crash. +TEST_F(WebContentsTest, InterstitialCrasher) { + // Show an interstitial. + TestInterstitialPage::InterstitialState state = + TestInterstitialPage::UNDECIDED; + bool deleted = false; + GURL url("http://interstitial"); + TestInterstitialPage* interstitial = + new TestInterstitialPage(contents, true, url, &state, &deleted); + TestInterstitialPageStateGuard state_guard(interstitial); + interstitial->Show(); + // Simulate a renderer crash before the interstitial is shown. + interstitial->TestRendererGone(); + // The interstitial should have been dismissed. + EXPECT_TRUE(deleted); + EXPECT_EQ(TestInterstitialPage::CANCELED, state); + + // Now try again but this time crash the intersitial after it was shown. + interstitial = + new TestInterstitialPage(contents, true, url, &state, &deleted); + interstitial->Show(); + interstitial->TestDidNavigate(1, url); + // Simulate a renderer crash. + interstitial->TestRendererGone(); + // The interstitial should have been dismissed. + EXPECT_TRUE(deleted); + EXPECT_EQ(TestInterstitialPage::CANCELED, state); +} diff --git a/chrome/browser/tab_contents/web_contents_view.cc b/chrome/browser/tab_contents/web_contents_view.cc new file mode 100644 index 0000000..d95fd78 --- /dev/null +++ b/chrome/browser/tab_contents/web_contents_view.cc @@ -0,0 +1,60 @@ +// 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/web_contents_view.h" + +#include "chrome/browser/render_widget_host.h" + +void WebContentsView::RenderWidgetHostDestroyed(RenderWidgetHost* host) { + for (PendingWidgetViews::iterator i = pending_widget_views_.begin(); + i != pending_widget_views_.end(); ++i) { + if (host->view() == i->second) { + pending_widget_views_.erase(i); + return; + } + } +} + +void WebContentsView::CreateNewWindow(int route_id, HANDLE modal_dialog_event) { + // Save the created window associated with the route so we can show it later. + pending_contents_[route_id] = CreateNewWindowInternal(route_id, + modal_dialog_event); +} + +void WebContentsView::CreateNewWidget(int route_id, bool activatable) { + // Save the created widget associated with the route so we can show it later. + pending_widget_views_[route_id] = CreateNewWidgetInternal(route_id, + activatable); +} + +void WebContentsView::ShowCreatedWindow(int route_id, + WindowOpenDisposition disposition, + const gfx::Rect& initial_pos, + bool user_gesture) { + PendingContents::iterator iter = pending_contents_.find(route_id); + if (iter == pending_contents_.end()) { + DCHECK(false); + return; + } + + WebContents* new_web_contents = iter->second; + pending_contents_.erase(route_id); + + ShowCreatedWindowInternal(new_web_contents, disposition, initial_pos, + user_gesture); +} + +void WebContentsView::ShowCreatedWidget(int route_id, + const gfx::Rect& initial_pos) { + PendingWidgetViews::iterator iter = pending_widget_views_.find(route_id); + if (iter == pending_widget_views_.end()) { + DCHECK(false); + return; + } + + RenderWidgetHostView* widget_host_view = iter->second; + pending_widget_views_.erase(route_id); + + ShowCreatedWidgetInternal(widget_host_view, initial_pos); +} diff --git a/chrome/browser/tab_contents/web_contents_view.h b/chrome/browser/tab_contents/web_contents_view.h new file mode 100644 index 0000000..232b449 --- /dev/null +++ b/chrome/browser/tab_contents/web_contents_view.h @@ -0,0 +1,191 @@ +// 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. + +#ifndef CHROME_BROWSER_WEB_CONTENTS_VIEW_H_ +#define CHROME_BROWSER_WEB_CONTENTS_VIEW_H_ + +#include + +#include +#include + +#include "base/basictypes.h" +#include "base/gfx/rect.h" +#include "base/gfx/size.h" +#include "chrome/browser/render_view_host_delegate.h" + +class Browser; +class RenderViewHost; +class RenderWidgetHost; +class RenderWidgetHostView; +class RenderWidgetHostViewWin; // TODO(brettw) this should not be necessary. +class WebContents; +struct WebDropData; +class WebKeyboardEvent; + +// The WebContentsView is an interface that is implemented by the platform- +// dependent web contents views. The WebContents 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 WebContentsView : public RenderViewHostDelegate::View { + public: + virtual ~WebContentsView() {} + + virtual WebContents* GetWebContents() = 0; + + virtual void CreateView() = 0; + + // Sets up the View that holds the rendered web page, receives messages for + // it and contains page plugins. + // TODO(brettw) make this so we don't need to return the Win version (see the + // caller in WebContents). + virtual RenderWidgetHostViewWin* CreateViewForWidget( + RenderWidgetHost* render_widget_host) = 0; + + // Returns the HWND that contains the contents of the tab. + // TODO(brettw) this should not be necessary in this cross-platform interface. + virtual HWND GetContainerHWND() const = 0; + + // Returns the HWND 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 HWND). + // TODO(brettw) this should not be necessary in this cross-platform interface. + virtual HWND GetContentHWND() 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()); + } + + // Called when the WebContents is being destroyed. This should clean up child + // windows that are part of the view. + // + // TODO(brettw) It seems like this might be able to be done internally as the + // window is being torn down without input from the WebContents. Try to + // implement functions that way rather than adding stuff here. + virtual void OnContentsDestroy() = 0; + + // 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; + + // Schedules a complete repaint of the window. This is used for cases where + // the existing contents became invalid due to an external event, such as the + // renderer crashing. + virtual void Invalidate() = 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); + + // Find in page -------------------------------------------------------------- + + // Opens the find in page window if it isn't already open. It will advance to + // the next match if |find_next| is set and there is a search string, + // otherwise, the find window will merely be opened. |forward_direction| + // indicates the direction to search when find_next is set, otherwise it is + // ignored. + virtual void FindInPage(const Browser& browser, + bool find_next, bool forward_direction) = 0; + + // Hides the find bar if there is one shown. Does nothing otherwise. The find + // bar will not be deleted, merely hidden. This ensures that any search terms + // are preserved if the user subsequently opens the find bar. + // + // If |end_session| is true, then the find session will be ended, which + // indicates the user requested they no longer be in find mode for that tab. + // The find bar will not be restored when we switch back to the tab. + // Otherwise, we assume that the find bar is being hidden because the tab is + // being hidden, and all state like visibility and tickmarks will be restored + // when the tab comes back. + virtual void HideFindBar(bool end_session) = 0; + + // Called when the tab is reparented to a new browser window. On MS Windows, + // we have to change the parent of our find bar to go with the new window. + // + // TODO(brettw) this seems like it could be improved. Possibly all doohickies + // around the tab like this, the download bar etc. should be managed by the + // BrowserView2 object. + virtual void ReparentFindWindow(Browser* new_browser) const = 0; + + // Computes the location of the find bar and whether it is fully visible in + // its parent window. The return value indicates if the window is visible at + // all. Both out arguments are required. + // + // This is used for UI tests of the find bar. If the find bar is not currently + // shown (return value of false), the out params will be {(0, 0), false}. + virtual bool GetFindBarWindowInfo(gfx::Point* position, + bool* fully_visible) const = 0; + + protected: + WebContentsView() {} // Abstract interface. + + // Internal interface for some functions in the RenderViewHostDelegate::View + // interface. Subclasses should implement this rather than the corresponding + // ...::View functions directly, since the routing stuff will already be + // computed. They should implement the rest of the functions as normal. + // + // The only difference is that the Create functions return the newly + // created objects so that they can be associated with the given routes. When + // they are shown later, we'll look them up again and pass the objects to + // the Show functions rather than the route ID. + virtual WebContents* CreateNewWindowInternal(int route_id, + HANDLE modal_dialog_event) = 0; + virtual RenderWidgetHostView* CreateNewWidgetInternal(int route_id, + bool activatable) = 0; + virtual void ShowCreatedWindowInternal(WebContents* new_web_contents, + WindowOpenDisposition disposition, + const gfx::Rect& initial_pos, + bool user_gesture) = 0; + virtual void ShowCreatedWidgetInternal(RenderWidgetHostView* widget_host_view, + const gfx::Rect& initial_pos) = 0; + + 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, HANDLE modal_dialog_event); + virtual void CreateNewWidget(int route_id, bool activatable); + 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); + + // Tracks created WebContents objects that have not been shown yet. They are + // identified by the route ID passed to CreateNewWindow. + typedef std::map 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 PendingWidgetViews; + PendingWidgetViews pending_widget_views_; + + DISALLOW_COPY_AND_ASSIGN(WebContentsView); +}; + +#endif // CHROME_BROWSER_WEB_CONTENTS_VIEW_H_ diff --git a/chrome/browser/tab_contents/web_contents_view_win.cc b/chrome/browser/tab_contents/web_contents_view_win.cc new file mode 100644 index 0000000..ab244cc --- /dev/null +++ b/chrome/browser/tab_contents/web_contents_view_win.cc @@ -0,0 +1,646 @@ +// 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/web_contents_view_win.h" + +#include + +#include "chrome/browser/bookmarks/bookmark_drag_data.h" +#include "chrome/browser/browser.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/download/download_request_manager.h" +#include "chrome/browser/render_view_context_menu.h" +#include "chrome/browser/render_view_context_menu_controller.h" +#include "chrome/browser/render_view_host.h" +#include "chrome/browser/render_widget_host_view_win.h" +#include "chrome/browser/tab_contents/interstitial_page.h" +#include "chrome/browser/tab_contents/tab_contents_delegate.h" +#include "chrome/browser/tab_contents/web_contents.h" +#include "chrome/browser/tab_contents/web_drag_source.h" +#include "chrome/browser/tab_contents/web_drop_target.h" +#include "chrome/browser/views/find_bar_win.h" +#include "chrome/browser/views/sad_tab_view.h" +#include "chrome/common/gfx/chrome_canvas.h" +#include "chrome/common/os_exchange_data.h" +#include "webkit/glue/plugins/webplugin_delegate_impl.h" + +namespace { + +// Windows callback for OnDestroy to detach the plugin windows. +BOOL CALLBACK DetachPluginWindowsCallback(HWND window, LPARAM param) { + if (WebPluginDelegateImpl::IsPluginDelegateWindow(window)) { + ::ShowWindow(window, SW_HIDE); + SetParent(window, NULL); + } + return TRUE; +} + +} // namespace + +WebContentsViewWin::WebContentsViewWin(WebContents* web_contents) + : web_contents_(web_contents), + ignore_next_char_event_(false) { +} + +WebContentsViewWin::~WebContentsViewWin() { +} + +WebContents* WebContentsViewWin::GetWebContents() { + return web_contents_; +} + +void WebContentsViewWin::CreateView() { + set_delete_on_destroy(false); + // Since we create these windows parented to the desktop window initially, we + // don't want to create them initially visible. + set_window_style(WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS); + WidgetWin::Init(GetDesktopWindow(), gfx::Rect(), false); + + // Remove the root view drop target so we can register our own. + RevokeDragDrop(GetHWND()); + drop_target_ = new WebDropTarget(GetHWND(), web_contents_); +} + +RenderWidgetHostViewWin* WebContentsViewWin::CreateViewForWidget( + RenderWidgetHost* render_widget_host) { + DCHECK(!render_widget_host->view()); + RenderWidgetHostViewWin* view = + new RenderWidgetHostViewWin(render_widget_host); + view->Create(GetHWND()); + view->ShowWindow(SW_SHOW); + return view; +} + +HWND WebContentsViewWin::GetContainerHWND() const { + return GetHWND(); +} + +HWND WebContentsViewWin::GetContentHWND() const { + if (!web_contents_->render_widget_host_view()) + return NULL; + return web_contents_->render_widget_host_view()->GetPluginHWND(); +} + +void WebContentsViewWin::GetContainerBounds(gfx::Rect* out) const { + GetBounds(out, false); +} + +void WebContentsViewWin::StartDragging(const WebDropData& drop_data) { + scoped_refptr data(new OSExchangeData); + + // TODO(tc): Generate an appropriate drag image. + + // We set the file contents before the URL because the URL also sets file + // contents (to a .URL shortcut). We want to prefer file content data over a + // shortcut so we add it first. + if (!drop_data.file_contents.empty()) { + data->SetFileContents(drop_data.file_description_filename, + drop_data.file_contents); + } + if (!drop_data.text_html.empty()) + data->SetHtml(drop_data.text_html, drop_data.html_base_url); + if (drop_data.url.is_valid()) { + if (drop_data.url.SchemeIs("javascript")) { + // We don't want to allow javascript URLs to be dragged to the desktop, + // but we do want to allow them to be added to the bookmarks bar + // (bookmarklets). + BookmarkDragData::Element bm_elt; + bm_elt.is_url = true; + bm_elt.url = drop_data.url; + bm_elt.title = drop_data.url_title; + + BookmarkDragData bm_drag_data; + bm_drag_data.elements.push_back(bm_elt); + + bm_drag_data.Write(web_contents_->profile(), data); + } else { + data->SetURL(drop_data.url, drop_data.url_title); + } + } + if (!drop_data.plain_text.empty()) + data->SetString(drop_data.plain_text); + + scoped_refptr drag_source( + new WebDragSource(GetHWND(), web_contents_->render_view_host())); + + DWORD effects; + + // We need to enable recursive tasks on the message loop so we can get + // updates while in the system DoDragDrop loop. + bool old_state = MessageLoop::current()->NestableTasksAllowed(); + MessageLoop::current()->SetNestableTasksAllowed(true); + DoDragDrop(data, drag_source, DROPEFFECT_COPY | DROPEFFECT_LINK, &effects); + MessageLoop::current()->SetNestableTasksAllowed(old_state); + + if (web_contents_->render_view_host()) + web_contents_->render_view_host()->DragSourceSystemDragEnded(); +} + +void WebContentsViewWin::OnContentsDestroy() { + // TODO(brettw) this seems like maybe it can be moved into OnDestroy and this + // function can be deleted? If you're adding more here, consider whether it + // can be moved into OnDestroy which is a Windows message handler as the + // window is being torn down. + + // When a tab is closed all its child plugin windows are destroyed + // automatically. This happens before plugins get any notification that its + // instances are tearing down. + // + // Plugins like Quicktime assume that their windows will remain valid as long + // as they have plugin instances active. Quicktime crashes in this case + // because its windowing code cleans up an internal data structure that the + // handler for NPP_DestroyStream relies on. + // + // The fix is to detach plugin windows from web contents when it is going + // away. This will prevent the plugin windows from getting destroyed + // automatically. The detached plugin windows will get cleaned up in proper + // sequence as part of the usual cleanup when the plugin instance goes away. + EnumChildWindows(GetHWND(), DetachPluginWindowsCallback, NULL); + + // Close the find bar if any. + if (find_bar_.get()) + find_bar_->Close(); +} + +void WebContentsViewWin::OnDestroy() { + if (drop_target_.get()) { + RevokeDragDrop(GetHWND()); + drop_target_ = NULL; + } +} + +void WebContentsViewWin::SetPageTitle(const std::wstring& title) { + if (GetContainerHWND()) { + // It's possible to get this after the hwnd has been destroyed. + ::SetWindowText(GetContainerHWND(), title.c_str()); + // TODO(brettw) this call seems messy the way it reaches into the widget + // view, and I'm not sure it's necessary. Maybe we should just remove it. + ::SetWindowText(web_contents_->render_widget_host_view()->GetPluginHWND(), + title.c_str()); + } +} + +void WebContentsViewWin::Invalidate() { + // Note that it's possible to get this message after the window was destroyed. + if (::IsWindow(GetContainerHWND())) + InvalidateRect(GetContainerHWND(), NULL, FALSE); +} + +void WebContentsViewWin::SizeContents(const gfx::Size& size) { + // TODO(brettw) this is a hack and should be removed. See web_contents_view.h. + WasSized(size); +} + +void WebContentsViewWin::FindInPage(const Browser& browser, + bool find_next, bool forward_direction) { + if (!find_bar_.get()) { + // We want the Chrome top-level (Frame) window. + HWND hwnd = reinterpret_cast(browser.window()->GetNativeHandle()); + find_bar_.reset(new FindBarWin(this, hwnd)); + } else { + find_bar_->Show(); + } + + if (find_next && !find_bar_->find_string().empty()) + find_bar_->StartFinding(forward_direction); +} + +void WebContentsViewWin::HideFindBar(bool end_session) { + if (find_bar_.get()) { + if (end_session) + find_bar_->EndFindSession(); + else + find_bar_->DidBecomeUnselected(); + } +} + +void WebContentsViewWin::ReparentFindWindow(Browser* new_browser) const { + if (find_bar_.get()) { + find_bar_->SetParent( + reinterpret_cast(new_browser->window()->GetNativeHandle())); + } +} + +bool WebContentsViewWin::GetFindBarWindowInfo(gfx::Point* position, + bool* fully_visible) const { + CRect window_rect; + if (!find_bar_.get() || + !::IsWindow(find_bar_->GetHWND()) || + !::GetWindowRect(find_bar_->GetHWND(), &window_rect)) { + *position = gfx::Point(0, 0); + *fully_visible = false; + return false; + } + + *position = gfx::Point(window_rect.TopLeft().x, window_rect.TopLeft().y); + *fully_visible = find_bar_->IsVisible() && !find_bar_->IsAnimating(); + return true; +} + +void WebContentsViewWin::UpdateDragCursor(bool is_drop_target) { + drop_target_->set_is_drop_target(is_drop_target); +} + +void WebContentsViewWin::TakeFocus(bool reverse) { + views::FocusManager* focus_manager = + views::FocusManager::GetFocusManager(GetContainerHWND()); + + // We may not have a focus manager if the tab has been switched before this + // message arrived. + if (focus_manager) + focus_manager->AdvanceFocus(reverse); +} + +void WebContentsViewWin::HandleKeyboardEvent(const WebKeyboardEvent& event) { + // Previous calls to TranslateMessage can generate CHAR events as well as + // KEY_DOWN events, even if the latter triggered an accelerator. In these + // cases, we discard the CHAR events. + if (event.type == WebInputEvent::CHAR && ignore_next_char_event_) { + ignore_next_char_event_ = false; + return; + } + ignore_next_char_event_ = false; + + // The renderer returned a keyboard event it did not process. This may be + // a keyboard shortcut that we have to process. + if (event.type == WebInputEvent::KEY_DOWN) { + views::FocusManager* focus_manager = + views::FocusManager::GetFocusManager(GetHWND()); + // We may not have a focus_manager at this point (if the tab has been + // switched by the time this message returned). + if (focus_manager) { + views::Accelerator accelerator(event.key_code, + (event.modifiers & WebInputEvent::SHIFT_KEY) == + WebInputEvent::SHIFT_KEY, + (event.modifiers & WebInputEvent::CTRL_KEY) == + WebInputEvent::CTRL_KEY, + (event.modifiers & WebInputEvent::ALT_KEY) == + WebInputEvent::ALT_KEY); + if (focus_manager->ProcessAccelerator(accelerator, false)) { + ignore_next_char_event_ = true; + return; + } + } + } + + // Any unhandled keyboard/character messages should be defproced. + // This allows stuff like Alt+F4, etc to work correctly. + DefWindowProc(event.actual_message.hwnd, + event.actual_message.message, + event.actual_message.wParam, + event.actual_message.lParam); +} + +void WebContentsViewWin::OnFindReply(int request_id, + int number_of_matches, + const gfx::Rect& selection_rect, + int active_match_ordinal, + bool final_update) { + if (find_bar_.get()) { + find_bar_->OnFindReply(request_id, number_of_matches, selection_rect, + active_match_ordinal, final_update); + } +} + +void WebContentsViewWin::ShowContextMenu( + const ViewHostMsg_ContextMenu_Params& params) { + RenderViewContextMenuController menu_controller(web_contents_, params); + RenderViewContextMenu menu(&menu_controller, + GetHWND(), + params.type, + params.misspelled_word, + params.dictionary_suggestions, + web_contents_->profile()); + + POINT screen_pt = { params.x, params.y }; + MapWindowPoints(GetHWND(), HWND_DESKTOP, &screen_pt, 1); + + // Enable recursive tasks on the message loop so we can get updates while + // the context menu is being displayed. + bool old_state = MessageLoop::current()->NestableTasksAllowed(); + MessageLoop::current()->SetNestableTasksAllowed(true); + menu.RunMenuAt(screen_pt.x, screen_pt.y); + MessageLoop::current()->SetNestableTasksAllowed(old_state); +} + +WebContents* WebContentsViewWin::CreateNewWindowInternal( + int route_id, + HANDLE modal_dialog_event) { + // Create the new web contents. This will automatically create the new + // WebContentsView. In the future, we may want to create the view separately. + WebContents* new_contents = + new WebContents(web_contents_->profile(), + web_contents_->GetSiteInstance(), + web_contents_->render_view_factory_, + route_id, + modal_dialog_event); + new_contents->SetupController(web_contents_->profile()); + WebContentsView* new_view = new_contents->view(); + + new_view->CreateView(); + + // TODO(brettw) it seems bogus that we have to call this function on the + // newly created object and give it one of its own member variables. + new_view->CreateViewForWidget(new_contents->render_view_host()); + return new_contents; +} + +RenderWidgetHostView* WebContentsViewWin::CreateNewWidgetInternal( + int route_id, + bool activatable) { + // Create the widget and its associated view. + // TODO(brettw) can widget creation be cross-platform? + RenderWidgetHost* widget_host = + new RenderWidgetHost(web_contents_->process(), route_id); + RenderWidgetHostViewWin* widget_view = + new RenderWidgetHostViewWin(widget_host); + + // We set the parent HWDN explicitly as pop-up HWNDs are parented and owned by + // the first non-child HWND of the HWND that was specified to the CreateWindow + // call. + // TODO(brettw) this should not need to get the current RVHView from the + // WebContents. We should have it somewhere ourselves. + widget_view->set_parent_hwnd( + web_contents_->render_widget_host_view()->GetPluginHWND()); + widget_view->set_close_on_deactivate(true); + widget_view->set_activatable(activatable); + + return widget_view; +} + +void WebContentsViewWin::ShowCreatedWindowInternal( + WebContents* new_web_contents, + WindowOpenDisposition disposition, + const gfx::Rect& initial_pos, + bool user_gesture) { + if (!new_web_contents->render_widget_host_view() || + !new_web_contents->process()->channel()) { + // The view has gone away or the renderer crashed. Nothing to do. + return; + } + + // TODO(brettw) this seems bogus to reach into here and initialize the host. + new_web_contents->render_view_host()->Init(); + web_contents_->AddNewContents(new_web_contents, disposition, initial_pos, + user_gesture); +} + +void WebContentsViewWin::ShowCreatedWidgetInternal( + RenderWidgetHostView* widget_host_view, + const gfx::Rect& initial_pos) { + // TODO(beng): (Cleanup) move all this windows-specific creation and showing + // code into RenderWidgetHostView behind some API that a + // ChromeView can also reasonably implement. + RenderWidgetHostViewWin* widget_host_view_win = + static_cast(widget_host_view); + + RenderWidgetHost* widget_host = widget_host_view->GetRenderWidgetHost(); + if (!widget_host->process()->channel()) { + // The view has gone away or the renderer crashed. Nothing to do. + return; + } + + // This logic should be implemented by RenderWidgetHostHWND (as mentioned + // above) in the ::Init function, which should take a parent and some initial + // bounds. + widget_host_view_win->Create(GetContainerHWND(), NULL, NULL, + WS_POPUP, WS_EX_TOOLWINDOW); + widget_host_view_win->MoveWindow(initial_pos.x(), initial_pos.y(), + initial_pos.width(), initial_pos.height(), + TRUE); + widget_host_view_win->ShowWindow(widget_host_view_win->activatable() ? + SW_SHOW : SW_SHOWNA); + widget_host->Init(); +} + +void WebContentsViewWin::OnHScroll(int scroll_type, short position, + HWND scrollbar) { + ScrollCommon(WM_HSCROLL, scroll_type, position, scrollbar); +} + +void WebContentsViewWin::OnMouseLeave() { + // Let our delegate know that the mouse moved (useful for resetting status + // bubble state). + if (web_contents_->delegate()) + web_contents_->delegate()->ContentsMouseEvent(web_contents_, WM_MOUSELEAVE); + SetMsgHandled(FALSE); +} + +LRESULT WebContentsViewWin::OnMouseRange(UINT msg, + WPARAM w_param, LPARAM l_param) { + switch (msg) { + case WM_LBUTTONDOWN: + case WM_MBUTTONDOWN: + case WM_RBUTTONDOWN: { + // Make sure this TabContents is activated when it is clicked on. + if (web_contents_->delegate()) + web_contents_->delegate()->ActivateContents(web_contents_); + DownloadRequestManager* drm = + g_browser_process->download_request_manager(); + if (drm) + drm->OnUserGesture(web_contents_); + break; + } + case WM_MOUSEMOVE: + // Let our delegate know that the mouse moved (useful for resetting status + // bubble state). + if (web_contents_->delegate()) { + web_contents_->delegate()->ContentsMouseEvent(web_contents_, + WM_MOUSEMOVE); + } + break; + default: + break; + } + + return 0; +} + +void WebContentsViewWin::OnPaint(HDC junk_dc) { + if (web_contents_->render_view_host() && + !web_contents_->render_view_host()->IsRenderViewLive()) { + if (!sad_tab_.get()) + sad_tab_.reset(new SadTabView); + CRect cr; + GetClientRect(&cr); + sad_tab_->SetBounds(gfx::Rect(cr)); + ChromeCanvasPaint canvas(GetHWND(), true); + sad_tab_->ProcessPaint(&canvas); + return; + } + + // We need to do this to validate the dirty area so we don't end up in a + // WM_PAINTstorm that causes other mysterious bugs (such as WM_TIMERs not + // firing etc). It doesn't matter that we don't have any non-clipped area. + CPaintDC dc(GetHWND()); + SetMsgHandled(FALSE); +} + +// A message is reflected here from view(). +// Return non-zero to indicate that it is handled here. +// Return 0 to allow view() to further process it. +LRESULT WebContentsViewWin::OnReflectedMessage(UINT msg, WPARAM w_param, + LPARAM l_param) { + MSG* message = reinterpret_cast(l_param); + switch (message->message) { + case WM_MOUSEWHEEL: + // This message is reflected from the view() to this window. + if (GET_KEYSTATE_WPARAM(message->wParam) & MK_CONTROL) { + WheelZoom(GET_WHEEL_DELTA_WPARAM(message->wParam)); + return 1; + } + break; + case WM_HSCROLL: + case WM_VSCROLL: + if (ScrollZoom(LOWORD(message->wParam))) + return 1; + default: + break; + } + + return 0; +} + +void WebContentsViewWin::OnSetFocus(HWND window) { + // TODO(jcampan): figure out why removing this prevents tabs opened in the + // background from properly taking focus. + // We NULL-check the render_view_host_ here because Windows can send us + // messages during the destruction process after it has been destroyed. + if (web_contents_->render_widget_host_view()) { + HWND inner_hwnd = web_contents_->render_widget_host_view()->GetPluginHWND(); + if (::IsWindow(inner_hwnd)) + ::SetFocus(inner_hwnd); + } +} + +void WebContentsViewWin::OnVScroll(int scroll_type, short position, + HWND scrollbar) { + ScrollCommon(WM_VSCROLL, scroll_type, position, scrollbar); +} + +void WebContentsViewWin::OnWindowPosChanged(WINDOWPOS* window_pos) { + if (window_pos->flags & SWP_HIDEWINDOW) { + WasHidden(); + } else { + // The WebContents was shown by a means other than the user selecting a + // Tab, e.g. the window was minimized then restored. + if (window_pos->flags & SWP_SHOWWINDOW) + WasShown(); + + // Unless we were specifically told not to size, cause the renderer to be + // sized to the new bounds, which forces a repaint. Not required for the + // simple minimize-restore case described above, for example, since the + // size hasn't changed. + if (!(window_pos->flags & SWP_NOSIZE)) + WasSized(gfx::Size(window_pos->cx, window_pos->cy)); + + // If we have a FindInPage dialog, notify it that the window changed. + if (find_bar_.get() && find_bar_->IsVisible()) + find_bar_->MoveWindowIfNecessary(gfx::Rect()); + } +} + +void WebContentsViewWin::OnSize(UINT param, const CSize& size) { + WidgetWin::OnSize(param, size); + + // Hack for thinkpad touchpad driver. + // Set fake scrollbars so that we can get scroll messages, + SCROLLINFO si = {0}; + si.cbSize = sizeof(si); + si.fMask = SIF_ALL; + + si.nMin = 1; + si.nMax = 100; + si.nPage = 10; + si.nPos = 50; + + ::SetScrollInfo(GetHWND(), SB_HORZ, &si, FALSE); + ::SetScrollInfo(GetHWND(), SB_VERT, &si, FALSE); +} + +LRESULT WebContentsViewWin::OnNCCalcSize(BOOL w_param, LPARAM l_param) { + // Hack for thinkpad mouse wheel driver. We have set the fake scroll bars + // to receive scroll messages from thinkpad touchpad driver. Suppress + // painting of scrollbars by returning 0 size for them. + return 0; +} + +void WebContentsViewWin::OnNCPaint(HRGN rgn) { + // Suppress default WM_NCPAINT handling. We don't need to do anything + // here since the view will draw everything correctly. +} + +void WebContentsViewWin::ScrollCommon(UINT message, int scroll_type, + short position, HWND scrollbar) { + // This window can receive scroll events as a result of the ThinkPad's + // Trackpad scroll wheel emulation. + if (!ScrollZoom(scroll_type)) { + // Reflect scroll message to the view() to give it a chance + // to process scrolling. + SendMessage(GetContentHWND(), message, MAKELONG(scroll_type, position), + (LPARAM) scrollbar); + } +} + +void WebContentsViewWin::WasHidden() { + web_contents_->HideContents(); + if (find_bar_.get()) + find_bar_->DidBecomeUnselected(); +} + +void WebContentsViewWin::WasShown() { + web_contents_->ShowContents(); + if (find_bar_.get()) + find_bar_->DidBecomeSelected(); +} + +void WebContentsViewWin::WasSized(const gfx::Size& size) { + if (web_contents_->interstitial_page()) + web_contents_->interstitial_page()->SetSize(size); + if (web_contents_->render_widget_host_view()) + web_contents_->render_widget_host_view()->SetSize(size); + if (find_bar_.get()) + find_bar_->RespondToResize(size); + + // TODO(brettw) this function can probably be moved to this class. + web_contents_->RepositionSupressedPopupsToFit(size); +} + +bool WebContentsViewWin::ScrollZoom(int scroll_type) { + // If ctrl is held, zoom the UI. There are three issues with this: + // 1) Should the event be eaten or forwarded to content? We eat the event, + // which is like Firefox and unlike IE. + // 2) Should wheel up zoom in or out? We zoom in (increase font size), which + // is like IE and Google maps, but unlike Firefox. + // 3) Should the mouse have to be over the content area? We zoom as long as + // content has focus, although FF and IE require that the mouse is over + // content. This is because all events get forwarded when content has + // focus. + if (GetAsyncKeyState(VK_CONTROL) & 0x8000) { + int distance = 0; + switch (scroll_type) { + case SB_LINEUP: + distance = WHEEL_DELTA; + break; + case SB_LINEDOWN: + distance = -WHEEL_DELTA; + break; + // TODO(joshia): Handle SB_PAGEUP, SB_PAGEDOWN, SB_THUMBPOSITION, + // and SB_THUMBTRACK for completeness + default: + break; + } + + WheelZoom(distance); + return true; + } + return false; +} + +void WebContentsViewWin::WheelZoom(int distance) { + if (web_contents_->delegate()) { + bool zoom_in = distance > 0; + web_contents_->delegate()->ContentsZoomChange(zoom_in); + } +} diff --git a/chrome/browser/tab_contents/web_contents_view_win.h b/chrome/browser/tab_contents/web_contents_view_win.h new file mode 100644 index 0000000..137674a --- /dev/null +++ b/chrome/browser/tab_contents/web_contents_view_win.h @@ -0,0 +1,128 @@ +// 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. + +#ifndef CHROME_BROWSER_WEB_CONTENTS_VIEW_WIN_H_ +#define CHROME_BROWSER_WEB_CONTENTS_VIEW_WIN_H_ + +#include "base/gfx/size.h" +#include "base/scoped_ptr.h" +#include "chrome/browser/tab_contents/web_contents_view.h" +#include "chrome/views/widget_win.h" + +class FindBarWin; +class SadTabView; +struct WebDropData; +class WebDropTarget; + +// Windows-specific implementation of the WebContentsView. It is a HWND that +// contains all of the contents of the tab and associated child views. +class WebContentsViewWin : public WebContentsView, + public views::WidgetWin { + public: + // The corresponding WebContents is passed in the constructor, and manages our + // lifetime. This doesn't need to be the case, but is this way currently + // because that's what was easiest when they were split. + explicit WebContentsViewWin(WebContents* web_contents); + virtual ~WebContentsViewWin(); + + // WebContentsView implementation -------------------------------------------- + + virtual WebContents* GetWebContents(); + virtual void CreateView(); + virtual RenderWidgetHostViewWin* CreateViewForWidget( + RenderWidgetHost* render_widget_host); + virtual HWND GetContainerHWND() const; + virtual HWND GetContentHWND() const; + virtual void GetContainerBounds(gfx::Rect* out) const; + virtual void OnContentsDestroy(); + virtual void SetPageTitle(const std::wstring& title); + virtual void Invalidate(); + virtual void SizeContents(const gfx::Size& size); + virtual void FindInPage(const Browser& browser, + bool find_next, bool forward_direction); + virtual void HideFindBar(bool end_session); + virtual void ReparentFindWindow(Browser* new_browser) const; + virtual bool GetFindBarWindowInfo(gfx::Point* position, + bool* fully_visible) const; + + // Backend implementation of RenderViewHostDelegate::View. + virtual WebContents* CreateNewWindowInternal( + int route_id, HANDLE modal_dialog_event); + virtual RenderWidgetHostView* CreateNewWidgetInternal(int route_id, + bool activatable); + virtual void ShowCreatedWindowInternal(WebContents* new_web_contents, + WindowOpenDisposition disposition, + const gfx::Rect& initial_pos, + bool user_gesture); + virtual void ShowCreatedWidgetInternal(RenderWidgetHostView* widget_host_view, + const gfx::Rect& initial_pos); + virtual void ShowContextMenu( + const ViewHostMsg_ContextMenu_Params& params); + virtual void StartDragging(const WebDropData& drop_data); + virtual void UpdateDragCursor(bool is_drop_target); + virtual void TakeFocus(bool reverse); + virtual void HandleKeyboardEvent(const WebKeyboardEvent& event); + virtual void OnFindReply(int request_id, + int number_of_matches, + const gfx::Rect& selection_rect, + int active_match_ordinal, + bool final_update); + + private: + // Windows events ------------------------------------------------------------ + + // Overrides from WidgetWin. + virtual void OnDestroy(); + virtual void OnHScroll(int scroll_type, short position, HWND scrollbar); + virtual void OnMouseLeave(); + virtual LRESULT OnMouseRange(UINT msg, WPARAM w_param, LPARAM l_param); + virtual void OnPaint(HDC junk_dc); + virtual LRESULT OnReflectedMessage(UINT msg, WPARAM w_param, LPARAM l_param); + virtual void OnSetFocus(HWND window); + virtual void OnVScroll(int scroll_type, short position, HWND scrollbar); + virtual void OnWindowPosChanged(WINDOWPOS* window_pos); + virtual void OnSize(UINT param, const CSize& size); + virtual LRESULT OnNCCalcSize(BOOL w_param, LPARAM l_param); + virtual void OnNCPaint(HRGN rgn); + + // Backend for all scroll messages, the |message| parameter indicates which + // one it is. + void ScrollCommon(UINT message, int scroll_type, short position, + HWND scrollbar); + + // Handles notifying the WebContents and other operations when the window was + // shown or hidden. + void WasHidden(); + void WasShown(); + + // Handles resizing of the contents. This will notify the RenderWidgetHostView + // of the change, reposition popups, and the find in page bar. + void WasSized(const gfx::Size& size); + + // TODO(brettw) comment these. They're confusing. + bool ScrollZoom(int scroll_type); + void WheelZoom(int distance); + + // --------------------------------------------------------------------------- + + WebContents* web_contents_; + + // For find in page. This may be NULL if there is no find bar, and if it is + // non-NULL, it may or may not be visible. + scoped_ptr find_bar_; + + // A drop target object that handles drags over this WebContents. + scoped_refptr drop_target_; + + // Used to render the sad tab. This will be non-NULL only when the sad tab is + // visible. + scoped_ptr sad_tab_; + + // Whether to ignore the next CHAR keyboard event. + bool ignore_next_char_event_; + + DISALLOW_COPY_AND_ASSIGN(WebContentsViewWin); +}; + +#endif // CHROME_BROWSER_WEB_CONTENTS_VIEW_WIN_H_ diff --git a/chrome/browser/tab_contents/web_drag_source.cc b/chrome/browser/tab_contents/web_drag_source.cc new file mode 100644 index 0000000..b47913b --- /dev/null +++ b/chrome/browser/tab_contents/web_drag_source.cc @@ -0,0 +1,45 @@ +// 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 +#include +#include + +#include "chrome/browser/tab_contents/web_drag_source.h" + +#include "chrome/browser/render_view_host.h" + +namespace { + +static void GetCursorPositions(HWND hwnd, CPoint* client, CPoint* screen) { + GetCursorPos(screen); + *client = *screen; + ScreenToClient(hwnd, client); +} + +} // namespace +/////////////////////////////////////////////////////////////////////////////// +// WebDragSource, public: + +WebDragSource::WebDragSource(HWND source_hwnd, + RenderViewHost* render_view_host) + : BaseDragSource(), + source_hwnd_(source_hwnd), + render_view_host_(render_view_host) { +} + +void WebDragSource::OnDragSourceDrop() { + CPoint client; + CPoint screen; + GetCursorPositions(source_hwnd_, &client, &screen); + render_view_host_->DragSourceEndedAt(client.x, client.y, screen.x, screen.y); +} + +void WebDragSource::OnDragSourceMove() { + CPoint client; + CPoint screen; + GetCursorPositions(source_hwnd_, &client, &screen); + render_view_host_->DragSourceMovedTo(client.x, client.y, screen.x, screen.y); +} + diff --git a/chrome/browser/tab_contents/web_drag_source.h b/chrome/browser/tab_contents/web_drag_source.h new file mode 100644 index 0000000..f8aa628 --- /dev/null +++ b/chrome/browser/tab_contents/web_drag_source.h @@ -0,0 +1,49 @@ +// 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. + +#ifndef CHROME_BROWSER_WEB_DRAG_SOURCE_H__ +#define CHROME_BROWSER_WEB_DRAG_SOURCE_H__ + +#include "base/base_drag_source.h" +#include "base/basictypes.h" + +class RenderViewHost; + +/////////////////////////////////////////////////////////////////////////////// +// +// WebDragSource +// +// An IDropSource implementation for a WebContents. Handles notifications sent +// by an active drag-drop operation as the user mouses over other drop targets +// on their system. This object tells Windows whether or not the drag should +// continue, and supplies the appropriate cursors. +// +class WebDragSource : public BaseDragSource { + public: + // Create a new DragSource for a given HWND and RenderViewHost. + WebDragSource(HWND source_hwnd, RenderViewHost* render_view_host); + virtual ~WebDragSource() { } + + protected: + // BaseDragSource + virtual void OnDragSourceDrop(); + virtual void OnDragSourceMove(); + + private: + // Cannot construct thusly. + WebDragSource(); + + // Keep a reference to the HWND so we can translate the cursor position. + HWND source_hwnd_; + + // We use this as a channel to the renderer to tell it about various drag + // drop events that it needs to know about (such as when a drag operation it + // initiated terminates). + RenderViewHost* render_view_host_; + + DISALLOW_EVIL_CONSTRUCTORS(WebDragSource); +}; + +#endif // #ifndef CHROME_BROWSER_WEB_DRAG_SOURCE_H__ + diff --git a/chrome/browser/tab_contents/web_drop_target.cc b/chrome/browser/tab_contents/web_drop_target.cc new file mode 100644 index 0000000..c3220e5 --- /dev/null +++ b/chrome/browser/tab_contents/web_drop_target.cc @@ -0,0 +1,182 @@ +// 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 +#include + +#include "chrome/browser/tab_contents/web_drop_target.h" + +#include "base/clipboard_util.h" +#include "base/gfx/point.h" +#include "chrome/browser/render_view_host.h" +#include "chrome/browser/tab_contents/web_contents.h" +#include "chrome/common/os_exchange_data.h" +#include "googleurl/src/gurl.h" +#include "net/base/net_util.h" +#include "webkit/glue/webdropdata.h" +#include "webkit/glue/window_open_disposition.h" + +namespace { + +// A helper method for getting the preferred drop effect. +DWORD GetPreferredDropEffect(DWORD effect) { + if (effect & DROPEFFECT_COPY) + return DROPEFFECT_COPY; + if (effect & DROPEFFECT_LINK) + return DROPEFFECT_LINK; + if (effect & DROPEFFECT_MOVE) + return DROPEFFECT_MOVE; + return DROPEFFECT_NONE; +} + +} // anonymous namespace + +// InterstitialDropTarget is like a BaseDropTarget implementation that +// WebDropTarget passes through to if an interstitial is showing. Rather than +// passing messages on to the renderer, we just check to see if there's a link +// in the drop data and handle links as navigations. +class InterstitialDropTarget { + public: + explicit InterstitialDropTarget(WebContents* web_contents) + : web_contents_(web_contents) {} + + DWORD OnDragEnter(IDataObject* data_object, DWORD effect) { + return ClipboardUtil::HasUrl(data_object) ? GetPreferredDropEffect(effect) + : DROPEFFECT_NONE; + } + + DWORD OnDragOver(IDataObject* data_object, DWORD effect) { + return ClipboardUtil::HasUrl(data_object) ? GetPreferredDropEffect(effect) + : DROPEFFECT_NONE; + } + + void OnDragLeave(IDataObject* data_object) { + } + + DWORD OnDrop(IDataObject* data_object, DWORD effect) { + if (ClipboardUtil::HasUrl(data_object)) { + std::wstring url; + std::wstring title; + ClipboardUtil::GetUrl(data_object, &url, &title); + web_contents_->OpenURL(GURL(url), GURL(), CURRENT_TAB, + PageTransition::AUTO_BOOKMARK); + return GetPreferredDropEffect(effect); + } + return DROPEFFECT_NONE; + } + + private: + WebContents* web_contents_; + + DISALLOW_EVIL_CONSTRUCTORS(InterstitialDropTarget); +}; + +/////////////////////////////////////////////////////////////////////////////// +// WebDropTarget, public: + +WebDropTarget::WebDropTarget(HWND source_hwnd, WebContents* web_contents) + : BaseDropTarget(source_hwnd), + web_contents_(web_contents), + current_rvh_(NULL), + is_drop_target_(false), + interstitial_drop_target_(new InterstitialDropTarget(web_contents)) { +} + +WebDropTarget::~WebDropTarget() { +} + +DWORD WebDropTarget::OnDragEnter(IDataObject* data_object, + DWORD key_state, + POINT cursor_position, + DWORD effect) { + current_rvh_ = web_contents_->render_view_host(); + + // Don't pass messages to the renderer if an interstitial page is showing + // because we don't want the interstitial page to navigate. Instead, + // pass the messages on to a separate interstitial DropTarget handler. + if (web_contents_->showing_interstitial_page()) + return interstitial_drop_target_->OnDragEnter(data_object, effect); + + // TODO(tc): PopulateWebDropData can be slow depending on what is in the + // IDataObject. Maybe we can do this in a background thread. + WebDropData drop_data; + WebDropData::PopulateWebDropData(data_object, &drop_data); + + if (drop_data.url.is_empty()) + OSExchangeData::GetPlainTextURL(data_object, &drop_data.url); + + is_drop_target_ = true; + + POINT client_pt = cursor_position; + ScreenToClient(GetHWND(), &client_pt); + web_contents_->render_view_host()->DragTargetDragEnter(drop_data, + gfx::Point(client_pt.x, client_pt.y), + gfx::Point(cursor_position.x, cursor_position.y)); + + // We lie here and always return a DROPEFFECT because we don't want to + // wait for the IPC call to return. + return GetPreferredDropEffect(effect); +} + +DWORD WebDropTarget::OnDragOver(IDataObject* data_object, + DWORD key_state, + POINT cursor_position, + DWORD effect) { + DCHECK(current_rvh_); + if (current_rvh_ != web_contents_->render_view_host()) + OnDragEnter(data_object, key_state, cursor_position, effect); + + if (web_contents_->showing_interstitial_page()) + return interstitial_drop_target_->OnDragOver(data_object, effect); + + POINT client_pt = cursor_position; + ScreenToClient(GetHWND(), &client_pt); + web_contents_->render_view_host()->DragTargetDragOver( + gfx::Point(client_pt.x, client_pt.y), + gfx::Point(cursor_position.x, cursor_position.y)); + + if (!is_drop_target_) + return DROPEFFECT_NONE; + + return GetPreferredDropEffect(effect); +} + +void WebDropTarget::OnDragLeave(IDataObject* data_object) { + DCHECK(current_rvh_); + if (current_rvh_ != web_contents_->render_view_host()) + return; + + if (web_contents_->showing_interstitial_page()) { + interstitial_drop_target_->OnDragLeave(data_object); + } else { + web_contents_->render_view_host()->DragTargetDragLeave(); + } +} + +DWORD WebDropTarget::OnDrop(IDataObject* data_object, + DWORD key_state, + POINT cursor_position, + DWORD effect) { + DCHECK(current_rvh_); + if (current_rvh_ != web_contents_->render_view_host()) + OnDragEnter(data_object, key_state, cursor_position, effect); + + if (web_contents_->showing_interstitial_page()) + interstitial_drop_target_->OnDragOver(data_object, effect); + + if (web_contents_->showing_interstitial_page()) + return interstitial_drop_target_->OnDrop(data_object, effect); + + POINT client_pt = cursor_position; + ScreenToClient(GetHWND(), &client_pt); + web_contents_->render_view_host()->DragTargetDrop( + gfx::Point(client_pt.x, client_pt.y), + gfx::Point(cursor_position.x, cursor_position.y)); + + current_rvh_ = NULL; + + // We lie and always claim that the drop operation didn't happen because we + // don't want to wait for the renderer to respond. + return DROPEFFECT_NONE; +} diff --git a/chrome/browser/tab_contents/web_drop_target.h b/chrome/browser/tab_contents/web_drop_target.h new file mode 100644 index 0000000..28f4073 --- /dev/null +++ b/chrome/browser/tab_contents/web_drop_target.h @@ -0,0 +1,74 @@ +// 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. + +#ifndef CHROME_BROWSER_WEB_DROP_TARGET_H__ +#define CHROME_BROWSER_WEB_DROP_TARGET_H__ + +#include "base/base_drop_target.h" +#include "base/scoped_ptr.h" + +class InterstitialDropTarget; +class RenderViewHost; +class WebContents; + +/////////////////////////////////////////////////////////////////////////////// +// +// WebDropTarget +// +// A helper object that provides drop capabilities to a WebContents. The +// DropTarget handles drags that enter the region of the WebContents by +// passing on the events to the renderer. +// +class WebDropTarget : public BaseDropTarget { + public: + // Create a new WebDropTarget associating it with the given HWND and + // WebContents. + WebDropTarget(HWND source_hwnd, WebContents* contents); + virtual ~WebDropTarget(); + + void set_is_drop_target(bool is_drop_target) { + is_drop_target_ = is_drop_target; + } + + protected: + virtual DWORD OnDragEnter(IDataObject* data_object, + DWORD key_state, + POINT cursor_position, + DWORD effect); + + virtual DWORD OnDragOver(IDataObject* data_object, + DWORD key_state, + POINT cursor_position, + DWORD effect); + + virtual void OnDragLeave(IDataObject* data_object); + + virtual DWORD OnDrop(IDataObject* data_object, + DWORD key_state, + POINT cursor_position, + DWORD effect); + + private: + // Our associated WebContents. + WebContents* web_contents_; + + // We keep track of the render view host we're dragging over. If it changes + // during a drag, we need to re-send the DragEnter message. WARNING: + // this pointer should never be dereferenced. We only use it for comparing + // pointers. + RenderViewHost* current_rvh_; + + // Used to determine what cursor we should display when dragging over web + // content area. This can be updated async during a drag operation. + bool is_drop_target_; + + // A special drop target handler for when we try to d&d while an interstitial + // page is showing. + scoped_ptr interstitial_drop_target_; + + DISALLOW_EVIL_CONSTRUCTORS(WebDropTarget); +}; + +#endif // #ifndef CHROME_BROWSER_WEB_DROP_TARGET_H__ + diff --git a/chrome/browser/tab_contents_delegate.h b/chrome/browser/tab_contents_delegate.h deleted file mode 100644 index 58cf471..0000000 --- a/chrome/browser/tab_contents_delegate.h +++ /dev/null @@ -1,150 +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. - -#ifndef CHROME_BROWSER_TAB_CONTENTS_DELEGATE_H_ -#define CHROME_BROWSER_TAB_CONTENTS_DELEGATE_H_ - -// TODO(maruel): Remove once UINT and HWND are replaced / typedef. -#include - -#include "chrome/browser/page_navigator.h" -#include "chrome/common/navigation_types.h" - -namespace gfx { -class Point; -class Rect; -} - -class TabContents; -class HtmlDialogContentsDelegate; - -// Objects implement this interface to get notified about changes in the -// TabContents and to provide necessary functionality. -class TabContentsDelegate : public PageNavigator { - public: - // Opens a new URL inside the passed in TabContents, if source is 0 open - // in the current front-most tab. - virtual void OpenURLFromTab(TabContents* source, - const GURL& url, const GURL& referrer, - WindowOpenDisposition disposition, - PageTransition::Type transition) = 0; - - virtual void OpenURL(const GURL& url, const GURL& referrer, - WindowOpenDisposition disposition, - PageTransition::Type transition) - { - OpenURLFromTab(NULL, url, referrer, disposition, transition); - } - - // 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; - - // Called to cause the delegate to replace the source contents with the new - // contents. - virtual void ReplaceContents(TabContents* source, - TabContents* new_contents) = 0; - - // 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; - - // 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; - - // 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; - - // Called to determine if the TabContents is contained in a popup window. - virtual bool IsPopup(TabContents* source) = 0; - - // Returns the tab which contains the specified tab content if it is - // constrained, NULL otherwise. - virtual TabContents* GetConstrainingContents(TabContents* source) { - return NULL; - } - - // 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 starredness of the current URL changed. - virtual void URLStarredChanged(TabContents* source, bool starred) = 0; - - // Notification that the target URL has changed - virtual void UpdateTargetURL(TabContents* source, const GURL& url) = 0; - - // Notification that the target URL has changed - virtual void ContentsMouseEvent(TabContents* source, UINT message) { } - - // Request the delegate to change the zoom level of the current tab. - virtual void ContentsZoomChange(bool zoom_in) { } - - // Check whether this contents is inside a window dedicated to running a web - // application. - virtual bool IsApplication() { return false; } - - // Detach the given tab and convert it to a "webapp" view. The tab must be - // a WebContents with a valid WebApp set. - virtual void ConvertContentsToApplication(TabContents* source) { } - - // Informs the TabContentsDelegate that some of our state has changed - // for this tab. - virtual void ContentsStateChanged(TabContents* source) {} - - // Return whether this tab contents should have a URL bar. Only web contents - // opened with a minimal chrome and their popups can be displayed without a - // URL bar. - virtual bool ShouldDisplayURLField() { return true; } - - // Whether this tab can be blurred through a javascript obj.blur() - // call. ConstrainedWindows shouldn't be able to be blurred. - virtual bool CanBlur() const { return true; } - - // 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(HtmlDialogContentsDelegate* delegate, - void* parent_window) { } - - // 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) { - *proceed_to_fire_unload = true; - } - - // Send IPC to external host. Default implementation is do nothing. - virtual void ForwardMessageToExternalHost(const std::string& receiver, - const std::string& message) {}; - - // If the delegate is hosting tabs externally. - virtual bool IsExternalTabContainer() const { return false; } -}; - -#endif // CHROME_BROWSER_TAB_CONTENTS_DELEGATE_H_ diff --git a/chrome/browser/tab_contents_factory.cc b/chrome/browser/tab_contents_factory.cc deleted file mode 100644 index 6a6abba..0000000 --- a/chrome/browser/tab_contents_factory.cc +++ /dev/null @@ -1,162 +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.h" - -#include "chrome/browser/about_internets_status_view.h" -#include "chrome/browser/browser_about_handler.h" -#include "chrome/browser/browser_url_handler.h" -#include "chrome/browser/dom_ui/dom_ui_contents.h" -#include "chrome/browser/dom_ui/html_dialog_contents.h" -#include "chrome/browser/dom_ui/new_tab_ui.h" -#include "chrome/browser/ipc_status_view.h" -#include "chrome/browser/native_ui_contents.h" -#include "chrome/browser/network_status_view.h" -#include "chrome/browser/profile.h" -#include "chrome/browser/render_process_host.h" -#include "chrome/browser/debugger/debugger_contents.h" -#include "chrome/browser/tab_contents_factory.h" -#include "chrome/browser/view_source_contents.h" -#include "chrome/browser/web_contents.h" -#include "base/string_util.h" -#include "net/base/net_util.h" - -typedef std::map TabContentsFactoryMap; -static TabContentsFactoryMap* g_extra_types; // Only allocated if needed. - -// static -TabContentsType TabContentsFactory::NextUnusedType() { - int type = static_cast(TAB_CONTENTS_NUM_TYPES); - if (g_extra_types) { - for (TabContentsFactoryMap::iterator i = g_extra_types->begin(); - i != g_extra_types->end(); ++i) { - type = std::max(type, static_cast(i->first)); - } - } - return static_cast(type + 1); -} - -/*static*/ -TabContents* TabContents::CreateWithType(TabContentsType type, - Profile* profile, - SiteInstance* instance) { - TabContents* contents; - - switch (type) { - case TAB_CONTENTS_WEB: - contents = new WebContents(profile, instance, NULL, MSG_ROUTING_NONE, NULL); - break; - case TAB_CONTENTS_NETWORK_STATUS_VIEW: - contents = new NetworkStatusView(); - break; -#ifdef IPC_MESSAGE_LOG_ENABLED - case TAB_CONTENTS_IPC_STATUS_VIEW: - contents = new IPCStatusView(); - break; -#endif - case TAB_CONTENTS_NEW_TAB_UI: - contents = new NewTabUIContents(profile, instance, NULL); - break; - case TAB_CONTENTS_HTML_DIALOG: - contents = new HtmlDialogContents(profile, instance, NULL); - break; - case TAB_CONTENTS_NATIVE_UI: - contents = new NativeUIContents(profile); - break; - case TAB_CONTENTS_ABOUT_INTERNETS_STATUS_VIEW: - contents = new AboutInternetsStatusView(); - break; - case TAB_CONTENTS_VIEW_SOURCE: - contents = new ViewSourceContents(profile, instance); - break; - case TAB_CONTENTS_ABOUT_UI: - contents = new BrowserAboutHandler(profile, instance, NULL); - break; - case TAB_CONTENTS_DEBUGGER: - contents = new DebuggerContents(profile, instance); - break; - case TAB_CONTENTS_DOM_UI: - contents = new DOMUIContents(profile, instance, NULL); - break; - default: - if (g_extra_types) { - TabContentsFactoryMap::const_iterator it = g_extra_types->find(type); - if (it != g_extra_types->end()) { - contents = it->second->CreateInstance(); - break; - } - } - NOTREACHED() << "Don't know how to create tab contents of type " << type; - contents = NULL; - } - - if (contents) - contents->CreateView(); - - return contents; -} - -/*static*/ -TabContentsType TabContents::TypeForURL(GURL* url) { - DCHECK(url); - if (g_extra_types) { - TabContentsFactoryMap::const_iterator it = g_extra_types->begin(); - for (; it != g_extra_types->end(); ++it) { - if (it->second->CanHandleURL(*url)) - return it->first; - } - } - - // Try to handle as a browser URL. If successful, |url| will end up - // containing the real url being loaded (browser url's are just an alias). - TabContentsType type(TAB_CONTENTS_UNKNOWN_TYPE); - if (BrowserURLHandler::HandleBrowserURL(url, &type)) - return type; - - if (url->SchemeIs(NativeUIContents::GetScheme().c_str())) - return TAB_CONTENTS_NATIVE_UI; - - if (HtmlDialogContents::IsHtmlDialogUrl(*url)) - return TAB_CONTENTS_HTML_DIALOG; - - if (DebuggerContents::IsDebuggerUrl(*url)) - return TAB_CONTENTS_DEBUGGER; - - if (url->SchemeIs(DOMUIContents::GetScheme().c_str())) - return TAB_CONTENTS_DOM_UI; - - if (url->SchemeIs("view-source")) { - // Load the inner URL instead, but render it using a ViewSourceContents. - *url = GURL(url->path()); - return TAB_CONTENTS_VIEW_SOURCE; - } - - // NOTE: Even the empty string can be loaded by a WebContents. - return TAB_CONTENTS_WEB; -} - -/*static*/ -TabContentsFactory* TabContents::RegisterFactory(TabContentsType type, - TabContentsFactory* factory) { - if (!g_extra_types) - g_extra_types = new TabContentsFactoryMap; - - TabContentsFactory* prev_factory = NULL; - TabContentsFactoryMap::const_iterator prev = g_extra_types->find(type); - if (prev != g_extra_types->end()) - prev_factory = prev->second; - - if (factory) { - g_extra_types->insert(TabContentsFactoryMap::value_type(type, factory)); - } else { - g_extra_types->erase(type); - if (g_extra_types->empty()) { - delete g_extra_types; - g_extra_types = NULL; - } - } - - return prev_factory; -} - diff --git a/chrome/browser/tab_contents_factory.h b/chrome/browser/tab_contents_factory.h deleted file mode 100644 index 86c15ea..0000000 --- a/chrome/browser/tab_contents_factory.h +++ /dev/null @@ -1,28 +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. - -#ifndef CHROME_BROWSER_TAB_CONTENTS_FACTORY_H_ -#define CHROME_BROWSER_TAB_CONTENTS_FACTORY_H_ - -#include -#include "chrome/browser/tab_contents_type.h" - -class TabContents; - -// Extend from this class to implement a custom tab contents type. See -// TabContents::RegisterFactory. -class TabContentsFactory { - public: - // Returns the next unused TabContentsType after TAB_CONTENTS_NUM_TYPES. - static TabContentsType NextUnusedType(); - - // Returns a new TabContents instance of the associated type. - virtual TabContents* CreateInstance() = 0; - - // Returns true if this factory can be used to create a TabContents instance - // capable of handling the given URL. NOTE: the given url can be empty. - virtual bool CanHandleURL(const GURL& url) = 0; -}; - -#endif // CHROME_BROWSER_TAB_CONTENTS_FACTORY_H_ \ No newline at end of file diff --git a/chrome/browser/tab_contents_type.h b/chrome/browser/tab_contents_type.h deleted file mode 100644 index 86f38cc..0000000 --- a/chrome/browser/tab_contents_type.h +++ /dev/null @@ -1,31 +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. - -#ifndef CHROME_BROWSER_TAB_CONTENTS_TYPE_H__ -#define CHROME_BROWSER_TAB_CONTENTS_TYPE_H__ - -// The different kinds of tab contents we support. This is declared outside of -// TabContents to eliminate the circular dependency between NavigationEntry -// (which requires a tab type) and TabContents (which requires a -// NavigationEntry). -enum TabContentsType { - TAB_CONTENTS_UNKNOWN_TYPE = 0, - TAB_CONTENTS_WEB, - TAB_CONTENTS_DOWNLOAD_VIEW, - TAB_CONTENTS_NETWORK_STATUS_VIEW, - TAB_CONTENTS_IPC_STATUS_VIEW, - TAB_CONTENTS_CHROME_VIEW_CONTENTS, - TAB_CONTENTS_NEW_TAB_UI, - TAB_CONTENTS_NATIVE_UI, - TAB_CONTENTS_ABOUT_INTERNETS_STATUS_VIEW, - TAB_CONTENTS_VIEW_SOURCE, - TAB_CONTENTS_HTML_DIALOG, - TAB_CONTENTS_ABOUT_UI, - TAB_CONTENTS_DEBUGGER, - TAB_CONTENTS_DOM_UI, - TAB_CONTENTS_NUM_TYPES -}; - -#endif // CHROME_BROWSER_TAB_CONTENTS_TYPE_H__ - diff --git a/chrome/browser/tab_util.cc b/chrome/browser/tab_util.cc deleted file mode 100644 index ecb7c84..0000000 --- a/chrome/browser/tab_util.cc +++ /dev/null @@ -1,39 +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_util.h" - -#include "chrome/browser/render_view_host.h" -#include "chrome/browser/render_process_host.h" -#include "chrome/browser/renderer_host/resource_dispatcher_host.h" -#include "chrome/browser/web_contents.h" -#include "net/url_request/url_request.h" - -bool tab_util::GetTabContentsID(URLRequest* request, - int* render_process_id, - int* render_view_id) { - - if (!request || !render_process_id || !render_view_id) - return false; - - ResourceDispatcherHost::ExtraRequestInfo* info = - ResourceDispatcherHost::ExtraInfoForRequest(request); - if (!info) - return false; - - *render_process_id = info->render_process_host_id; - *render_view_id = info->render_view_id; - return true; -} - -WebContents* tab_util::GetWebContentsByID(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 static_cast(render_view_host->delegate()); -} - diff --git a/chrome/browser/tab_util.h b/chrome/browser/tab_util.h deleted file mode 100644 index 6aa96f3..0000000 --- a/chrome/browser/tab_util.h +++ /dev/null @@ -1,26 +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. - -#ifndef CHROME_BROWSER_TAB_UTIL_H__ -#define CHROME_BROWSER_TAB_UTIL_H__ - -class URLRequest; -class WebContents; - -namespace tab_util { - -// Helper to get the IDs necessary for looking up a TabContents. -// Should only be called from the IO thread, since it accesses an URLRequest. -bool GetTabContentsID(URLRequest* request, int* render_process_host_id, - int* routing_id); - -// Helper to find the WebContents that originated the given request. Can be -// NULL if the tab has been closed or some other error occurs. -// Should only be called from the UI thread, since it accesses TabContent. -WebContents* GetWebContentsByID(int render_process_host_id, int routing_id); - -} // namespace tab_util - -#endif // CHROME_BROWSER_TAB_UTIL_H__ - diff --git a/chrome/browser/tabs/tab_strip_model.cc b/chrome/browser/tabs/tab_strip_model.cc index 3658ef5..2e42a64 100644 --- a/chrome/browser/tabs/tab_strip_model.cc +++ b/chrome/browser/tabs/tab_strip_model.cc @@ -10,11 +10,11 @@ #include "chrome/browser/browser_about_handler.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/profile.h" -#include "chrome/browser/navigation_controller.h" -#include "chrome/browser/navigation_entry.h" #include "chrome/browser/render_view_host.h" #include "chrome/browser/sessions/tab_restore_service.h" -#include "chrome/browser/tab_contents_factory.h" +#include "chrome/browser/tab_contents/navigation_controller.h" +#include "chrome/browser/tab_contents/navigation_entry.h" +#include "chrome/browser/tab_contents/tab_contents_factory.h" #include "chrome/browser/tabs/tab_strip_model.h" #include "chrome/browser/tabs/tab_strip_model_order_controller.h" #include "chrome/browser/user_metrics.h" diff --git a/chrome/browser/tabs/tab_strip_model.h b/chrome/browser/tabs/tab_strip_model.h index d5d56f2..0e5ceea 100644 --- a/chrome/browser/tabs/tab_strip_model.h +++ b/chrome/browser/tabs/tab_strip_model.h @@ -10,7 +10,7 @@ #include "base/basictypes.h" #include "base/observer_list.h" #include "chrome/browser/history/history.h" -#include "chrome/browser/site_instance.h" +#include "chrome/browser/tab_contents/site_instance.h" #include "chrome/common/notification_service.h" #include "chrome/common/page_transition_types.h" #include "chrome/common/pref_member.h" diff --git a/chrome/browser/tabs/tab_strip_model_order_controller.cc b/chrome/browser/tabs/tab_strip_model_order_controller.cc index 4259fd2..1a1d416 100644 --- a/chrome/browser/tabs/tab_strip_model_order_controller.cc +++ b/chrome/browser/tabs/tab_strip_model_order_controller.cc @@ -4,7 +4,7 @@ #include "chrome/browser/tabs/tab_strip_model_order_controller.h" -#include "chrome/browser/tab_contents.h" +#include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/browser/tabs/tab_strip_model.h" #include "chrome/common/pref_names.h" diff --git a/chrome/browser/tabs/tab_strip_model_unittest.cc b/chrome/browser/tabs/tab_strip_model_unittest.cc index 071975f..21ea248 100644 --- a/chrome/browser/tabs/tab_strip_model_unittest.cc +++ b/chrome/browser/tabs/tab_strip_model_unittest.cc @@ -6,14 +6,14 @@ #include "base/path_service.h" #include "chrome/browser/dock_info.h" #include "chrome/browser/dom_ui/new_tab_ui.h" -#include "chrome/browser/navigation_controller.h" -#include "chrome/browser/navigation_entry.h" #include "chrome/browser/profile.h" #include "chrome/browser/profile_manager.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_factory.h" #include "chrome/browser/tabs/tab_strip_model.h" #include "chrome/browser/tabs/tab_strip_model_order_controller.h" -#include "chrome/browser/tab_contents.h" -#include "chrome/browser/tab_contents_factory.h" #include "chrome/common/pref_names.h" #include "chrome/common/stl_util-inl.h" #include "testing/gtest/include/gtest/gtest.h" diff --git a/chrome/browser/task_manager.cc b/chrome/browser/task_manager.cc index 423a55f..31c28ca 100644 --- a/chrome/browser/task_manager.cc +++ b/chrome/browser/task_manager.cc @@ -12,7 +12,7 @@ #include "chrome/browser/browser_process.h" #include "chrome/browser/render_process_host.h" #include "chrome/browser/task_manager_resource_providers.h" -#include "chrome/browser/tab_util.h" +#include "chrome/browser/tab_contents/tab_util.h" #include "chrome/browser/views/standard_layout.h" #include "chrome/common/l10n_util.h" #include "chrome/common/pref_names.h" diff --git a/chrome/browser/task_manager.h b/chrome/browser/task_manager.h index 3c872fb..90111fc 100644 --- a/chrome/browser/task_manager.h +++ b/chrome/browser/task_manager.h @@ -16,7 +16,7 @@ #include "chrome/views/dialog_delegate.h" #include "chrome/views/group_table_view.h" #include "chrome/browser/cache_manager_host.h" -#include "chrome/browser/tab_contents.h" +#include "chrome/browser/tab_contents/tab_contents.h" #include "net/url_request/url_request_job_tracker.h" class MessageLoop; diff --git a/chrome/browser/task_manager_resource_providers.cc b/chrome/browser/task_manager_resource_providers.cc index 7167957..be0ed1f 100644 --- a/chrome/browser/task_manager_resource_providers.cc +++ b/chrome/browser/task_manager_resource_providers.cc @@ -16,8 +16,8 @@ #include "chrome/browser/plugin_service.h" #include "chrome/browser/render_process_host.h" #include "chrome/browser/resource_message_filter.h" -#include "chrome/browser/tab_util.h" -#include "chrome/browser/web_contents.h" +#include "chrome/browser/tab_contents/tab_util.h" +#include "chrome/browser/tab_contents/web_contents.h" #include "chrome/common/resource_bundle.h" #include "chrome/common/stl_util-inl.h" #include "chrome/common/gfx/icon_util.h" diff --git a/chrome/browser/toolbar_model.cc b/chrome/browser/toolbar_model.cc index e2cf9a5..ba40deb 100644 --- a/chrome/browser/toolbar_model.cc +++ b/chrome/browser/toolbar_model.cc @@ -5,10 +5,10 @@ #include "chrome/browser/toolbar_model.h" #include "chrome/browser/cert_store.h" -#include "chrome/browser/navigation_controller.h" -#include "chrome/browser/navigation_entry.h" #include "chrome/browser/ssl_error_info.h" -#include "chrome/browser/tab_contents.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/common/gfx/text_elider.h" #include "chrome/common/l10n_util.h" #include "chrome/common/pref_names.h" diff --git a/chrome/browser/view_source_contents.cc b/chrome/browser/view_source_contents.cc deleted file mode 100644 index 6ba3fc7..0000000 --- a/chrome/browser/view_source_contents.cc +++ /dev/null @@ -1,19 +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/view_source_contents.h" - -#include "chrome/browser/navigation_entry.h" -#include "chrome/browser/render_view_host.h" - -ViewSourceContents::ViewSourceContents(Profile* profile, SiteInstance* instance) - : WebContents(profile, instance, NULL, MSG_ROUTING_NONE, NULL) { - set_type(TAB_CONTENTS_VIEW_SOURCE); -} - -void ViewSourceContents::RendererCreated(RenderViewHost* host) { - // Make sure the renderer is in view source mode. - host->Send(new ViewMsg_EnableViewSourceMode(host->routing_id())); -} - diff --git a/chrome/browser/view_source_contents.h b/chrome/browser/view_source_contents.h deleted file mode 100644 index c10975a..0000000 --- a/chrome/browser/view_source_contents.h +++ /dev/null @@ -1,27 +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. - -#ifndef CHROME_BROWSER_VIEW_SOURCE_CONTENTS_H__ -#define CHROME_BROWSER_VIEW_SOURCE_CONTENTS_H__ - -#include "chrome/browser/web_contents.h" - -// We use this class to implement view-source: URLs. -class ViewSourceContents : public WebContents { - public: - ViewSourceContents(Profile* profile, SiteInstance* instance); - - protected: - // RenderViewHostDelegate overrides: - virtual void RendererCreated(RenderViewHost* host); - - // WebContents overrides: - // We override updating history with a no-op so these pages - // are not saved to history. - virtual void UpdateHistoryForNavigation(const GURL& url, - const ViewHostMsg_FrameNavigate_Params& params) { } -}; - -#endif // CHROME_BROWSER_VIEW_SOURCE_CONTENTS_H__ - diff --git a/chrome/browser/view_source_uitest.cc b/chrome/browser/view_source_uitest.cc deleted file mode 100644 index 73cc875..0000000 --- a/chrome/browser/view_source_uitest.cc +++ /dev/null @@ -1,110 +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/app/chrome_dll_resource.h" -#include "chrome/test/automation/browser_proxy.h" -#include "chrome/test/automation/tab_proxy.h" -#include "chrome/test/ui/ui_test.h" -#include "net/url_request/url_request_unittest.h" - -namespace { - -const wchar_t kDocRoot[] = L"chrome/test/data"; - -class ViewSourceTest : public UITest { - protected: - ViewSourceTest() : UITest() { - test_html_ = L"files/viewsource/test.html"; - } - - bool IsPageMenuCommandEnabled(int command) { - scoped_ptr window_proxy(automation()->GetBrowserWindow(0)); - if (!window_proxy.get()) - return false; - - bool timed_out; - return window_proxy->IsPageMenuCommandEnabledWithTimeout( - command, 5000, &timed_out) && !timed_out; - } - - protected: - std::wstring test_html_; -}; - -} // namespace - -// This test renders a page in view-source and then checks to see if a cookie -// set in the html was set successfully (it shouldn't because we rendered the -// page in view source) -TEST_F(ViewSourceTest, DoesBrowserRenderInViewSource) { - scoped_refptr server = - HTTPTestServer::CreateServer(kDocRoot); - ASSERT_TRUE(NULL != server.get()); - std::string cookie = "viewsource_cookie"; - std::string cookie_data = "foo"; - - // First we navigate to our view-source test page - GURL url = server->TestServerPageW(test_html_); - url = GURL("view-source:" + url.spec()); - scoped_ptr tab(GetActiveTab()); - tab->NavigateToURL(url); - Sleep(kWaitForActionMsec); - - // Try to retrieve the cookie that the page sets - // It should not be there (because we are in view-source mode - std::string cookie_found; - tab->GetCookieByName(url, cookie, &cookie_found); - EXPECT_NE(cookie_data, cookie_found); -} - -// This test renders a page normally and then renders the same page in -// view-source mode. This is done since we had a problem at one point during -// implementation of the view-source: prefix being consumed (removed from the -// URL) if the URL was not changed (apart from adding the view-source prefix) -TEST_F(ViewSourceTest, DoesBrowserConsumeViewSourcePrefix) { - scoped_refptr server = - HTTPTestServer::CreateServer(kDocRoot); - ASSERT_TRUE(NULL != server.get()); - - // First we navigate to google.html - GURL url = server->TestServerPageW(test_html_); - NavigateToURL(url); - - // Then we navigate to the SAME url but with the view-source: prefix - GURL url_viewsource = GURL("view-source:" + url.spec()); - NavigateToURL(url_viewsource); - - // The URL should still be prefixed with view-source: - EXPECT_EQ(url_viewsource.spec(), GetActiveTabURL().spec()); -} - -// Make sure that when looking at the actual page, we can select -// "View Source" from the Page menu. -TEST_F(ViewSourceTest, ViewSourceInPageMenuEnabledOnANormalPage) { - scoped_refptr server = - HTTPTestServer::CreateServer(kDocRoot); - ASSERT_TRUE(NULL != server.get()); - - // First we navigate to google.html - GURL url = server->TestServerPageW(test_html_); - NavigateToURL(url); - - EXPECT_TRUE(IsPageMenuCommandEnabled(IDC_VIEW_SOURCE)); -} - -// Make sure that when looking at the page source, we can't select -// "View Source" from the Page menu. -TEST_F(ViewSourceTest, ViewSourceInPageMenuDisabledWhileViewingSource) { - scoped_refptr server = - HTTPTestServer::CreateServer(kDocRoot); - ASSERT_TRUE(NULL != server.get()); - - // First we navigate to google.html - GURL url = server->TestServerPageW(test_html_); - GURL url_viewsource = GURL("view-source:" + url.spec()); - NavigateToURL(url_viewsource); - - EXPECT_FALSE(IsPageMenuCommandEnabled(IDC_VIEW_SOURCE)); -} - diff --git a/chrome/browser/views/blocked_popup_container.cc b/chrome/browser/views/blocked_popup_container.cc index ef66737..0ec1dd0 100644 --- a/chrome/browser/views/blocked_popup_container.cc +++ b/chrome/browser/views/blocked_popup_container.cc @@ -14,7 +14,7 @@ #include "chrome/app/theme/theme_resources.h" #include "chrome/browser/profile.h" -#include "chrome/browser/tab_contents.h" +#include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/common/gfx/chrome_canvas.h" #include "chrome/common/gfx/path.h" #include "chrome/common/l10n_util.h" diff --git a/chrome/browser/views/blocked_popup_container.h b/chrome/browser/views/blocked_popup_container.h index 6da3e4f..3b012a8 100644 --- a/chrome/browser/views/blocked_popup_container.h +++ b/chrome/browser/views/blocked_popup_container.h @@ -14,8 +14,8 @@ #include #include "base/gfx/rect.h" -#include "chrome/browser/constrained_window.h" -#include "chrome/browser/tab_contents_delegate.h" +#include "chrome/browser/tab_contents/constrained_window.h" +#include "chrome/browser/tab_contents/tab_contents_delegate.h" #include "chrome/common/animation.h" #include "chrome/common/pref_member.h" #include "chrome/views/base_button.h" diff --git a/chrome/browser/views/bookmark_bar_view.cc b/chrome/browser/views/bookmark_bar_view.cc index e1327ac..0c32f22 100644 --- a/chrome/browser/views/bookmark_bar_view.cc +++ b/chrome/browser/views/bookmark_bar_view.cc @@ -17,9 +17,9 @@ #include "chrome/browser/drag_utils.h" #include "chrome/browser/download/download_util.h" #include "chrome/browser/history/history.h" -#include "chrome/browser/page_navigator.h" #include "chrome/browser/profile.h" -#include "chrome/browser/tab_contents.h" +#include "chrome/browser/tab_contents/page_navigator.h" +#include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/browser/user_metrics.h" #include "chrome/browser/view_ids.h" #include "chrome/browser/views/bookmark_editor_view.h" diff --git a/chrome/browser/views/bookmark_bar_view_test.cc b/chrome/browser/views/bookmark_bar_view_test.cc index 1e6a0b8..5a9b5dd 100644 --- a/chrome/browser/views/bookmark_bar_view_test.cc +++ b/chrome/browser/views/bookmark_bar_view_test.cc @@ -6,8 +6,8 @@ #include "chrome/browser/automation/ui_controls.h" #include "chrome/browser/bookmarks/bookmark_model.h" #include "chrome/browser/bookmarks/bookmark_utils.h" -#include "chrome/browser/page_navigator.h" #include "chrome/browser/profile.h" +#include "chrome/browser/tab_contents/page_navigator.h" #include "chrome/browser/views/bookmark_bar_view.h" #include "chrome/common/pref_names.h" #include "chrome/common/pref_service.h" diff --git a/chrome/browser/views/bug_report_view.cc b/chrome/browser/views/bug_report_view.cc index 58d70aa..cf0a74e 100644 --- a/chrome/browser/views/bug_report_view.cc +++ b/chrome/browser/views/bug_report_view.cc @@ -9,11 +9,11 @@ #include "base/string_util.h" #include "chrome/app/locales/locale_settings.h" -#include "chrome/browser/navigation_controller.h" -#include "chrome/browser/navigation_entry.h" #include "chrome/browser/profile.h" #include "chrome/browser/safe_browsing/safe_browsing_util.h" -#include "chrome/browser/tab_contents.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/url_fetcher.h" #include "chrome/browser/views/standard_layout.h" #include "chrome/common/l10n_util.h" diff --git a/chrome/browser/views/constrained_window_impl.cc b/chrome/browser/views/constrained_window_impl.cc index ec0b9d2..7f5eafe 100644 --- a/chrome/browser/views/constrained_window_impl.cc +++ b/chrome/browser/views/constrained_window_impl.cc @@ -7,13 +7,13 @@ #include "base/gfx/rect.h" #include "chrome/app/chrome_dll_resource.h" #include "chrome/app/theme/theme_resources.h" -#include "chrome/browser/tab_contents.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/profile.h" +#include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/tab_contents/web_contents.h" +#include "chrome/browser/tab_contents/web_contents_view.h" #include "chrome/browser/toolbar_model.h" #include "chrome/browser/web_app.h" -#include "chrome/browser/web_contents.h" -#include "chrome/browser/web_contents_view.h" #include "chrome/browser/window_sizer.h" #include "chrome/common/chrome_constants.h" #include "chrome/common/gfx/chrome_canvas.h" diff --git a/chrome/browser/views/constrained_window_impl.h b/chrome/browser/views/constrained_window_impl.h index 836b2a9..229555e 100644 --- a/chrome/browser/views/constrained_window_impl.h +++ b/chrome/browser/views/constrained_window_impl.h @@ -6,8 +6,8 @@ #define CHROME_BROWSER_CONSTRAINED_WINDOW_IMPL_H_ #include "base/gfx/rect.h" -#include "chrome/browser/constrained_window.h" -#include "chrome/browser/tab_contents_delegate.h" +#include "chrome/browser/tab_contents/constrained_window.h" +#include "chrome/browser/tab_contents/tab_contents_delegate.h" #include "chrome/views/custom_frame_window.h" class ConstrainedTabContentsWindowDelegate; diff --git a/chrome/browser/views/download_shelf_view.cc b/chrome/browser/views/download_shelf_view.cc index f21ef01..5467be7 100644 --- a/chrome/browser/views/download_shelf_view.cc +++ b/chrome/browser/views/download_shelf_view.cc @@ -10,8 +10,8 @@ #include "chrome/browser/browser.h" #include "chrome/browser/download/download_item_model.h" #include "chrome/browser/download/download_manager.h" -#include "chrome/browser/navigation_entry.h" -#include "chrome/browser/tab_contents.h" +#include "chrome/browser/tab_contents/navigation_entry.h" +#include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/browser/views/download_item_view.h" #include "chrome/browser/views/download_tab_view.h" #include "chrome/common/gfx/chrome_canvas.h" diff --git a/chrome/browser/views/download_started_animation.cc b/chrome/browser/views/download_started_animation.cc index 001208d..b08b1c3 100644 --- a/chrome/browser/views/download_started_animation.cc +++ b/chrome/browser/views/download_started_animation.cc @@ -5,7 +5,7 @@ #include "chrome/browser/views/download_started_animation.h" #include "chrome/app/theme/theme_resources.h" -#include "chrome/browser/tab_contents.h" +#include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/common/resource_bundle.h" #include "chrome/views/widget_win.h" diff --git a/chrome/browser/views/download_tab_view.h b/chrome/browser/views/download_tab_view.h index 932f5c1..db6861f 100644 --- a/chrome/browser/views/download_tab_view.h +++ b/chrome/browser/views/download_tab_view.h @@ -10,7 +10,7 @@ #include "chrome/browser/download/download_manager.h" #include "chrome/browser/download/download_util.h" #include "chrome/browser/icon_manager.h" -#include "chrome/browser/native_ui_contents.h" +#include "chrome/browser/tab_contents/native_ui_contents.h" #include "chrome/views/event.h" #include "chrome/views/label.h" #include "chrome/views/link.h" diff --git a/chrome/browser/views/external_protocol_dialog.cc b/chrome/browser/views/external_protocol_dialog.cc index f4aafcb..594dfbb 100644 --- a/chrome/browser/views/external_protocol_dialog.cc +++ b/chrome/browser/views/external_protocol_dialog.cc @@ -9,8 +9,8 @@ #include "base/thread.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/external_protocol_handler.h" -#include "chrome/browser/tab_util.h" -#include "chrome/browser/web_contents.h" +#include "chrome/browser/tab_contents/tab_util.h" +#include "chrome/browser/tab_contents/web_contents.h" #include "chrome/common/l10n_util.h" #include "chrome/views/message_box_view.h" #include "chrome/views/window.h" diff --git a/chrome/browser/views/find_bar_win.cc b/chrome/browser/views/find_bar_win.cc index 0510762..867f341 100644 --- a/chrome/browser/views/find_bar_win.cc +++ b/chrome/browser/views/find_bar_win.cc @@ -11,8 +11,8 @@ #include "chrome/browser/view_ids.h" #include "chrome/browser/views/bookmark_bar_view.h" #include "chrome/browser/views/find_bar_view.h" -#include "chrome/browser/web_contents.h" -#include "chrome/browser/web_contents_view.h" +#include "chrome/browser/tab_contents/web_contents.h" +#include "chrome/browser/tab_contents/web_contents_view.h" #include "chrome/views/external_focus_tracker.h" #include "chrome/views/native_scroll_bar.h" #include "chrome/views/root_view.h" diff --git a/chrome/browser/views/frame/browser_view.cc b/chrome/browser/views/frame/browser_view.cc index 18823fd..ce04f73 100644 --- a/chrome/browser/views/frame/browser_view.cc +++ b/chrome/browser/views/frame/browser_view.cc @@ -14,7 +14,6 @@ #include "chrome/browser/browser.h" #include "chrome/browser/browser_list.h" #include "chrome/browser/encoding_menu_controller_delegate.h" -#include "chrome/browser/navigation_entry.h" #include "chrome/browser/view_ids.h" #include "chrome/browser/views/about_chrome_view.h" #include "chrome/browser/views/bookmark_bar_view.h" @@ -32,8 +31,9 @@ #include "chrome/browser/views/tab_contents_container_view.h" #include "chrome/browser/views/tabs/tab_strip.h" #include "chrome/browser/views/toolbar_view.h" -#include "chrome/browser/web_contents.h" -#include "chrome/browser/web_contents_view.h" +#include "chrome/browser/tab_contents/navigation_entry.h" +#include "chrome/browser/tab_contents/web_contents.h" +#include "chrome/browser/tab_contents/web_contents_view.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/drag_drop_types.h" #include "chrome/common/l10n_util.h" diff --git a/chrome/browser/views/frame/opaque_non_client_view.cc b/chrome/browser/views/frame/opaque_non_client_view.cc index 5324b4b..b0584d4 100644 --- a/chrome/browser/views/frame/opaque_non_client_view.cc +++ b/chrome/browser/views/frame/opaque_non_client_view.cc @@ -5,7 +5,7 @@ #include "chrome/browser/views/frame/opaque_non_client_view.h" #include "chrome/app/theme/theme_resources.h" -#include "chrome/browser/tab_contents.h" +#include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/browser/views/frame/browser_view.h" #include "chrome/browser/views/tabs/tab_strip.h" #include "chrome/common/gfx/chrome_font.h" diff --git a/chrome/browser/views/html_dialog_view.h b/chrome/browser/views/html_dialog_view.h index 3b8b28c..224f882 100644 --- a/chrome/browser/views/html_dialog_view.h +++ b/chrome/browser/views/html_dialog_view.h @@ -8,7 +8,7 @@ #include #include "chrome/browser/dom_ui/html_dialog_contents.h" -#include "chrome/browser/tab_contents_delegate.h" +#include "chrome/browser/tab_contents/tab_contents_delegate.h" #include "chrome/browser/views/dom_view.h" class Browser; diff --git a/chrome/browser/views/hung_renderer_view.cc b/chrome/browser/views/hung_renderer_view.cc index 4365b3e..9c55a1b 100644 --- a/chrome/browser/views/hung_renderer_view.cc +++ b/chrome/browser/views/hung_renderer_view.cc @@ -9,7 +9,7 @@ #include "chrome/browser/browser_list.h" #include "chrome/browser/render_view_host.h" #include "chrome/browser/views/standard_layout.h" -#include "chrome/browser/web_contents.h" +#include "chrome/browser/tab_contents/web_contents.h" #include "chrome/common/chrome_constants.h" #include "chrome/common/gfx/chrome_canvas.h" #include "chrome/common/gfx/path.h" diff --git a/chrome/browser/views/hwnd_html_view.cc b/chrome/browser/views/hwnd_html_view.cc index 41fc7c6..c418c1e 100644 --- a/chrome/browser/views/hwnd_html_view.cc +++ b/chrome/browser/views/hwnd_html_view.cc @@ -7,7 +7,7 @@ #include "chrome/browser/render_view_host.h" #include "chrome/browser/render_widget_host_view_win.h" #include "chrome/browser/render_view_host_delegate.h" -#include "chrome/browser/site_instance.h" +#include "chrome/browser/tab_contents/site_instance.h" #include "chrome/views/widget.h" HWNDHtmlView::~HWNDHtmlView() { diff --git a/chrome/browser/views/infobars/infobar_container.cc b/chrome/browser/views/infobars/infobar_container.cc index 3a79464..d3d007f 100644 --- a/chrome/browser/views/infobars/infobar_container.cc +++ b/chrome/browser/views/infobars/infobar_container.cc @@ -4,8 +4,8 @@ #include "chrome/browser/views/infobars/infobar_container.h" -#include "chrome/browser/infobar_delegate.h" -#include "chrome/browser/tab_contents.h" +#include "chrome/browser/tab_contents/infobar_delegate.h" +#include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/browser/views/frame/browser_view.h" #include "chrome/browser/views/infobars/infobars.h" #include "chrome/common/notification_types.h" diff --git a/chrome/browser/views/infobars/infobars.h b/chrome/browser/views/infobars/infobars.h index e0ae487..56f140b 100644 --- a/chrome/browser/views/infobars/infobars.h +++ b/chrome/browser/views/infobars/infobars.h @@ -5,7 +5,7 @@ #ifndef CHROME_BROWSER_VIEWS_INFOBARS_INFOBARS_H_ #define CHROME_BROWSER_VIEWS_INFOBARS_INFOBARS_H_ -#include "chrome/browser/infobar_delegate.h" +#include "chrome/browser/tab_contents/infobar_delegate.h" #include "chrome/views/base_button.h" #include "chrome/views/link.h" #include "chrome/views/native_button.h" @@ -20,8 +20,8 @@ class Label; } // This file contains implementations for some general purpose InfoBars. See -// chrome/browser/infobar_delegate.h for the delegate interface(s) that you must -// implement to use these. +// chrome/browser/tab_contents/infobar_delegate.h for the delegate interface(s) +// that you must implement to use these. class InfoBar : public views::View, public views::BaseButton::ButtonListener, diff --git a/chrome/browser/views/location_bar_view.cc b/chrome/browser/views/location_bar_view.cc index 9bc23db..cad8583 100644 --- a/chrome/browser/views/location_bar_view.cc +++ b/chrome/browser/views/location_bar_view.cc @@ -12,8 +12,8 @@ #include "chrome/browser/browser.h" #include "chrome/browser/browser_list.h" #include "chrome/browser/browser_process.h" -#include "chrome/browser/navigation_entry.h" #include "chrome/browser/profile.h" +#include "chrome/browser/tab_contents/navigation_entry.h" #include "chrome/browser/template_url.h" #include "chrome/browser/template_url_model.h" #include "chrome/browser/view_ids.h" diff --git a/chrome/browser/views/location_bar_view.h b/chrome/browser/views/location_bar_view.h index 054c79b..ad99fb5 100644 --- a/chrome/browser/views/location_bar_view.h +++ b/chrome/browser/views/location_bar_view.h @@ -10,7 +10,7 @@ #include "base/gfx/rect.h" #include "chrome/browser/autocomplete/autocomplete_edit.h" #include "chrome/browser/controller.h" -#include "chrome/browser/tab_contents.h" +#include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/browser/toolbar_model.h" #include "chrome/browser/views/info_bubble.h" #include "chrome/common/gfx/chrome_font.h" diff --git a/chrome/browser/views/page_info_window.h b/chrome/browser/views/page_info_window.h index 6df7c09..1d3bbac 100644 --- a/chrome/browser/views/page_info_window.h +++ b/chrome/browser/views/page_info_window.h @@ -5,7 +5,7 @@ #ifndef CHROME_BROWSER_VIEWS_PAGE_INFO_WINDOW_H__ #define CHROME_BROWSER_VIEWS_PAGE_INFO_WINDOW_H__ -#include "chrome/browser/navigation_entry.h" +#include "chrome/browser/tab_contents/navigation_entry.h" #include "chrome/views/dialog_delegate.h" #include "chrome/views/native_button.h" #include "chrome/views/window.h" diff --git a/chrome/browser/views/shelf_item_dialog.cc b/chrome/browser/views/shelf_item_dialog.cc index fed7d5c..377eca2 100644 --- a/chrome/browser/views/shelf_item_dialog.cc +++ b/chrome/browser/views/shelf_item_dialog.cc @@ -9,7 +9,7 @@ #include "chrome/app/locales/locale_settings.h" #include "chrome/app/theme/theme_resources.h" #include "chrome/browser/profile.h" -#include "chrome/browser/tab_contents.h" +#include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/browser/url_fixer_upper.h" #include "chrome/browser/views/standard_layout.h" #include "chrome/common/gfx/text_elider.h" diff --git a/chrome/browser/views/tab_contents_container_view.cc b/chrome/browser/views/tab_contents_container_view.cc index 27e664e..01f449b 100644 --- a/chrome/browser/views/tab_contents_container_view.cc +++ b/chrome/browser/views/tab_contents_container_view.cc @@ -10,9 +10,9 @@ #include "chrome/browser/render_view_host.h" #include "chrome/browser/render_view_host_manager.h" #include "chrome/browser/render_widget_host_view.h" -#include "chrome/browser/tab_contents.h" +#include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/tab_contents/web_contents.h" #include "chrome/browser/view_ids.h" -#include "chrome/browser/web_contents.h" #include "chrome/views/root_view.h" #include "chrome/views/widget.h" diff --git a/chrome/browser/views/tab_icon_view.cc b/chrome/browser/views/tab_icon_view.cc index 46595f6..b9af037 100644 --- a/chrome/browser/views/tab_icon_view.cc +++ b/chrome/browser/views/tab_icon_view.cc @@ -14,7 +14,7 @@ #include "chrome/common/gfx/favicon_size.h" #include "chrome/common/gfx/icon_util.h" #include "chrome/common/resource_bundle.h" -#include "chrome/browser/tab_contents.h" +#include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/app/chrome_dll_resource.h" static bool g_initialized = false; diff --git a/chrome/browser/views/tabs/dragged_tab_controller.cc b/chrome/browser/views/tabs/dragged_tab_controller.cc index f0b6d4a..57efb2d 100644 --- a/chrome/browser/views/tabs/dragged_tab_controller.cc +++ b/chrome/browser/views/tabs/dragged_tab_controller.cc @@ -8,14 +8,14 @@ #include "chrome/browser/views/tabs/dragged_tab_controller.h" #include "chrome/browser/browser_window.h" -#include "chrome/browser/tab_contents.h" +#include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/browser/user_metrics.h" #include "chrome/browser/views/frame/browser_view.h" #include "chrome/browser/views/tabs/dragged_tab_view.h" #include "chrome/browser/views/tabs/hwnd_photobooth.h" #include "chrome/browser/views/tabs/tab.h" #include "chrome/browser/views/tabs/tab_strip.h" -#include "chrome/browser/web_contents.h" +#include "chrome/browser/tab_contents/web_contents.h" #include "chrome/common/animation.h" #include "chrome/views/event.h" #include "chrome/views/root_view.h" diff --git a/chrome/browser/views/tabs/dragged_tab_controller.h b/chrome/browser/views/tabs/dragged_tab_controller.h index a509aff..5c9730a 100644 --- a/chrome/browser/views/tabs/dragged_tab_controller.h +++ b/chrome/browser/views/tabs/dragged_tab_controller.h @@ -9,7 +9,7 @@ #include "base/message_loop.h" #include "base/timer.h" #include "chrome/browser/dock_info.h" -#include "chrome/browser/tab_contents_delegate.h" +#include "chrome/browser/tab_contents/tab_contents_delegate.h" #include "chrome/browser/tabs/tab_strip_model.h" #include "chrome/browser/views/tabs/tab_renderer.h" #include "chrome/common/notification_service.h" diff --git a/chrome/browser/views/tabs/dragged_tab_view.cc b/chrome/browser/views/tabs/dragged_tab_view.cc index 9aaeee1..3b5e218 100644 --- a/chrome/browser/views/tabs/dragged_tab_view.cc +++ b/chrome/browser/views/tabs/dragged_tab_view.cc @@ -5,7 +5,7 @@ #include "chrome/browser/views/tabs/dragged_tab_view.h" #include "chrome/common/gfx/chrome_canvas.h" -#include "chrome/browser/tab_contents.h" +#include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/browser/tabs/tab_strip_model.h" #include "chrome/browser/views/tabs/hwnd_photobooth.h" #include "chrome/browser/views/tabs/tab_renderer.h" diff --git a/chrome/browser/views/tabs/hwnd_photobooth.cc b/chrome/browser/views/tabs/hwnd_photobooth.cc index 19e130c..3cf5908 100644 --- a/chrome/browser/views/tabs/hwnd_photobooth.cc +++ b/chrome/browser/views/tabs/hwnd_photobooth.cc @@ -3,7 +3,7 @@ // found in the LICENSE file. #include "base/gfx/point.h" -#include "chrome/browser/tab_contents.h" +#include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/browser/views/tabs/hwnd_photobooth.h" #include "chrome/common/gfx/chrome_canvas.h" #include "chrome/views/widget_win.h" diff --git a/chrome/browser/views/tabs/tab_renderer.cc b/chrome/browser/views/tabs/tab_renderer.cc index 4581f6d..d0c51e7 100644 --- a/chrome/browser/views/tabs/tab_renderer.cc +++ b/chrome/browser/views/tabs/tab_renderer.cc @@ -8,8 +8,8 @@ #include "chrome/app/theme/theme_resources.h" #include "chrome/browser/browser.h" +#include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/browser/tabs/tab_strip_model.h" -#include "chrome/browser/tab_contents.h" #include "chrome/common/gfx/chrome_canvas.h" #include "chrome/common/gfx/chrome_font.h" #include "chrome/common/l10n_util.h" diff --git a/chrome/browser/views/tabs/tab_strip.cc b/chrome/browser/views/tabs/tab_strip.cc index c460100..3232ec4 100644 --- a/chrome/browser/views/tabs/tab_strip.cc +++ b/chrome/browser/views/tabs/tab_strip.cc @@ -7,13 +7,13 @@ #include "base/gfx/size.h" #include "chrome/app/theme/theme_resources.h" #include "chrome/browser/profile.h" -#include "chrome/browser/tab_contents.h" +#include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/browser/tabs/tab_strip_model.h" #include "chrome/browser/user_metrics.h" #include "chrome/browser/view_ids.h" #include "chrome/browser/views/tabs/dragged_tab_controller.h" #include "chrome/browser/views/tabs/tab.h" -#include "chrome/browser/web_contents.h" +#include "chrome/browser/tab_contents/web_contents.h" #include "chrome/common/drag_drop_types.h" #include "chrome/common/gfx/chrome_canvas.h" #include "chrome/common/gfx/path.h" diff --git a/chrome/browser/views/toolbar_view.cc b/chrome/browser/views/toolbar_view.cc index ffd423d..aa3b4e9 100644 --- a/chrome/browser/views/toolbar_view.cc +++ b/chrome/browser/views/toolbar_view.cc @@ -16,9 +16,9 @@ #include "chrome/browser/browser_process.h" #include "chrome/browser/character_encoding.h" #include "chrome/browser/drag_utils.h" -#include "chrome/browser/navigation_controller.h" -#include "chrome/browser/navigation_entry.h" #include "chrome/browser/profile.h" +#include "chrome/browser/tab_contents/navigation_controller.h" +#include "chrome/browser/tab_contents/navigation_entry.h" #include "chrome/browser/user_data_manager.h" #include "chrome/browser/user_metrics.h" #include "chrome/browser/views/dom_view.h" diff --git a/chrome/browser/web_app.cc b/chrome/browser/web_app.cc index 506a94f1..0d24874e 100644 --- a/chrome/browser/web_app.cc +++ b/chrome/browser/web_app.cc @@ -7,7 +7,7 @@ #include "base/gfx/png_decoder.h" #include "chrome/browser/profile.h" #include "chrome/browser/render_view_host.h" -#include "chrome/browser/web_contents.h" +#include "chrome/browser/tab_contents/web_contents.h" #include "chrome/common/gfx/favicon_size.h" #include "net/base/base64.h" #include "net/base/data_url.h" diff --git a/chrome/browser/web_app_icon_manager.cc b/chrome/browser/web_app_icon_manager.cc index e544998..3d12aed 100644 --- a/chrome/browser/web_app_icon_manager.cc +++ b/chrome/browser/web_app_icon_manager.cc @@ -6,7 +6,7 @@ #include "chrome/app/chrome_dll_resource.h" #include "chrome/app/theme/theme_resources.h" -#include "chrome/browser/web_contents.h" +#include "chrome/browser/tab_contents/web_contents.h" #include "chrome/common/gfx/icon_util.h" #include "skia/include/SkBitmap.h" diff --git a/chrome/browser/web_contents.cc b/chrome/browser/web_contents.cc deleted file mode 100644 index 90f6491..0000000 --- a/chrome/browser/web_contents.cc +++ /dev/null @@ -1,1796 +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/web_contents.h" - -#include "base/command_line.h" -#include "base/compiler_specific.h" -#include "base/file_version_info.h" -#include "base/process_util.h" -#include "chrome/app/locales/locale_settings.h" -#include "chrome/browser/autofill_manager.h" -#include "chrome/browser/bookmarks/bookmark_model.h" -#include "chrome/browser/browser.h" -#include "chrome/browser/cache_manager_host.h" -#include "chrome/browser/character_encoding.h" -#include "chrome/browser/dom_operation_notification_details.h" -#include "chrome/browser/download/download_manager.h" -#include "chrome/browser/download/download_request_manager.h" -#include "chrome/browser/find_notification_details.h" -#include "chrome/browser/google_util.h" -#include "chrome/browser/js_before_unload_handler.h" -#include "chrome/browser/jsmessage_box_handler.h" -#include "chrome/browser/load_from_memory_cache_details.h" -#include "chrome/browser/load_notification_details.h" -#include "chrome/browser/modal_html_dialog_delegate.h" -#include "chrome/browser/navigation_entry.h" -#include "chrome/browser/password_manager.h" -#include "chrome/browser/plugin_installer.h" -#include "chrome/browser/plugin_service.h" -#include "chrome/browser/printing/print_job.h" -#include "chrome/browser/render_view_host.h" -#include "chrome/browser/render_widget_host_view_win.h" // TODO(brettw) delete me. -#include "chrome/browser/template_url_fetcher.h" -#include "chrome/browser/template_url_model.h" -#include "chrome/browser/views/hung_renderer_view.h" // TODO(brettw) delete me. -#include "chrome/browser/web_contents_view.h" -#include "chrome/browser/web_contents_view_win.h" -#include "chrome/common/chrome_switches.h" -#include "chrome/common/l10n_util.h" -#include "chrome/common/pref_names.h" -#include "chrome/common/pref_service.h" -#include "chrome/common/resource_bundle.h" -#include "net/base/mime_util.h" -#include "net/base/registry_controlled_domain.h" -#include "webkit/glue/webkit_glue.h" - -#include "generated_resources.h" - -// Cross-Site Navigations -// -// If a WebContents 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 WebContents. 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 WebContents 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. - -using base::TimeDelta; -using base::TimeTicks; - -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; - -// Minimum amount of time in ms that has to elapse since the download shelf was -// shown for us to hide it when navigating away from the current page. -const int kDownloadShelfHideDelay = 5000; - -const wchar_t kLinkDoctorBaseURL[] = - L"http://linkhelp.clients.google.com/tbproxy/lh/fixurl"; - -// The printer icon in shell32.dll. That's a standard icon user will quickly -// recognize. -const int kShell32PrinterIcon = 17; - -// The list of prefs we want to observe. -const wchar_t* kPrefsToObserve[] = { - prefs::kAlternateErrorPagesEnabled, - prefs::kWebKitJavaEnabled, - prefs::kWebKitJavascriptEnabled, - prefs::kWebKitLoadsImagesAutomatically, - prefs::kWebKitPluginsEnabled, - prefs::kWebKitUsesUniversalDetector, - prefs::kWebKitSerifFontFamily, - prefs::kWebKitSansSerifFontFamily, - prefs::kWebKitFixedFontFamily, - prefs::kWebKitDefaultFontSize, - prefs::kWebKitDefaultFixedFontSize, - 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); - -// Limit on the number of suggestions to appear in the pop-up menu under an -// text input element in a form. -const int kMaxAutofillMenuItems = 6; - -void InitWebContentsClass() { - static bool web_contents_class_initialized = false; - if (!web_contents_class_initialized) { - ResourceBundle& rb = ResourceBundle::GetSharedInstance(); - web_contents_class_initialized = true; - } -} - -// Returns true if the entry's transition type is FORM_SUBMIT. -bool IsFormSubmit(const NavigationEntry* entry) { - return (PageTransition::StripQualifier(entry->transition_type()) == - PageTransition::FORM_SUBMIT); -} - -} // namespace - -class WebContents::GearsCreateShortcutCallbackFunctor { - public: - explicit GearsCreateShortcutCallbackFunctor(WebContents* contents) - : contents_(contents) {} - - void Run(const GearsShortcutData& shortcut_data, bool success) { - if (contents_) - contents_->OnGearsCreateShortcutDone(shortcut_data, success); - delete this; - } - void Cancel() { - contents_ = NULL; - } - - private: - WebContents* contents_; -}; - -WebContents::WebContents(Profile* profile, - SiteInstance* site_instance, - RenderViewHostFactory* render_view_factory, - int routing_id, - HANDLE modal_dialog_event) - : TabContents(TAB_CONTENTS_WEB), - view_(new WebContentsViewWin(this)), - ALLOW_THIS_IN_INITIALIZER_LIST( - render_manager_(render_view_factory, this, this)), - render_view_factory_(render_view_factory), - received_page_title_(false), - is_starred_(false), - printing_(*this), - notify_disconnection_(false), - message_box_active_(CreateEvent(NULL, TRUE, FALSE, NULL)), - ALLOW_THIS_IN_INITIALIZER_LIST(fav_icon_helper_(this)), - suppress_javascript_messages_(false), - load_state_(net::LOAD_STATE_IDLE) { - InitWebContentsClass(); - - pending_install_.page_id = 0; - pending_install_.callback_functor = NULL; - - render_manager_.Init(profile, site_instance, routing_id, modal_dialog_event); - - // Register for notifications about all interested prefs change. - PrefService* prefs = profile->GetPrefs(); - if (prefs) { - for (int i = 0; i < kPrefsToObserveLength; ++i) - prefs->AddPrefObserver(kPrefsToObserve[i], this); - } - - // Register for notifications about URL starredness changing on any profile. - NotificationService::current()-> - AddObserver(this, NOTIFY_URLS_STARRED, NotificationService::AllSources()); - NotificationService::current()-> - AddObserver(this, NOTIFY_BOOKMARK_MODEL_LOADED, - NotificationService::AllSources()); - NotificationService::current()-> - AddObserver(this, NOTIFY_RENDER_WIDGET_HOST_DESTROYED, - NotificationService::AllSources()); -} - -WebContents::~WebContents() { - if (web_app_.get()) - web_app_->RemoveObserver(this); - if (pending_install_.callback_functor) - pending_install_.callback_functor->Cancel(); - NotificationService::current()-> - RemoveObserver(this, NOTIFY_RENDER_WIDGET_HOST_DESTROYED, - NotificationService::AllSources()); -} - -// static -void WebContents::RegisterUserPrefs(PrefService* prefs) { - prefs->RegisterBooleanPref(prefs::kAlternateErrorPagesEnabled, true); - - WebPreferences pref_defaults; - prefs->RegisterBooleanPref(prefs::kWebKitJavascriptEnabled, - pref_defaults.javascript_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->RegisterBooleanPref(prefs::kWebKitDeveloperExtrasEnabled, - true); - prefs->RegisterBooleanPref(prefs::kWebKitTextAreasAreResizable, - pref_defaults.text_areas_are_resizable); - prefs->RegisterBooleanPref(prefs::kWebKitJavaEnabled, - pref_defaults.java_enabled); - - 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); -} - -AutofillManager* WebContents::GetAutofillManager() { - if (autofill_manager_.get() == NULL) - autofill_manager_.reset(new AutofillManager(this)); - return autofill_manager_.get(); -} - -PasswordManager* WebContents::GetPasswordManager() { - if (password_manager_.get() == NULL) - password_manager_.reset(new PasswordManager(this)); - return password_manager_.get(); -} - -PluginInstaller* WebContents::GetPluginInstaller() { - if (plugin_installer_.get() == NULL) - plugin_installer_.reset(new PluginInstaller(this)); - return plugin_installer_.get(); -} - -void WebContents::Destroy() { - // Tell the notification service we no longer want notifications. - NotificationService::current()-> - RemoveObserver(this, NOTIFY_URLS_STARRED, - NotificationService::AllSources()); - NotificationService::current()-> - RemoveObserver(this, NOTIFY_BOOKMARK_MODEL_LOADED, - NotificationService::AllSources()); - - // Destroy the print manager right now since a Print command may be pending. - printing_.Destroy(); - - // Unregister the notifications of all observed prefs change. - PrefService* prefs = profile()->GetPrefs(); - if (prefs) { - for (int i = 0; i < kPrefsToObserveLength; ++i) - prefs->RemovePrefObserver(kPrefsToObserve[i], this); - } - - cancelable_consumer_.CancelAllRequests(); - - // Clean up subwindows like plugins and the find in page bar. - view_->OnContentsDestroy(); - - NotifyDisconnected(); - HungRendererWarning::HideForWebContents(this); - render_manager_.Shutdown(); - TabContents::Destroy(); -} - -SiteInstance* WebContents::GetSiteInstance() const { - return render_manager_.current_host()->site_instance(); -} - -SkBitmap WebContents::GetFavIcon() { - if (web_app_.get() && IsWebApplicationActive()) { - SkBitmap app_icon = web_app_->GetFavIcon(); - if (!app_icon.isNull()) - return app_icon; - } - return TabContents::GetFavIcon(); -} - -std::wstring WebContents::GetStatusText() const { - if (!is_loading() || load_state_ == net::LOAD_STATE_IDLE) - return std::wstring(); - - switch (load_state_) { - case net::LOAD_STATE_WAITING_FOR_CACHE: - return l10n_util::GetString(IDS_LOAD_STATE_WAITING_FOR_CACHE); - case net::LOAD_STATE_RESOLVING_PROXY_FOR_URL: - return l10n_util::GetString(IDS_LOAD_STATE_RESOLVING_PROXY_FOR_URL); - case net::LOAD_STATE_RESOLVING_HOST: - return l10n_util::GetString(IDS_LOAD_STATE_RESOLVING_HOST); - case net::LOAD_STATE_CONNECTING: - return l10n_util::GetString(IDS_LOAD_STATE_CONNECTING); - case net::LOAD_STATE_SENDING_REQUEST: - return l10n_util::GetString(IDS_LOAD_STATE_SENDING_REQUEST); - case net::LOAD_STATE_WAITING_FOR_RESPONSE: - return l10n_util::GetStringF(IDS_LOAD_STATE_WAITING_FOR_RESPONSE, - load_state_host_); - // Ignore net::LOAD_STATE_READING_RESPONSE and net::LOAD_STATE_IDLE - } - - return std::wstring(); -} - -bool WebContents::NavigateToPendingEntry(bool reload) { - NavigationEntry* entry = controller()->GetPendingEntry(); - RenderViewHost* dest_render_view_host = render_manager_.Navigate(*entry); - if (!dest_render_view_host) - return false; // Unable to create the desired render view host. - - // Used for page load time metrics. - current_load_start_ = TimeTicks::Now(); - - // Navigate in the desired RenderViewHost. - dest_render_view_host->NavigateToEntry(*entry, reload); - - 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("javascript")) - return false; - } - - // Clear any provisional password saves - this stops password infobars - // showing up on pages the user navigates to while the right page is - // loading. - GetPasswordManager()->ClearProvisionalSave(); - - if (reload && !profile()->IsOffTheRecord()) { - HistoryService* history = - profile()->GetHistoryService(Profile::IMPLICIT_ACCESS); - if (history) - history->SetFavIconOutOfDateForPage(entry->url()); - } - - return true; -} - -void WebContents::Stop() { - render_manager_.Stop(); - printing_.Stop(); -} - -void WebContents::Cut() { - render_view_host()->Cut(); -} - -void WebContents::Copy() { - render_view_host()->Copy(); -} - -void WebContents::Paste() { - render_view_host()->Paste(); -} - -void WebContents::DisassociateFromPopupCount() { - render_view_host()->DisassociateFromPopupCount(); -} - -void WebContents::DidBecomeSelected() { - TabContents::DidBecomeSelected(); - - if (render_widget_host_view()) - render_widget_host_view()->DidBecomeSelected(); - - CacheManagerHost::GetInstance()->ObserveActivity(process()->host_id()); -} - -void WebContents::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 WebContents::Destroy(), which removes - // the |render_view_host()|; then when we actually destroy the window, - // OnWindowPosChanged() notices and calls HideContents() (which calls us). - if (render_widget_host_view()) - render_widget_host_view()->WasHidden(); - - // Loop through children and send WasHidden to them, too. - int count = static_cast(child_windows_.size()); - for (int i = count - 1; i >= 0; --i) { - ConstrainedWindow* window = child_windows_.at(i); - window->WasHidden(); - } - } - - TabContents::WasHidden(); -} - -void WebContents::ShowContents() { - if (render_widget_host_view()) - render_widget_host_view()->DidBecomeSelected(); - - // Loop through children and send DidBecomeSelected to them, too. - int count = static_cast(child_windows_.size()); - for (int i = count - 1; i >= 0; --i) { - ConstrainedWindow* window = child_windows_.at(i); - window->DidBecomeSelected(); - } -} - -void WebContents::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 WebContents. - WasHidden(); -} - -void WebContents::SetDownloadShelfVisible(bool visible) { - TabContents::SetDownloadShelfVisible(visible); - if (visible) { - // Always set this value as it reflects the last time the download shelf - // was made visible (even if it was already visible). - last_download_shelf_show_ = TimeTicks::Now(); - } -} - -void WebContents::PopupNotificationVisibilityChanged(bool visible) { - render_view_host()->PopupNotificationVisibilityChanged(visible); -} - -// Stupid view pass-throughs -void WebContents::CreateView() { - view_->CreateView(); -} -HWND WebContents::GetContainerHWND() const { - return view_->GetContainerHWND(); -} -HWND WebContents::GetContentHWND() { - return view_->GetContentHWND(); -} -void WebContents::GetContainerBounds(gfx::Rect *out) const { - view_->GetContainerBounds(out); -} - -void WebContents::SetWebApp(WebApp* web_app) { - if (web_app_.get()) { - web_app_->RemoveObserver(this); - web_app_->SetWebContents(NULL); - } - - web_app_ = web_app; - if (web_app) { - web_app->AddObserver(this); - web_app_->SetWebContents(this); - } -} - -bool WebContents::IsWebApplication() const { - return (web_app_.get() != NULL); -} - -void WebContents::CreateShortcut() { - NavigationEntry* entry = controller()->GetLastCommittedEntry(); - if (!entry) - return; - - // We only allow one pending install request. By resetting the page id we - // effectively cancel the pending install request. - pending_install_.page_id = entry->page_id(); - pending_install_.icon = GetFavIcon(); - pending_install_.title = GetTitle(); - pending_install_.url = GetURL(); - if (pending_install_.callback_functor) { - pending_install_.callback_functor->Cancel(); - pending_install_.callback_functor = NULL; - } - DCHECK(!pending_install_.icon.isNull()) << "Menu item should be disabled."; - if (pending_install_.title.empty()) - pending_install_.title = UTF8ToWide(GetURL().spec()); - - // Request the application info. When done OnDidGetApplicationInfo is invoked - // and we'll create the shortcut. - render_view_host()->GetApplicationInfo(pending_install_.page_id); -} - -void WebContents::OnJavaScriptMessageBoxClosed(IPC::Message* reply_msg, - bool success, - const std::wstring& prompt) { - last_javascript_message_dismissal_ = TimeTicks::Now(); - render_manager_.OnJavaScriptMessageBoxClosed(reply_msg, success, prompt); -} - -void WebContents::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; - } - - // Get our user preference state. - PrefService* prefs = profile()->GetPrefs(); - DCHECK(prefs); - - std::wstring suggest_name = - SavePackage::GetSuggestNameForSaveAs(prefs, GetTitle()); - - SavePackage::SavePackageParam param(contents_mime_type()); - param.prefs = prefs; - - // TODO(rocking): Use new asynchronous dialog boxes to prevent the SaveAs - // dialog blocking the UI thread. See bug: http://b/issue?id=1129694. - if (SavePackage::GetSaveInfo(suggest_name, GetContainerHWND(), ¶m, - profile()->GetDownloadManager())) - SavePage(param.saved_main_file_path, param.dir, param.save_type); -} - -void WebContents::SavePage(const std::wstring& main_file, - const std::wstring& dir_path, - SavePackage::SavePackageType save_type) { - // Stop the page from navigating. - Stop(); - - save_package_ = new SavePackage(this, save_type, main_file, dir_path); - save_package_->Init(); -} - -void WebContents::PrintPreview() { - // We can't print interstitial page for now. - if (showing_interstitial_page()) - return; - - // If we have a find bar it needs to hide as well. - view_->HideFindBar(false); - - // We don't show the print preview for the beta, only the print dialog. - printing_.ShowPrintDialog(); -} - -bool WebContents::PrintNow() { - // We can't print interstitial page for now. - if (showing_interstitial_page()) - return false; - - // If we have a find bar it needs to hide as well. - view_->HideFindBar(false); - - return printing_.PrintNow(); -} - -bool WebContents::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 WebContents::SetInitialFocus(bool reverse) { - render_view_host()->SetInitialFocus(reverse); -} - -// Notifies the RenderWidgetHost instance about the fact that the page is -// loading, or done loading and calls the base implementation. -void WebContents::SetIsLoading(bool is_loading, - LoadNotificationDetails* details) { - if (!is_loading) { - load_state_ = net::LOAD_STATE_IDLE; - load_state_host_.clear(); - } - - TabContents::SetIsLoading(is_loading, details); - render_manager_.SetIsLoading(is_loading); -} - -RenderViewHostDelegate::View* WebContents::GetViewDelegate() const { - return view_.get(); -} - -RenderViewHostDelegate::Save* WebContents::GetSaveDelegate() const { - return save_package_.get(); // May be NULL, but we can return NULL. -} - -Profile* WebContents::GetProfile() const { - return profile(); -} - -void WebContents::RendererReady(RenderViewHost* rvh) { - if (rvh != render_view_host()) { - // Don't notify the world, since this came from a renderer in the - // background. - return; - } - - NotifyConnected(); - SetIsCrashed(false); -} - -void WebContents::RendererGone(RenderViewHost* rvh) { - // Ask the print preview if this renderer was valuable. - if (!printing_.OnRendererGone(rvh)) - return; - if (rvh != render_view_host()) { - // The pending page's RenderViewHost is gone. - return; - } - - SetIsLoading(false, NULL); - NotifyDisconnected(); - SetIsCrashed(true); - - // Force an invalidation to render sad tab. The view will notice we crashed - // when it paints. - view_->Invalidate(); - - // Hide any visible hung renderer warning for this web contents' process. - HungRendererWarning::HideForWebContents(this); -} - -void WebContents::DidNavigate(RenderViewHost* rvh, - const ViewHostMsg_FrameNavigate_Params& params) { - if (PageTransition::IsMainFrame(params.transition)) - render_manager_.DidNavigateMainFrame(rvh); - - // We can't do anything about navigations when we're inactive. - if (!controller() || !is_active()) - return; - - // 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; - if (!controller()->RendererDidNavigate(params, &details)) - 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 WebContents::UpdateState(RenderViewHost* rvh, - int32 page_id, - const std::string& state) { - DCHECK(rvh == render_view_host()); - if (!controller()) - return; - - // 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( - type(), 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 WebContents::UpdateTitle(RenderViewHost* rvh, - int32 page_id, const std::wstring& title) { - if (!controller()) - return; - - // 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(type(), - GetSiteInstance(), - 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 WebContents::UpdateEncoding(RenderViewHost* render_view_host, - const std::wstring& encoding) { - set_encoding(encoding); -} - -void WebContents::UpdateTargetURL(int32 page_id, const GURL& url) { - if (delegate()) - delegate()->UpdateTargetURL(this, url); -} - -void WebContents::UpdateThumbnail(const GURL& url, - const SkBitmap& bitmap, - const ThumbnailScore& score) { - // Tell History about this thumbnail - HistoryService* hs; - if (!profile()->IsOffTheRecord() && - (hs = profile()->GetHistoryService(Profile::IMPLICIT_ACCESS))) { - hs->SetPageThumbnail(url, bitmap, score); - } -} - -void WebContents::Close(RenderViewHost* rvh) { - // Ignore this if it comes from a RenderViewHost that we aren't showing. - if (delegate() && rvh == render_view_host()) - delegate()->CloseContents(this); -} - -void WebContents::RequestMove(const gfx::Rect& new_bounds) { - if (delegate() && delegate()->IsPopup(this)) - delegate()->MoveContents(this, new_bounds); -} - -void WebContents::DidStartLoading(RenderViewHost* rvh, int32 page_id) { - SetIsLoading(true, NULL); -} - -void WebContents::DidStopLoading(RenderViewHost* rvh, int32 page_id) { - scoped_ptr details; - if (controller()) { - 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) { - scoped_ptr metrics( - base::ProcessMetrics::CreateProcessMetrics( - process()->process().handle())); - - TimeDelta elapsed = TimeTicks::Now() - current_load_start_; - - details.reset(new LoadNotificationDetails( - entry->display_url(), - entry->transition_type(), - elapsed, - controller(), - controller()->GetCurrentEntryIndex())); - } - } - - // Tell PasswordManager we've finished a page load, which serves as a - // green light to save pending passwords and reset itself. - GetPasswordManager()->DidStopLoading(); - - SetIsLoading(false, details.get()); -} - -void WebContents::DidStartProvisionalLoadForFrame( - RenderViewHost* render_view_host, - bool is_main_frame, - const GURL& url) { - ProvisionalLoadDetails details(is_main_frame, - controller()->IsURLInPageNavigation(url), - url, std::string(), false); - NotificationService::current()-> - Notify(NOTIFY_FRAME_PROVISIONAL_LOAD_START, - Source(controller()), - Details(&details)); -} - -void WebContents::DidRedirectProvisionalLoad(int32 page_id, - const GURL& source_url, - const GURL& target_url) { - NavigationEntry* entry; - if (page_id == -1) { - entry = controller()->GetPendingEntry(); - } else { - entry = controller()->GetEntryWithPageID(type(), GetSiteInstance(), - page_id); - } - if (!entry || entry->tab_type() != type() || entry->url() != source_url) - return; - entry->set_url(target_url); -} - -void WebContents::DidLoadResourceFromMemoryCache( - const GURL& url, - const std::string& security_info) { - if (!controller()) - return; - - // Send out a notification that we loaded a resource from our memory cache. - int cert_id, cert_status, security_bits; - SSLManager::DeserializeSecurityInfo(security_info, - &cert_id, &cert_status, - &security_bits); - LoadFromMemoryCacheDetails details(url, cert_id, cert_status); - - NotificationService::current()-> - Notify(NOTIFY_LOAD_FROM_MEMORY_CACHE, - Source(controller()), - Details(&details)); -} - -void WebContents::DidFailProvisionalLoadWithError( - RenderViewHost* render_view_host, - bool is_main_frame, - int error_code, - const GURL& url) { - if (!controller()) - return; - - 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()->GetPendingEntry(); - if (pending_entry && pending_entry->url() == url) - controller()->DiscardNonCommittedEntries(); - - 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(url), - url, std::string(), false); - details.set_error_code(error_code); - - NotificationService::current()-> - Notify(NOTIFY_FAIL_PROVISIONAL_LOAD_WITH_ERROR, - Source(controller()), - Details(&details)); -} - -void WebContents::UpdateFavIconURL(RenderViewHost* render_view_host, - int32 page_id, - const GURL& icon_url) { - fav_icon_helper_.SetFavIconURL(icon_url); -} - -void WebContents::DidDownloadImage( - RenderViewHost* render_view_host, - int id, - const GURL& image_url, - bool errored, - const SkBitmap& image) { - // A notification for downloading would be more flexible, but for now I'm - // forwarding to the two places that could possibly have initiated the - // request. If we end up with another place invoking DownloadImage, probably - // best to refactor out into notification service, or something similar. - if (errored) - fav_icon_helper_.FavIconDownloadFailed(id); - else - fav_icon_helper_.SetFavIcon(id, image_url, image); - if (web_app_.get() && !errored) - web_app_->SetImage(image_url, image); -} - -void WebContents::RequestOpenURL(const GURL& url, const GURL& referrer, - WindowOpenDisposition disposition) { - OpenURL(url, referrer, disposition, PageTransition::LINK); -} - -void WebContents::DomOperationResponse(const std::string& json_string, - int automation_id) { - DomOperationNotificationDetails details(json_string, automation_id); - NotificationService::current()->Notify( - NOTIFY_DOM_OPERATION_RESPONSE, Source(this), - Details(&details)); -} - -void WebContents::ProcessExternalHostMessage(const std::string& receiver, - const std::string& message) { - if (delegate()) - delegate()->ForwardMessageToExternalHost(receiver, message); -} - -void WebContents::GoToEntryAtOffset(int offset) { - if (!controller()) - return; - controller()->GoToOffset(offset); -} - -void WebContents::GetHistoryListCount(int* back_list_count, - int* forward_list_count) { - *back_list_count = 0; - *forward_list_count = 0; - - if (controller()) { - int current_index = controller()->GetLastCommittedEntryIndex(); - *back_list_count = current_index; - *forward_list_count = controller()->GetEntryCount() - current_index - 1; - } -} - -void WebContents::RunFileChooser(bool multiple_files, - const std::wstring& title, - const std::wstring& default_file, - const std::wstring& filter) { - HWND toplevel_hwnd = GetAncestor(GetContainerHWND(), GA_ROOT); - if (!select_file_dialog_.get()) - select_file_dialog_ = SelectFileDialog::Create(this); - SelectFileDialog::Type dialog_type = - multiple_files ? SelectFileDialog::SELECT_OPEN_MULTI_FILE : - SelectFileDialog::SELECT_OPEN_FILE; - select_file_dialog_->SelectFile(dialog_type, title, default_file, filter, - std::wstring(), toplevel_hwnd, NULL); -} - -void WebContents::RunJavaScriptMessage( - const std::wstring& message, - const std::wstring& default_prompt, - 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). - bool suppress_this_message = suppress_javascript_messages_; - if (delegate()) - suppress_this_message |= - (delegate()->GetConstrainingContents(this) != NULL); - - *did_suppress_message = suppress_this_message; - - if (!suppress_this_message) { - TimeDelta time_since_last_message( - 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 < - TimeDelta::FromMilliseconds(kJavascriptMessageExpectedDelay)) - show_suppress_checkbox = true; - - JavascriptMessageBoxHandler::RunJavascriptMessageBox(this, - 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". - OnJavaScriptMessageBoxClosed(reply_msg, false, L""); - } -} - -void WebContents::RunBeforeUnloadConfirm(const std::wstring& message, - IPC::Message* reply_msg) { - JavascriptBeforeUnloadHandler::RunBeforeUnloadDialog(this, message, - reply_msg); -} - -void WebContents::ShowModalHTMLDialog(const GURL& url, int width, int height, - const std::string& json_arguments, - IPC::Message* reply_msg) { - if (delegate()) { - ModalHtmlDialogDelegate* dialog_delegate = - new ModalHtmlDialogDelegate(url, width, height, json_arguments, - reply_msg, this); - delegate()->ShowHtmlDialog(dialog_delegate, NULL); - } -} - -void WebContents::PasswordFormsSeen( - const std::vector& forms) { - GetPasswordManager()->PasswordFormsSeen(forms); -} - -void WebContents::AutofillFormSubmitted( - const AutofillForm& form) { - GetAutofillManager()->AutofillFormSubmitted(form); -} - -void WebContents::GetAutofillSuggestions(const std::wstring& field_name, - const std::wstring& user_text, int64 node_id, int request_id) { - GetAutofillManager()->FetchValuesForName(field_name, user_text, - kMaxAutofillMenuItems, node_id, request_id); -} - -// Checks to see if we should generate a keyword based on the OSDD, and if -// necessary uses TemplateURLFetcher to download the OSDD and create a keyword. -void WebContents::PageHasOSDD(RenderViewHost* render_view_host, - int32 page_id, const GURL& url, - bool autodetected) { - // Make sure page_id is the current page, and the TemplateURLModel is loaded. - DCHECK(url.is_valid()); - if (!controller() || !IsActiveEntry(page_id)) - return; - TemplateURLModel* url_model = profile()->GetTemplateURLModel(); - if (!url_model) - return; - if (!url_model->loaded()) { - url_model->Load(); - return; - } - if (!profile()->GetTemplateURLFetcher()) - return; - - if (profile()->IsOffTheRecord()) - return; - - const NavigationEntry* entry = controller()->GetLastCommittedEntry(); - DCHECK(entry); - - const NavigationEntry* base_entry = entry; - if (IsFormSubmit(base_entry)) { - // If the current page is a form submit, find the last page that was not - // a form submit and use its url to generate the keyword from. - int index = controller()->GetLastCommittedEntryIndex() - 1; - while (index >= 0 && IsFormSubmit(controller()->GetEntryAtIndex(index))) - index--; - if (index >= 0) - base_entry = controller()->GetEntryAtIndex(index); - else - base_entry = NULL; - } - - // We want to use the user typed URL if available since that represents what - // the user typed to get here, and fall back on the regular URL if not. - if (!base_entry) - return; - GURL keyword_url = base_entry->user_typed_url().is_valid() ? - base_entry->user_typed_url() : base_entry->url(); - if (!keyword_url.is_valid()) - return; - std::wstring keyword = TemplateURLModel::GenerateKeyword(keyword_url, - autodetected); - if (keyword.empty()) - return; - const TemplateURL* template_url = - url_model->GetTemplateURLForKeyword(keyword); - if (template_url && (!template_url->safe_for_autoreplace() || - template_url->originating_url() == url)) { - // Either there is a user created TemplateURL for this keyword, or the - // keyword has the same OSDD url and we've parsed it. - return; - } - - // Download the OpenSearch description document. If this is successful a - // new keyword will be created when done. - profile()->GetTemplateURLFetcher()->ScheduleDownload( - keyword, - url, - base_entry->favicon().url(), - GetAncestor(view_->GetContainerHWND(), GA_ROOT), - autodetected); -} - -void WebContents::InspectElementReply(int num_resources) { - // We have received reply from inspect element request. Notify the - // automation provider in case we need to notify automation client. - NotificationService::current()-> - Notify(NOTIFY_DOM_INSPECT_ELEMENT_RESPONSE, Source(this), - Details(&num_resources)); -} - -void WebContents::DidGetPrintedPagesCount(int cookie, int number_pages) { - printing_.DidGetPrintedPagesCount(cookie, number_pages); -} - -void WebContents::DidPrintPage(const ViewHostMsg_DidPrintPage_Params& params) { - printing_.DidPrintPage(params); -} - -GURL WebContents::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(kLinkDoctorBaseURL)); - url = google_util::AppendGoogleTLDParam(url); - } - return url; -} - -WebPreferences WebContents::GetWebkitPrefs() { - // Initialize web_preferences_ to chrome defaults. - WebPreferences web_prefs; - PrefService* prefs = profile()->GetPrefs(); - - web_prefs.fixed_font_family = - prefs->GetString(prefs::kWebKitFixedFontFamily); - web_prefs.serif_font_family = - prefs->GetString(prefs::kWebKitSerifFontFamily); - web_prefs.sans_serif_font_family = - prefs->GetString(prefs::kWebKitSansSerifFontFamily); - if (prefs->GetBoolean(prefs::kWebKitStandardFontIsSerif)) - web_prefs.standard_font_family = web_prefs.serif_font_family; - else - web_prefs.standard_font_family = web_prefs.sans_serif_font_family; - web_prefs.cursive_font_family = - prefs->GetString(prefs::kWebKitCursiveFontFamily); - web_prefs.fantasy_font_family = - prefs->GetString(prefs::kWebKitFantasyFontFamily); - - web_prefs.default_font_size = - prefs->GetInteger(prefs::kWebKitDefaultFontSize); - web_prefs.default_fixed_font_size = - prefs->GetInteger(prefs::kWebKitDefaultFixedFontSize); - web_prefs.minimum_font_size = - prefs->GetInteger(prefs::kWebKitMinimumFontSize); - web_prefs.minimum_logical_font_size = - prefs->GetInteger(prefs::kWebKitMinimumLogicalFontSize); - - web_prefs.default_encoding = prefs->GetString(prefs::kDefaultCharset); - - web_prefs.javascript_can_open_windows_automatically = - prefs->GetBoolean(prefs::kWebKitJavascriptCanOpenWindowsAutomatically); - web_prefs.dom_paste_enabled = - prefs->GetBoolean(prefs::kWebKitDomPasteEnabled); - web_prefs.shrinks_standalone_images_to_fit = - prefs->GetBoolean(prefs::kWebKitShrinksStandaloneImagesToFit); - - { // Command line switches are used for preferences with no user interface. - CommandLine command_line; - web_prefs.developer_extras_enabled = - !command_line.HasSwitch(switches::kDisableDevTools) && - prefs->GetBoolean(prefs::kWebKitDeveloperExtrasEnabled); - web_prefs.javascript_enabled = - !command_line.HasSwitch(switches::kDisableJavaScript) && - prefs->GetBoolean(prefs::kWebKitJavascriptEnabled); - web_prefs.plugins_enabled = - !command_line.HasSwitch(switches::kDisablePlugins) && - prefs->GetBoolean(prefs::kWebKitPluginsEnabled); - web_prefs.java_enabled = - !command_line.HasSwitch(switches::kDisableJava) && - prefs->GetBoolean(prefs::kWebKitJavaEnabled); - web_prefs.loads_images_automatically = - !command_line.HasSwitch(switches::kDisableImages) && - prefs->GetBoolean(prefs::kWebKitLoadsImagesAutomatically); - web_prefs.uses_page_cache = - command_line.HasSwitch(switches::kEnableFastback); - } - - web_prefs.uses_universal_detector = - prefs->GetBoolean(prefs::kWebKitUsesUniversalDetector); - web_prefs.text_areas_are_resizable = - prefs->GetBoolean(prefs::kWebKitTextAreasAreResizable); - - // User CSS is currently disabled because it crashes chrome. See - // webkit/glue/webpreferences.h for more details. - - // Make sure we will set the default_encoding with canonical encoding name. - web_prefs.default_encoding = - CharacterEncoding::GetCanonicalEncodingNameByAliasName( - web_prefs.default_encoding); - if (web_prefs.default_encoding.empty()) { - prefs->ClearPref(prefs::kDefaultCharset); - web_prefs.default_encoding = prefs->GetString( - prefs::kDefaultCharset); - } - DCHECK(!web_prefs.default_encoding.empty()); - return web_prefs; -} - -void WebContents::OnMissingPluginStatus(int status) { - GetPluginInstaller()->OnMissingPluginStatus(status); -} - -void WebContents::OnCrashedPlugin(const FilePath& plugin_path) { - DCHECK(!plugin_path.value().empty()); - - std::wstring plugin_name = plugin_path.ToWStringHack(); - scoped_ptr version_info( - FileVersionInfo::CreateFileVersionInfo(plugin_path)); - if (version_info.get()) { - const std::wstring& product_name = version_info->product_name(); - if (!product_name.empty()) - plugin_name = product_name; - } - AddInfoBar(new SimpleAlertInfoBarDelegate( - this, l10n_util::GetStringF(IDS_PLUGIN_CRASHED_PROMPT, plugin_name), - NULL)); -} - -void WebContents::OnJSOutOfMemory() { - AddInfoBar(new SimpleAlertInfoBarDelegate( - this, l10n_util::GetString(IDS_JS_OUT_OF_MEMORY_PROMPT), NULL)); -} - -bool WebContents::CanBlur() const { - return delegate() ? delegate()->CanBlur() : true; -} - -void WebContents::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->UnloadListenerHasFired(); - - 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()) - HungRendererWarning::ShowForWebContents(this); -} - -void WebContents::RendererResponsive(RenderViewHost* render_view_host) { - HungRendererWarning::HideForWebContents(this); -} - -void WebContents::LoadStateChanged(const GURL& url, - net::LoadState load_state) { - load_state_ = load_state; - load_state_host_ = UTF8ToWide(url.host()); - if (load_state_ == net::LOAD_STATE_READING_RESPONSE) - SetNotWaitingForResponse(); - if (is_loading()) - NotifyNavigationStateChanged(INVALIDATE_LOAD); -} - -void WebContents::OnDidGetApplicationInfo( - int32 page_id, - const webkit_glue::WebApplicationInfo& info) { - if (pending_install_.page_id != page_id) - return; // The user clicked create on a separate page. Ignore this. - - pending_install_.callback_functor = - new GearsCreateShortcutCallbackFunctor(this); - GearsCreateShortcut( - info, pending_install_.title, pending_install_.url, pending_install_.icon, - NewCallback(pending_install_.callback_functor, - &GearsCreateShortcutCallbackFunctor::Run)); -} - -void WebContents::OnEnterOrSpace() { - // See comment in RenderViewHostDelegate::OnEnterOrSpace as to why we do this. - DownloadRequestManager* drm = g_browser_process->download_request_manager(); - if (drm) - drm->OnUserGesture(this); -} - -bool WebContents::CanTerminate() const { - if (!delegate()) - return true; - - return !delegate()->IsExternalTabContainer(); -} - -void WebContents::FileSelected(const std::wstring& path, void* params) { - render_view_host()->FileSelected(path); -} - -void WebContents::MultiFilesSelected(const std::vector& files, - void* params) { - render_view_host()->MultiFilesSelected(files); -} - - -void WebContents::FileSelectionCanceled(void* params) { - // If the user cancels choosing a file to upload we pass back an - // empty vector. - render_view_host()->MultiFilesSelected(std::vector()); -} - -void WebContents::BeforeUnloadFiredFromRenderManager( - bool proceed, - bool* proceed_to_fire_unload) { - if (delegate()) - delegate()->BeforeUnloadFired(this, proceed, proceed_to_fire_unload); -} - -void WebContents::UpdateRenderViewSizeForRenderManager() { - // TODO(brettw) this is a hack. See WebContentsView::SizeContents. - view_->SizeContents(view_->GetContainerSize()); -} - -bool WebContents::CreateRenderViewForRenderManager( - RenderViewHost* render_view_host) { - RenderWidgetHostView* rvh_view = view_->CreateViewForWidget(render_view_host); - - bool ok = render_view_host->CreateRenderView(); - if (ok) { - // TODO(brettw) hack alert. Do this in some cross platform way, or move - // to the view? - RenderWidgetHostViewWin* rvh_view_win = - static_cast(rvh_view); - rvh_view->SetSize(view_->GetContainerSize()); - UpdateMaxPageIDIfNecessary(render_view_host->site_instance(), - render_view_host); - } - return ok; -} - -void WebContents::Observe(NotificationType type, - const NotificationSource& source, - const NotificationDetails& details) { - switch (type) { - case NOTIFY_BOOKMARK_MODEL_LOADED: // BookmarkModel finished loading, fall - // through to update starred state. - case NOTIFY_URLS_STARRED: { // Somewhere, a URL has been starred. - // Ignore notifications for profiles other than our current one. - Profile* source_profile = Source(source).ptr(); - if (!source_profile->IsSameProfile(profile())) - return; - - UpdateStarredStateForCurrentURL(); - break; - } - case NOTIFY_PREF_CHANGED: { - std::wstring* pref_name_in = Details(details).ptr(); - DCHECK(Source(source).ptr() == profile()->GetPrefs()); - if (*pref_name_in == prefs::kAlternateErrorPagesEnabled) { - UpdateAlternateErrorPageURL(); - } else if (*pref_name_in == prefs::kDefaultCharset || - StartsWithASCII(WideToUTF8(*pref_name_in), "webkit.webprefs.", true) - ) { - UpdateWebPreferences(); - } else { - NOTREACHED() << "unexpected pref change notification" << *pref_name_in; - } - break; - } - case NOTIFY_RENDER_WIDGET_HOST_DESTROYED: - view_->RenderWidgetHostDestroyed(Source(source).ptr()); - break; - default: { - TabContents::Observe(type, source, details); - break; - } - } -} - -void WebContents::DidNavigateMainFramePostCommit( - const NavigationController::LoadCommittedDetails& details, - const ViewHostMsg_FrameNavigate_Params& params) { - // Hide the download shelf if all the following conditions are true: - // - there are no active downloads. - // - this is a navigation to a different TLD. - // - at least 5 seconds have elapsed since the download shelf was shown. - // TODO(jcampan): bug 1156075 when user gestures are reliable, they should - // be used to ensure we are hiding only on user initiated - // navigations. - DownloadManager* download_manager = profile()->GetDownloadManager(); - // download_manager can be NULL in unit test context. - if (download_manager && download_manager->in_progress_count() == 0 && - !details.previous_url.is_empty() && - !net::RegistryControlledDomainService::SameDomainOrHost( - details.previous_url, details.entry->url())) { - TimeDelta time_delta( - TimeTicks::Now() - last_download_shelf_show_); - if (time_delta > - TimeDelta::FromMilliseconds(kDownloadShelfHideDelay)) { - SetDownloadShelfVisible(false); - } - } - - 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()); - - // UpdateHelpersForDidNavigate will handle the case where the password_form - // origin is valid. - // TODO(brettw) bug 1343111: Password manager stuff in here needs to be - // cleaned up and covered by tests. - if (!params.password_form.origin.is_valid()) - GetPasswordManager()->DidNavigate(); - } - - // The keyword generator uses the navigation entries, so must be called after - // the commit. - GenerateKeywordIfNecessary(params); - - // 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()); - - // Close constrained popups if necessary. - MaybeCloseChildWindows(details.previous_url, details.entry->url()); - - // We hide the FindInPage window when the user navigates away, except on - // reload. - if (PageTransition::StripQualifier(params.transition) != - PageTransition::RELOAD) - view_->HideFindBar(true); - - // Update the starred state. - UpdateStarredStateForCurrentURL(); -} - -void WebContents::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; - - // 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. - UpdateHistoryForNavigation(GetURL(), params); - } - - // Notify the password manager of the navigation or form submit. - // TODO(brettw) bug 1343111: Password manager stuff in here needs to be - // cleaned up and covered by tests. - if (params.password_form.origin.is_valid()) - GetPasswordManager()->ProvisionallySavePassword(params.password_form); -} - -void WebContents::MaybeCloseChildWindows(const GURL& previous_url, - const GURL& current_url) { - if (net::RegistryControlledDomainService::SameDomainOrHost( - previous_url, current_url)) - return; - - // Clear out any child windows since we are leaving this page entirely. - // We use indices instead of iterators in case CloseWindow does something - // that may invalidate an iterator. - int size = static_cast(child_windows_.size()); - for (int i = size - 1; i >= 0; --i) { - ConstrainedWindow* window = child_windows_[i]; - if (window) - window->CloseConstrainedWindow(); - } -} - -void WebContents::UpdateStarredStateForCurrentURL() { - BookmarkModel* model = profile()->GetBookmarkModel(); - const bool old_state = is_starred_; - is_starred_ = (model && model->IsBookmarked(GetURL())); - - if (is_starred_ != old_state && delegate()) - delegate()->URLStarredChanged(this, is_starred_); -} - -void WebContents::UpdateAlternateErrorPageURL() { - GURL url = GetAlternateErrorPageURL(); - render_view_host()->SetAlternateErrorPageURL(url); -} - -void WebContents::UpdateWebPreferences() { - render_view_host()->UpdateWebPreferences(GetWebkitPrefs()); -} - -bool WebContents::IsWebApplicationActive() const { - if (!web_app_.get()) - return false; - - // If we are inside an application, the application is always active. For - // example, this allows us to display the GMail icon even when we are bounced - // the login page. - if (delegate() && delegate()->IsApplication()) - return true; - - return (GetURL() == web_app_->url()); -} - -void WebContents::WebAppImagesChanged(WebApp* web_app) { - DCHECK(web_app == web_app_.get()); - if (delegate() && IsWebApplicationActive()) - delegate()->NavigationStateChanged(this, TabContents::INVALIDATE_FAVICON); -} - -void WebContents::OnGearsCreateShortcutDone( - const GearsShortcutData& shortcut_data, bool success) { - NavigationEntry* current_entry = controller()->GetLastCommittedEntry(); - bool same_page = - current_entry && pending_install_.page_id == current_entry->page_id(); - - if (success && same_page) { - // Only switch to app mode if the user chose to create a shortcut and - // we're still on the same page that it corresponded to. - SetWebApp(new WebApp(profile(), shortcut_data)); - if (delegate()) - delegate()->ConvertContentsToApplication(this); - } - - // Reset the page id to indicate no requests are pending. - pending_install_.page_id = 0; - pending_install_.callback_functor = NULL; -} - -void WebContents::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); - } - } -} - -void WebContents::UpdateHistoryForNavigation(const GURL& display_url, - const ViewHostMsg_FrameNavigate_Params& params) { - if (profile()->IsOffTheRecord()) - return; - - // Add to history service. - HistoryService* hs = profile()->GetHistoryService(Profile::IMPLICIT_ACCESS); - if (hs) { - if (PageTransition::IsMainFrame(params.transition) && - display_url != params.url) { - // Hack on the "display" 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 display URL as a redirect. - // This only applies to the main frame, as the display URL doesn't apply - // to sub-frames. - std::vector redirects = params.redirects; - if (!redirects.empty()) - redirects.back() = display_url; - hs->AddPage(display_url, this, params.page_id, params.referrer, - params.transition, redirects); - } else { - hs->AddPage(params.url, this, params.page_id, params.referrer, - params.transition, params.redirects); - } - } -} - -bool WebContents::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." - std::wstring final_title; - bool explicit_set; - if (entry->url().SchemeIsFile() && title.empty()) { - final_title = UTF8ToWide(entry->url().ExtractFileName()); - explicit_set = false; // Don't count synthetic titles toward the set limit. - } else { - TrimWhitespace(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); - - // Update the history system for this page. - if (!profile()->IsOffTheRecord() && !received_page_title_) { - HistoryService* hs = - profile()->GetHistoryService(Profile::IMPLICIT_ACCESS); - if (hs) - hs->SetPageTitle(entry->display_url(), final_title); - - // Don't allow the title to be saved again for explicitly set ones. - received_page_title_ = explicit_set; - } - - // Lastly, set the title for the view. - view_->SetPageTitle(final_title); - - return true; -} - -void WebContents::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(NOTIFY_WEB_CONTENTS_SWAPPED, - Source(this), - NotificationService::NoDetails()); -} - -void WebContents::NotifyConnected() { - notify_disconnection_ = true; - NotificationService::current()-> - Notify(NOTIFY_WEB_CONTENTS_CONNECTED, - Source(this), - NotificationService::NoDetails()); -} - -void WebContents::NotifyDisconnected() { - if (!notify_disconnection_) - return; - - notify_disconnection_ = false; - NotificationService::current()-> - Notify(NOTIFY_WEB_CONTENTS_DISCONNECTED, - Source(this), - NotificationService::NoDetails()); -} - -void WebContents::GenerateKeywordIfNecessary( - const ViewHostMsg_FrameNavigate_Params& params) { - DCHECK(controller()); - if (!params.searchable_form_url.is_valid()) - return; - - if (profile()->IsOffTheRecord()) - return; - - const int last_index = controller()->GetLastCommittedEntryIndex(); - // When there was no previous page, the last index will be 0. This is - // normally due to a form submit that opened in a new tab. - // TODO(brettw) bug 916126: we should support keywords when form submits - // happen in new tabs. - if (last_index <= 0) - return; - const NavigationEntry* previous_entry = - controller()->GetEntryAtIndex(last_index - 1); - if (IsFormSubmit(previous_entry)) { - // Only generate a keyword if the previous page wasn't itself a form - // submit. - return; - } - - GURL keyword_url = previous_entry->user_typed_url().is_valid() ? - previous_entry->user_typed_url() : previous_entry->url(); - std::wstring keyword = - TemplateURLModel::GenerateKeyword(keyword_url, true); // autodetected - if (keyword.empty()) - return; - - TemplateURLModel* url_model = profile()->GetTemplateURLModel(); - if (!url_model) - return; - - if (!url_model->loaded()) { - url_model->Load(); - return; - } - - const TemplateURL* current_url; - std::wstring url = UTF8ToWide(params.searchable_form_url.spec()); - if (!url_model->CanReplaceKeyword(keyword, url, ¤t_url)) - return; - - if (current_url) { - if (current_url->originating_url().is_valid()) { - // The existing keyword was generated from an OpenSearch description - // document, don't regenerate. - return; - } - url_model->Remove(current_url); - } - TemplateURL* new_url = new TemplateURL(); - new_url->set_keyword(keyword); - new_url->set_short_name(keyword); - new_url->SetURL(url, 0, 0); - new_url->add_input_encoding(params.searchable_form_encoding); - DCHECK(controller()->GetLastCommittedEntry()); - const GURL& favicon_url = - controller()->GetLastCommittedEntry()->favicon().url(); - if (favicon_url.is_valid()) { - new_url->SetFavIconURL(favicon_url); - } else { - // The favicon url isn't valid. This means there really isn't a favicon, - // or the favicon url wasn't obtained before the load started. This assumes - // the later. - // TODO(sky): Need a way to set the favicon that doesn't involve generating - // its url. - new_url->SetFavIconURL(TemplateURL::GenerateFaviconURL(params.referrer)); - } - new_url->set_safe_for_autoreplace(true); - url_model->Add(new_url); -} diff --git a/chrome/browser/web_contents.h b/chrome/browser/web_contents.h deleted file mode 100644 index 1ac6a56..0000000 --- a/chrome/browser/web_contents.h +++ /dev/null @@ -1,572 +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. - -#ifndef CHROME_BROWSER_WEB_CONTENTS_H_ -#define CHROME_BROWSER_WEB_CONTENTS_H_ - -#include "base/hash_tables.h" -#include "chrome/browser/download/save_package.h" -#include "chrome/browser/fav_icon_helper.h" -#include "chrome/browser/printing/print_view_manager.h" -#include "chrome/browser/render_view_host_delegate.h" -#include "chrome/browser/render_view_host_manager.h" -#include "chrome/browser/shell_dialogs.h" -#include "chrome/browser/tab_contents.h" -#include "chrome/browser/web_app.h" - -class AutofillManager; -class InterstitialPageDelegate; -class PasswordManager; -class PluginInstaller; -class RenderViewHost; -class RenderViewHostFactory; -class RenderWidgetHost; -class WebContentsView; - -// WebContents represents the contents of a tab that shows web pages. It embeds -// a RenderViewHost (via RenderViewHostManager) to actually display the page. -class WebContents : public TabContents, - public RenderViewHostDelegate, - public RenderViewHostManager::Delegate, - public SelectFileDialog::Listener, - public WebApp::Observer { - public: - // If instance is NULL, then creates a new process for this view. Otherwise - // initialize with a process already created for a different WebContents. - // This will share the process between views in the same instance. If - // render_view_factory is NULL, this will create RenderViewHost objects - // directly. - WebContents(Profile* profile, - SiteInstance* instance, - RenderViewHostFactory* render_view_factory, - int routing_id, - HANDLE modal_dialog_event); - - static void RegisterUserPrefs(PrefService* prefs); - - // Getters ------------------------------------------------------------------- - - // Returns the AutofillManager, creating it if necessary. - AutofillManager* GetAutofillManager(); - - // Returns the PasswordManager, creating it if necessary. - PasswordManager* GetPasswordManager(); - - // Returns the PluginInstaller, creating it if necessary. - PluginInstaller* GetPluginInstaller(); - - // 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* process() const { - return render_manager_.current_host()->process(); - } - RenderViewHost* render_view_host() const { - return render_manager_.current_host(); - } - - // The WebContentsView will never change and is guaranteed non-NULL. - WebContentsView* view() const { - return view_.get(); - } - - bool is_starred() const { return is_starred_; } - - const std::wstring& encoding() const { return encoding_; } - void set_encoding(const std::wstring& encoding) { - encoding_ = encoding; - } - - // TabContents (public overrides) -------------------------------------------- - - virtual void Destroy(); - virtual WebContents* AsWebContents() { return this; } - virtual SiteInstance* GetSiteInstance() const; - virtual SkBitmap GetFavIcon(); - virtual std::wstring GetStatusText() const; - virtual bool NavigateToPendingEntry(bool reload); - virtual void Stop(); - virtual void Cut(); - virtual void Copy(); - virtual void Paste(); - virtual void DisassociateFromPopupCount(); - virtual void DidBecomeSelected(); - virtual void WasHidden(); - virtual void ShowContents(); - virtual void HideContents(); - virtual void SetDownloadShelfVisible(bool visible); - virtual void PopupNotificationVisibilityChanged(bool visible); - - // Retarded pass-throughs to the view. - // TODO(brettw) fix this, tab contents shouldn't have these methods, probably - // it should be killed altogether. - virtual void CreateView(); - virtual HWND GetContainerHWND() const; - virtual HWND GetContentHWND(); - virtual void GetContainerBounds(gfx::Rect *out) const; - - // Web apps ------------------------------------------------------------------ - - // Sets the WebApp for this WebContents. - void SetWebApp(WebApp* web_app); - WebApp* web_app() { return web_app_.get(); } - - // Return whether this tab contents was created to contain an application. - bool IsWebApplication() const; - - // Tell Gears to create a shortcut for the current page. - void CreateShortcut(); - - // 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; - } - - // JavascriptMessageBoxHandler calls this when the dialog is closed. - void OnJavaScriptMessageBoxClosed(IPC::Message* reply_msg, - bool success, - const std::wstring& prompt); - - // Prepare for saving page. - 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. - void SavePage(const std::wstring& main_file, const std::wstring& dir_path, - SavePackage::SavePackageType save_type); - - // 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(); - - // 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 WebContents 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 override_encoding(const std::wstring& encoding) { - set_encoding(encoding); - render_view_host()->SetPageEncoding(encoding); - } - - void CrossSiteNavigationCanceled() { - render_manager_.CrossSiteNavigationCanceled(); - } - - protected: - // Should be deleted via CloseContents. - virtual ~WebContents(); - - RenderWidgetHostView* render_widget_host_view() const { - return render_manager_.current_view(); - } - - // TabContents (private overrides) ------------------------------------------- - - virtual void SetInitialFocus(bool reverse); - virtual void SetIsLoading(bool is_loading, LoadNotificationDetails* details); - - // RenderViewHostDelegate ---------------------------------------------------- - - virtual RenderViewHostDelegate::View* GetViewDelegate() const; - virtual RenderViewHostDelegate::Save* GetSaveDelegate() const; - virtual Profile* GetProfile() const; - virtual void RendererReady(RenderViewHost* render_view_host); - virtual void RendererGone(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::wstring& encoding); - virtual void UpdateTargetURL(int32 page_id, const GURL& url); - virtual void UpdateThumbnail(const GURL& url, - const SkBitmap& bitmap, - const ThumbnailScore& score); - virtual void Close(RenderViewHost* render_view_host); - virtual void RequestMove(const gfx::Rect& new_bounds); - virtual void DidStartLoading(RenderViewHost* render_view_host, int32 page_id); - virtual void DidStopLoading(RenderViewHost* render_view_host, int32 page_id); - virtual void DidStartProvisionalLoadForFrame(RenderViewHost* render_view_host, - bool is_main_frame, - const GURL& url); - virtual void DidRedirectProvisionalLoad(int32 page_id, - const GURL& source_url, - const GURL& target_url); - virtual void DidLoadResourceFromMemoryCache(const GURL& url, - const std::string& security_info); - virtual void DidFailProvisionalLoadWithError(RenderViewHost* render_view_host, - bool is_main_frame, - int error_code, - const GURL& url); - virtual void UpdateFavIconURL(RenderViewHost* render_view_host, - int32 page_id, const GURL& icon_url); - virtual void DidDownloadImage(RenderViewHost* render_view_host, - int id, - const GURL& image_url, - bool errored, - const SkBitmap& image); - virtual void RequestOpenURL(const GURL& url, const GURL& referrer, - WindowOpenDisposition disposition); - virtual void DomOperationResponse(const std::string& json_string, - int automation_id); - virtual void ProcessExternalHostMessage(const std::string& receiver, - const std::string& message); - virtual void GoToEntryAtOffset(int offset); - virtual void GetHistoryListCount(int* back_list_count, - int* forward_list_count); - virtual void RunFileChooser(bool multiple_files, - const std::wstring& title, - const std::wstring& default_file, - const std::wstring& filter); - virtual void RunJavaScriptMessage(const std::wstring& message, - const std::wstring& default_prompt, - 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 void PasswordFormsSeen(const std::vector& forms); - virtual void AutofillFormSubmitted(const AutofillForm& form); - virtual void GetAutofillSuggestions(const std::wstring& field_name, - const std::wstring& user_text, int64 node_id, int request_id); - virtual void PageHasOSDD(RenderViewHost* render_view_host, - int32 page_id, const GURL& url, bool autodetected); - virtual void InspectElementReply(int num_resources); - virtual void DidGetPrintedPagesCount(int cookie, int number_pages); - virtual void DidPrintPage(const ViewHostMsg_DidPrintPage_Params& params); - virtual GURL GetAlternateErrorPageURL() const; - virtual WebPreferences GetWebkitPrefs(); - virtual void OnMissingPluginStatus(int status); - virtual void OnCrashedPlugin(const FilePath& plugin_path); - virtual void OnJSOutOfMemory(); - virtual void ShouldClosePage(bool proceed) { - render_manager_.ShouldClosePage(proceed); - } - // Allows the WebContents 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. - void OnCrossSiteResponse(int new_render_process_host_id, - int new_request_id) { - render_manager_.OnCrossSiteResponse(new_render_process_host_id, - new_request_id); - } - virtual bool CanBlur() const; - 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); - virtual void OnDidGetApplicationInfo( - int32 page_id, - const webkit_glue::WebApplicationInfo& info); - virtual void OnEnterOrSpace(); - virtual bool CanTerminate() const; - - - // SelectFileDialog::Listener ------------------------------------------------ - - virtual void FileSelected(const std::wstring& path, void* params); - virtual void MultiFilesSelected(const std::vector& files, - void* params); - virtual void FileSelectionCanceled(void* params); - - // RenderViewHostManager::Delegate ------------------------------------------- - - virtual void BeforeUnloadFiredFromRenderManager( - bool proceed, - bool* proceed_to_fire_unload); - virtual void DidStartLoadingFromRenderManager( - RenderViewHost* render_view_host, int32 page_id) { - DidStartLoading(render_view_host, page_id); - } - virtual void RendererGoneFromRenderManager(RenderViewHost* render_view_host) { - RendererGone(render_view_host); - } - virtual void UpdateRenderViewSizeForRenderManager(); - virtual void NotifySwappedFromRenderManager() { - NotifySwapped(); - } - virtual NavigationController* GetControllerForRenderManager() { - return controller(); - } - - // 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 WebContents 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. - // - // TODO(brettw) clean this up! This logic seems out of place. This is called - // by the RenderViewHostManager, but also overridden by the DOMUIHost. Any - // logic that has to be here should have a more clear name. - virtual bool CreateRenderViewForRenderManager( - RenderViewHost* render_view_host); - - private: - FRIEND_TEST(WebContentsTest, UpdateTitle); - friend class TestWebContents; - - // Temporary until the view/contents separation is complete. - friend class WebContentsViewWin; - - // So InterstitialPage can access SetIsLoading. - friend class InterstitialPage; - - // When CreateShortcut is invoked RenderViewHost::GetApplicationInfo is - // invoked. CreateShortcut caches the state of the page needed to create the - // shortcut in PendingInstall. When OnDidGetApplicationInfo is invoked, it - // uses the information from PendingInstall and the WebApplicationInfo - // to create the shortcut. - class GearsCreateShortcutCallbackFunctor; - struct PendingInstall { - int32 page_id; - SkBitmap icon; - std::wstring title; - GURL url; - // This object receives the GearsCreateShortcutCallback and routes the - // message back to the WebContents, if we haven't been deleted. - GearsCreateShortcutCallbackFunctor* callback_functor; - }; - - - // NotificationObserver ------------------------------------------------------ - - virtual void Observe(NotificationType type, - const NotificationSource& source, - const NotificationDetails& details); - - // 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 child windows (constrained popups) when the domain changes. - // Supply the new and old URLs, and this function will figure out when the - // domain changing conditions are met. - void MaybeCloseChildWindows(const GURL& previous_url, - const GURL& current_url); - - // Updates the starred state from the bookmark bar model. If the state has - // changed, the delegate is notified. - void UpdateStarredStateForCurrentURL(); - - // 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(); - - // Return whether the optional web application is active for the current URL. - // Call this method to check if web app properties are in effect. - // - // Note: This method should be used for presentation but not security. The app - // is always active if the containing window is a web application. - bool IsWebApplicationActive() const; - - // WebApp::Observer method. Invoked when the set of images contained in the - // web app changes. Notifies the delegate our favicon has changed. - virtual void WebAppImagesChanged(WebApp* web_app); - - // Called when the user dismisses the shortcut creation dialog. 'success' is - // true if the shortcut was created. - void OnGearsCreateShortcutDone(const GearsShortcutData& shortcut_data, - bool success); - - // 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); - - // Called by OnMsgNavigate to update history state. Overridden by subclasses - // that don't want to be added to history. - virtual void UpdateHistoryForNavigation(const GURL& display_url, - 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); - - // Misc non-view stuff ------------------------------------------------------- - - // Helper functions for sending notifications. - void NotifySwapped(); - void NotifyConnected(); - void NotifyDisconnected(); - - // If params has a searchable form, this tries to create a new keyword. - void GenerateKeywordIfNecessary( - const ViewHostMsg_FrameNavigate_Params& params); - - // Data ---------------------------------------------------------------------- - - // The corresponding view. - scoped_ptr view_; - - // Manages creation and swapping of render views. - RenderViewHostManager render_manager_; - - // For testing, passed to new RenderViewHost managers. - RenderViewHostFactory* render_view_factory_; - - // Handles print preview and print job for this contents. - printing::PrintViewManager printing_; - - // Indicates whether we should notify about disconnection of this - // WebContents. 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 HistoryRequestMap; - HistoryRequestMap history_requests_; - - // System time at which the current load was started. - base::TimeTicks current_load_start_; - - // 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_; - - // SavePackage, lazily created. - scoped_refptr save_package_; - - // Tracks our pending CancelableRequests. This maps pending requests to - // page IDs so that we know whether a given callback still applies. The - // page ID -1 means no page ID was set. - CancelableRequestConsumerT cancelable_consumer_; - - // Whether the current URL is starred - bool is_starred_; - - // 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. - ScopedHandle message_box_active_; - - // AutofillManager, lazily created. - scoped_ptr autofill_manager_; - - // PasswordManager, lazily created. - scoped_ptr password_manager_; - - // PluginInstaller, lazily created. - scoped_ptr plugin_installer_; - - // Handles downloading favicons. - FavIconHelper fav_icon_helper_; - - // Dialog box used for choosing files to upload from file form fields. - scoped_refptr select_file_dialog_; - - // 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_; - - // 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. TODO(jungshik) : convert to std::string - std::wstring encoding_; - - PendingInstall pending_install_; - - // The last time that the download shelf was made visible. - base::TimeTicks last_download_shelf_show_; - - // The current load state and the URL associated with it. - net::LoadState load_state_; - std::wstring load_state_host_; - - // Non-null if we're displaying content for a web app. - scoped_refptr web_app_; - - DISALLOW_COPY_AND_ASSIGN(WebContents); -}; - -#endif // CHROME_BROWSER_WEB_CONTENTS_H_ diff --git a/chrome/browser/web_contents_unittest.cc b/chrome/browser/web_contents_unittest.cc deleted file mode 100644 index c3ba13e..0000000 --- a/chrome/browser/web_contents_unittest.cc +++ /dev/null @@ -1,1271 +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 "base/logging.h" -#include "chrome/browser/interstitial_page.h" -#include "chrome/browser/navigation_controller.h" -#include "chrome/browser/navigation_entry.h" -#include "chrome/browser/render_view_host.h" -#include "chrome/browser/render_widget_host_view.h" -#include "chrome/browser/web_contents.h" -#include "chrome/common/chrome_paths.h" -#include "chrome/common/ipc_channel.h" -#include "chrome/common/pref_service.h" -#include "chrome/common/render_messages.h" -#include "chrome/test/testing_profile.h" -#include "testing/gtest/include/gtest/gtest.h" - -static void InitNavigateParams(ViewHostMsg_FrameNavigate_Params* params, - int page_id, - const GURL& url) { - params->page_id = page_id; - params->url = url; - params->referrer = GURL::EmptyGURL(); - params->transition = PageTransition::TYPED; - params->redirects = std::vector(); - params->should_update_history = false; - params->searchable_form_url = GURL::EmptyGURL(); - params->searchable_form_element_name = std::wstring(); - params->searchable_form_encoding = std::string(); - params->password_form = PasswordForm(); - params->security_info = std::string(); - params->gesture = NavigationGestureUser; - params->is_post = false; -} - -// Subclass the RenderViewHost's view so that we can call Show(), etc., -// without having side-effects. -class TestRenderWidgetHostView : public RenderWidgetHostView { - public: - TestRenderWidgetHostView() : is_showing_(false) {} - - virtual RenderWidgetHost* GetRenderWidgetHost() const { return NULL; } - virtual void DidBecomeSelected() {} - virtual void WasHidden() {} - virtual void SetSize(const gfx::Size& size) {} - virtual HWND GetPluginHWND() { return NULL; } - virtual HANDLE ModalDialogEvent() { return NULL; } - virtual void ForwardMouseEventToRenderer(UINT message, - WPARAM wparam, - LPARAM lparam) {} - virtual void Focus() {} - virtual void Blur() {} - virtual bool HasFocus() { return true; } - virtual void AdvanceFocus(bool reverse) {} - virtual void Show() { is_showing_ = true; } - virtual void Hide() { is_showing_ = false; } - virtual gfx::Rect GetViewBounds() const { return gfx::Rect(); } - virtual void UpdateCursor(const WebCursor& cursor) {} - virtual void UpdateCursorIfOverSelf() {} - // Indicates if the page has finished loading. - virtual void SetIsLoading(bool is_loading) {} - virtual void IMEUpdateStatus(ViewHostMsg_ImeControl control, - const gfx::Rect& caret_rect) {} - virtual void DidPaintRect(const gfx::Rect& rect) {} - virtual void DidScrollRect(const gfx::Rect& rect, int dx, int dy) {} - virtual void RendererGone() {} - virtual void Destroy() {} - virtual void PrepareToDestroy() {} - virtual void SetTooltipText(const std::wstring& tooltip_text) {} - - bool is_showing() const { return is_showing_; } - - private: - bool is_showing_; -}; - -// Subclass RenderViewHost so that it does not create a process. -class TestRenderViewHost : public RenderViewHost { - public: - TestRenderViewHost( - SiteInstance* instance, - RenderViewHostDelegate* delegate, - int routing_id, - HANDLE modal_dialog_event) - : RenderViewHost(instance, delegate, routing_id, modal_dialog_event), - is_loading(false), - is_created(false), - immediate_before_unload(true), - delete_counter_(NULL) { - set_view(new TestRenderWidgetHostView()); - } - ~TestRenderViewHost() { - // Track the delete if we've been asked to. - if (delete_counter_) - ++*delete_counter_; - - // Since this isn't a traditional view, we have to delete it. - delete view_; - } - - // If set, *delete_counter is incremented when this object destructs. - void set_delete_counter(int* delete_counter) { - delete_counter_ = delete_counter; - } - - bool CreateRenderView() { - is_created = true; - return true; - } - - bool IsRenderViewLive() const { return is_created; } - - bool IsNavigationSuspended() { return navigations_suspended_; } - - void NavigateToEntry(const NavigationEntry& entry, bool is_reload) { - is_loading = true; - } - - void LoadAlternateHTMLString(const std::string& html_text, - bool new_navigation, - const GURL& display_url, - const std::string& security_info) { - is_loading = true; - } - - // Support for onbeforeunload, onunload - void FirePageBeforeUnload() { - is_waiting_for_unload_ack_ = true; - if (immediate_before_unload) - delegate()->ShouldClosePage(true); - } - void ClosePage(int new_render_process_host_id, int new_request_id) { - // Nothing to do here... This would cause a ClosePage_ACK to be sent to - // ResourceDispatcherHost, so we can simulate that manually. - } - void TestOnMsgShouldClose(bool proceed) { - OnMsgShouldCloseACK(proceed); - } - - bool is_loading; - bool is_created; - bool immediate_before_unload; - int* delete_counter_; -}; - -// Factory to create TestRenderViewHosts. -class TestRenderViewHostFactory : public RenderViewHostFactory { - public: - static TestRenderViewHostFactory* GetInstance() { - static TestRenderViewHostFactory instance; - return &instance; - } - - virtual RenderViewHost* CreateRenderViewHost( - SiteInstance* instance, - RenderViewHostDelegate* delegate, - int routing_id, - HANDLE modal_dialog_event) { - return new TestRenderViewHost( - instance, delegate, routing_id, modal_dialog_event); - } - - private: - TestRenderViewHostFactory() {} -}; - -// Subclass the TestingProfile so that it can return certain services we need. -class WebContentsTestingProfile : public TestingProfile { - public: - WebContentsTestingProfile() : TestingProfile() { } - - virtual PrefService* GetPrefs() { - if (!prefs_.get()) { - std::wstring source_path; - PathService::Get(chrome::DIR_TEST_DATA, &source_path); - file_util::AppendToPath(&source_path, L"profiles"); - file_util::AppendToPath(&source_path, L"chrome_prefs"); - file_util::AppendToPath(&source_path, L"Preferences"); - - prefs_.reset(new PrefService(source_path)); - Profile::RegisterUserPrefs(prefs_.get()); - browser::RegisterAllPrefs(prefs_.get(), prefs_.get()); - } - return prefs_.get(); - } -}; - -// Subclass WebContents to ensure it creates TestRenderViewHosts and does -// not do anything involving views. -class TestWebContents : public WebContents { - public: - TestWebContents(Profile* profile, SiteInstance* instance) - : WebContents(profile, - instance, - TestRenderViewHostFactory::GetInstance(), - MSG_ROUTING_NONE, - NULL), - transition_cross_site(false) {} - - // Accessors for interesting fields - TestRenderViewHost* rvh() { - return static_cast( - render_manager_.render_view_host_); - } - TestRenderViewHost* pending_rvh() { - return static_cast( - render_manager_.pending_render_view_host_); - } - - // State accessor. - bool cross_navigation_pending() { - return render_manager_.cross_navigation_pending_; - } - - // Ensure we create TestRenderViewHosts that don't spawn processes. - RenderViewHost* CreateRenderViewHost(SiteInstance* instance, - RenderViewHostDelegate* delegate, - int routing_id, - HANDLE modal_dialog_event) { - return new TestRenderViewHost( - instance, delegate, routing_id, modal_dialog_event); - } - - // Overrides WebContents::ShouldTransitionCrossSite so that we can test both - // alternatives without using command-line switches. - bool ShouldTransitionCrossSite() { return transition_cross_site; } - - // Promote DidNavigate to public. - void TestDidNavigate(TestRenderViewHost* render_view_host, - const ViewHostMsg_FrameNavigate_Params& params) { - DidNavigate(render_view_host, params); - render_view_host->is_loading = false; - } - - // Promote GetWebkitPrefs to public. - WebPreferences TestGetWebkitPrefs() { - return GetWebkitPrefs(); - } - - // Prevent interaction with views. - bool CreateRenderViewForRenderManager(RenderViewHost* render_view_host) { - // This will go to a TestRenderViewHost. - render_view_host->CreateRenderView(); - return true; - } - void UpdateRenderViewSizeForRenderManager() {} - - // Set by individual tests. - bool transition_cross_site; -}; - -class TestInterstitialPage : public InterstitialPage { - public: - enum InterstitialState { - UNDECIDED = 0, // No decision taken yet. - OKED, // Proceed was called. - CANCELED // DontProceed was called. - }; - - class Delegate { - public: - virtual void TestInterstitialPageDeleted( - TestInterstitialPage* interstitial) = 0; - }; - - // IMPORTANT NOTE: if you pass stack allocated values for |state| and - // |deleted| (like all interstitial related tests do at this point), make sure - // to create an instance of the TestInterstitialPageStateGuard class on the - // stack in your test. This will ensure that the TestInterstitialPage states - // are cleared when the test finishes. - // Not doing so will cause stack trashing if your test does not hide the - // interstitial, as in such a case it will be destroyed in the test TearDown - // method and will dereference the |deleted| local variable which by then is - // out of scope. - TestInterstitialPage(WebContents* tab, - bool new_navigation, - const GURL& url, - InterstitialState* state, - bool* deleted) - : InterstitialPage(tab, new_navigation, url), - state_(state), - deleted_(deleted), - command_received_count_(0), - delegate_(NULL) { - *state_ = UNDECIDED; - *deleted_ = false; - } - - virtual ~TestInterstitialPage() { - if (deleted_) - *deleted_ = true; - if (delegate_) - delegate_->TestInterstitialPageDeleted(this); - } - - virtual void DontProceed() { - if (state_) - *state_ = CANCELED; - InterstitialPage::DontProceed(); - } - virtual void Proceed() { - if (state_) - *state_ = OKED; - InterstitialPage::Proceed(); - } - - int command_received_count() const { - return command_received_count_; - } - - void TestDomOperationResponse(const std::string& json_string) { - DomOperationResponse(json_string, 1); - } - - void TestDidNavigate(int page_id, const GURL& url) { - ViewHostMsg_FrameNavigate_Params params; - InitNavigateParams(¶ms, page_id, url); - DidNavigate(render_view_host(), params); - } - - void TestRendererGone() { - RendererGone(render_view_host()); - } - - bool is_showing() const { - return static_cast(render_view_host()->view())-> - is_showing(); - } - - void ClearStates() { - state_ = NULL; - deleted_ = NULL; - delegate_ = NULL; - } - - void set_delegate(Delegate* delegate) { - delegate_ = delegate; - } - - protected: - virtual RenderViewHost* CreateRenderViewHost() { - return new TestRenderViewHost( - SiteInstance::CreateSiteInstance(tab()->profile()), - this, MSG_ROUTING_NONE, NULL); - } - - virtual void CommandReceived(const std::string& command) { - command_received_count_++; - } - - private: - InterstitialState* state_; - bool* deleted_; - int command_received_count_; - Delegate* delegate_; -}; - -class TestInterstitialPageStateGuard : public TestInterstitialPage::Delegate { - public: - explicit TestInterstitialPageStateGuard( - TestInterstitialPage* interstitial_page) - : interstitial_page_(interstitial_page) { - DCHECK(interstitial_page_); - interstitial_page_->set_delegate(this); - } - ~TestInterstitialPageStateGuard() { - if (interstitial_page_) - interstitial_page_->ClearStates(); - } - - virtual void TestInterstitialPageDeleted(TestInterstitialPage* interstitial) { - DCHECK(interstitial_page_ == interstitial); - interstitial_page_ = NULL; - } - - private: - TestInterstitialPage* interstitial_page_; -}; - -class WebContentsTest : public testing::Test { - public: - WebContentsTest() : contents(NULL) {} - - // testing::Test methods: - - virtual void SetUp() { - profile.reset(new WebContentsTestingProfile()); - - // This will be deleted when the WebContents goes away - SiteInstance* instance = SiteInstance::CreateSiteInstance(profile.get()); - - contents = new TestWebContents(profile.get(), instance); - contents->SetupController(profile.get()); - } - - virtual void TearDown() { - // This will delete the contents. - if (contents) - contents->CloseContents(); - - // Make sure that we flush any messages related to WebContents destruction - // before we destroy the profile. - MessageLoop::current()->RunAllPending(); - } - - void Navigate(int page_id, const GURL& url) { - DCHECK(contents); - ViewHostMsg_FrameNavigate_Params params; - InitNavigateParams(¶ms, page_id, url); - contents->TestDidNavigate(contents->rvh(), params); - } - - scoped_ptr profile; - TestWebContents* contents; - - private: - MessageLoopForUI message_loop_; -}; - -// Test to make sure that title updates get stripped of whitespace. -TEST_F(WebContentsTest, UpdateTitle) { - ViewHostMsg_FrameNavigate_Params params; - InitNavigateParams(¶ms, 0, GURL("about:blank")); - - NavigationController::LoadCommittedDetails details; - contents->controller()->RendererDidNavigate(params, &details); - - contents->UpdateTitle(contents->rvh(), 0, L" Lots O' Whitespace\n"); - EXPECT_EQ(std::wstring(L"Lots O' Whitespace"), contents->GetTitle()); -} - -// Test simple same-SiteInstance navigation. -TEST_F(WebContentsTest, SimpleNavigation) { - TestRenderViewHost* orig_rvh = contents->rvh(); - SiteInstance* instance1 = contents->GetSiteInstance(); - EXPECT_TRUE(contents->pending_rvh() == NULL); - EXPECT_FALSE(orig_rvh->is_loading); - - // Navigate to URL - const GURL url("http://www.google.com"); - contents->controller()->LoadURL(url, GURL(), PageTransition::TYPED); - EXPECT_FALSE(contents->cross_navigation_pending()); - EXPECT_TRUE(orig_rvh->is_loading); - EXPECT_EQ(instance1, orig_rvh->site_instance()); - // Controller's pending entry will have a NULL site instance until we assign - // it in DidNavigate. - EXPECT_TRUE( - contents->controller()->GetActiveEntry()->site_instance() == NULL); - - // DidNavigate from the page - ViewHostMsg_FrameNavigate_Params params; - InitNavigateParams(¶ms, 1, url); - contents->TestDidNavigate(orig_rvh, params); - EXPECT_FALSE(contents->cross_navigation_pending()); - EXPECT_EQ(orig_rvh, contents->render_view_host()); - EXPECT_EQ(instance1, orig_rvh->site_instance()); - // Controller's entry should now have the SiteInstance, or else we won't be - // able to find it later. - EXPECT_EQ(instance1, - contents->controller()->GetActiveEntry()->site_instance()); -} - -// Test that navigating across a site boundary creates a new RenderViewHost -// with a new SiteInstance. Going back should do the same. -TEST_F(WebContentsTest, CrossSiteBoundaries) { - contents->transition_cross_site = true; - TestRenderViewHost* orig_rvh = contents->rvh(); - int orig_rvh_delete_count = 0; - orig_rvh->set_delete_counter(&orig_rvh_delete_count); - SiteInstance* instance1 = contents->GetSiteInstance(); - - // Navigate to URL. First URL should use first RenderViewHost. - const GURL url("http://www.google.com"); - contents->controller()->LoadURL(url, GURL(), PageTransition::TYPED); - ViewHostMsg_FrameNavigate_Params params1; - InitNavigateParams(¶ms1, 1, url); - contents->TestDidNavigate(orig_rvh, params1); - - EXPECT_FALSE(contents->cross_navigation_pending()); - EXPECT_EQ(orig_rvh, contents->render_view_host()); - - // Navigate to new site - const GURL url2("http://www.yahoo.com"); - contents->controller()->LoadURL(url2, GURL(), PageTransition::TYPED); - EXPECT_TRUE(contents->cross_navigation_pending()); - TestRenderViewHost* pending_rvh = contents->pending_rvh(); - int pending_rvh_delete_count = 0; - pending_rvh->set_delete_counter(&pending_rvh_delete_count); - - // DidNavigate from the pending page - ViewHostMsg_FrameNavigate_Params params2; - InitNavigateParams(¶ms2, 1, url2); - contents->TestDidNavigate(pending_rvh, params2); - SiteInstance* instance2 = contents->GetSiteInstance(); - - EXPECT_FALSE(contents->cross_navigation_pending()); - EXPECT_EQ(pending_rvh, contents->render_view_host()); - EXPECT_NE(instance1, instance2); - EXPECT_TRUE(contents->pending_rvh() == NULL); - EXPECT_EQ(orig_rvh_delete_count, 1); - - // Going back should switch SiteInstances again. The first SiteInstance is - // stored in the NavigationEntry, so it should be the same as at the start. - contents->controller()->GoBack(); - TestRenderViewHost* goback_rvh = contents->pending_rvh(); - EXPECT_TRUE(contents->cross_navigation_pending()); - - // DidNavigate from the back action - contents->TestDidNavigate(goback_rvh, params1); - EXPECT_FALSE(contents->cross_navigation_pending()); - EXPECT_EQ(goback_rvh, contents->render_view_host()); - EXPECT_EQ(pending_rvh_delete_count, 1); - EXPECT_EQ(instance1, contents->GetSiteInstance()); -} - -// Test that navigating across a site boundary after a crash creates a new -// RVH without requiring a cross-site transition (i.e., PENDING state). -TEST_F(WebContentsTest, CrossSiteBoundariesAfterCrash) { - contents->transition_cross_site = true; - TestRenderViewHost* orig_rvh = contents->rvh(); - int orig_rvh_delete_count = 0; - orig_rvh->set_delete_counter(&orig_rvh_delete_count); - SiteInstance* instance1 = contents->GetSiteInstance(); - - // Navigate to URL. First URL should use first RenderViewHost. - const GURL url("http://www.google.com"); - contents->controller()->LoadURL(url, GURL(), PageTransition::TYPED); - ViewHostMsg_FrameNavigate_Params params1; - InitNavigateParams(¶ms1, 1, url); - contents->TestDidNavigate(orig_rvh, params1); - - EXPECT_FALSE(contents->cross_navigation_pending()); - EXPECT_EQ(orig_rvh, contents->render_view_host()); - - // Crash the renderer. - orig_rvh->is_created = false; - - // Navigate to new site. We should not go into PENDING. - const GURL url2("http://www.yahoo.com"); - contents->controller()->LoadURL(url2, GURL(), PageTransition::TYPED); - TestRenderViewHost* new_rvh = contents->rvh(); - EXPECT_FALSE(contents->cross_navigation_pending()); - EXPECT_TRUE(contents->pending_rvh() == NULL); - EXPECT_NE(orig_rvh, new_rvh); - EXPECT_EQ(orig_rvh_delete_count, 1); - - // DidNavigate from the new page - ViewHostMsg_FrameNavigate_Params params2; - InitNavigateParams(¶ms2, 1, url2); - contents->TestDidNavigate(new_rvh, params2); - SiteInstance* instance2 = contents->GetSiteInstance(); - - EXPECT_FALSE(contents->cross_navigation_pending()); - EXPECT_EQ(new_rvh, contents->render_view_host()); - EXPECT_NE(instance1, instance2); - EXPECT_TRUE(contents->pending_rvh() == NULL); -} - -// Test that opening a new tab in the same SiteInstance and then navigating -// both tabs to a new site will place both tabs in a single SiteInstance. -TEST_F(WebContentsTest, NavigateTwoTabsCrossSite) { - contents->transition_cross_site = true; - TestRenderViewHost* orig_rvh = contents->rvh(); - SiteInstance* instance1 = contents->GetSiteInstance(); - - // Navigate to URL. First URL should use first RenderViewHost. - const GURL url("http://www.google.com"); - contents->controller()->LoadURL(url, GURL(), PageTransition::TYPED); - ViewHostMsg_FrameNavigate_Params params1; - InitNavigateParams(¶ms1, 1, url); - contents->TestDidNavigate(orig_rvh, params1); - - // Open a new tab with the same SiteInstance, navigated to the same site. - TestWebContents* contents2 = new TestWebContents(profile.get(), instance1); - params1.page_id = 2; // Need this since the site instance is the same (which - // is the scope of page IDs) and we want to consider - // this a new page. - contents2->transition_cross_site = true; - contents2->SetupController(profile.get()); - contents2->controller()->LoadURL(url, GURL(), PageTransition::TYPED); - contents2->TestDidNavigate(contents2->rvh(), params1); - - // Navigate first tab to a new site - const GURL url2a("http://www.yahoo.com"); - contents->controller()->LoadURL(url2a, GURL(), PageTransition::TYPED); - TestRenderViewHost* pending_rvh_a = contents->pending_rvh(); - ViewHostMsg_FrameNavigate_Params params2a; - InitNavigateParams(¶ms2a, 1, url2a); - contents->TestDidNavigate(pending_rvh_a, params2a); - SiteInstance* instance2a = contents->GetSiteInstance(); - EXPECT_NE(instance1, instance2a); - - // Navigate second tab to the same site as the first tab - const GURL url2b("http://mail.yahoo.com"); - contents2->controller()->LoadURL(url2b, GURL(), PageTransition::TYPED); - TestRenderViewHost* pending_rvh_b = contents2->pending_rvh(); - EXPECT_TRUE(pending_rvh_b != NULL); - EXPECT_TRUE(contents2->cross_navigation_pending()); - - // NOTE(creis): We used to be in danger of showing a sad tab page here if the - // second tab hadn't navigated somewhere first (bug 1145430). That case is - // now covered by the CrossSiteBoundariesAfterCrash test. - - ViewHostMsg_FrameNavigate_Params params2b; - InitNavigateParams(¶ms2b, 2, url2b); - contents2->TestDidNavigate(pending_rvh_b, params2b); - SiteInstance* instance2b = contents2->GetSiteInstance(); - EXPECT_NE(instance1, instance2b); - - // Both tabs should now be in the same SiteInstance. - EXPECT_EQ(instance2a, instance2b); - - contents2->CloseContents(); -} - -// Tests that WebContents uses the current URL, not the SiteInstance's site, to -// determine whether a navigation is cross-site. -TEST_F(WebContentsTest, CrossSiteComparesAgainstCurrentPage) { - contents->transition_cross_site = true; - TestRenderViewHost* orig_rvh = contents->rvh(); - SiteInstance* instance1 = contents->GetSiteInstance(); - - // Navigate to URL. - const GURL url("http://www.google.com"); - contents->controller()->LoadURL(url, GURL(), PageTransition::TYPED); - ViewHostMsg_FrameNavigate_Params params1; - InitNavigateParams(¶ms1, 1, url); - contents->TestDidNavigate(orig_rvh, params1); - - // Open a related tab to a second site. - TestWebContents* contents2 = new TestWebContents(profile.get(), instance1); - contents2->transition_cross_site = true; - contents2->SetupController(profile.get()); - const GURL url2("http://www.yahoo.com"); - contents2->controller()->LoadURL(url2, GURL(), PageTransition::TYPED); - // The first RVH in contents2 isn't live yet, so we shortcut the cross site - // pending. - TestRenderViewHost* rvh2 = contents2->rvh(); - EXPECT_FALSE(contents2->cross_navigation_pending()); - ViewHostMsg_FrameNavigate_Params params2; - InitNavigateParams(¶ms2, 2, url2); - contents2->TestDidNavigate(rvh2, params2); - SiteInstance* instance2 = contents2->GetSiteInstance(); - EXPECT_NE(instance1, instance2); - EXPECT_FALSE(contents2->cross_navigation_pending()); - - // Simulate a link click in first tab to second site. Doesn't switch - // SiteInstances, because we don't intercept WebKit navigations. - ViewHostMsg_FrameNavigate_Params params3; - InitNavigateParams(¶ms3, 2, url2); - contents->TestDidNavigate(orig_rvh, params3); - SiteInstance* instance3 = contents->GetSiteInstance(); - EXPECT_EQ(instance1, instance3); - EXPECT_FALSE(contents->cross_navigation_pending()); - - // Navigate to the new site. Doesn't switch SiteInstancees, because we - // compare against the current URL, not the SiteInstance's site. - const GURL url3("http://mail.yahoo.com"); - contents->controller()->LoadURL(url3, GURL(), PageTransition::TYPED); - EXPECT_FALSE(contents->cross_navigation_pending()); - ViewHostMsg_FrameNavigate_Params params4; - InitNavigateParams(¶ms4, 3, url3); - contents->TestDidNavigate(orig_rvh, params4); - SiteInstance* instance4 = contents->GetSiteInstance(); - EXPECT_EQ(instance1, instance4); - - contents2->CloseContents(); -} - -// Test that the onbeforeunload and onunload handlers run when navigating -// across site boundaries. -TEST_F(WebContentsTest, CrossSiteUnloadHandlers) { - contents->transition_cross_site = true; - TestRenderViewHost* orig_rvh = contents->rvh(); - SiteInstance* instance1 = contents->GetSiteInstance(); - - // Navigate to URL. First URL should use first RenderViewHost. - const GURL url("http://www.google.com"); - contents->controller()->LoadURL(url, GURL(), PageTransition::TYPED); - ViewHostMsg_FrameNavigate_Params params1; - InitNavigateParams(¶ms1, 1, url); - contents->TestDidNavigate(orig_rvh, params1); - EXPECT_FALSE(contents->cross_navigation_pending()); - EXPECT_EQ(orig_rvh, contents->render_view_host()); - - // Navigate to new site, but simulate an onbeforeunload denial. - const GURL url2("http://www.yahoo.com"); - orig_rvh->immediate_before_unload = false; - contents->controller()->LoadURL(url2, GURL(), PageTransition::TYPED); - orig_rvh->TestOnMsgShouldClose(false); - EXPECT_FALSE(contents->cross_navigation_pending()); - EXPECT_EQ(orig_rvh, contents->render_view_host()); - - // Navigate again, but simulate an onbeforeunload approval. - contents->controller()->LoadURL(url2, GURL(), PageTransition::TYPED); - orig_rvh->TestOnMsgShouldClose(true); - EXPECT_TRUE(contents->cross_navigation_pending()); - TestRenderViewHost* pending_rvh = contents->pending_rvh(); - - // We won't hear DidNavigate until the onunload handler has finished running. - // (No way to simulate that here, but it involves a call from RDH to - // WebContents::OnCrossSiteResponse.) - - // DidNavigate from the pending page - ViewHostMsg_FrameNavigate_Params params2; - InitNavigateParams(¶ms2, 1, url2); - contents->TestDidNavigate(pending_rvh, params2); - SiteInstance* instance2 = contents->GetSiteInstance(); - EXPECT_FALSE(contents->cross_navigation_pending()); - EXPECT_EQ(pending_rvh, contents->render_view_host()); - EXPECT_NE(instance1, instance2); - EXPECT_TRUE(contents->pending_rvh() == NULL); -} - -// Test that NavigationEntries have the correct content state after going -// forward and back. Prevents regression for bug 1116137. -TEST_F(WebContentsTest, NavigationEntryContentState) { - TestRenderViewHost* orig_rvh = contents->rvh(); - - // Navigate to URL. There should be no committed entry yet. - const GURL url("http://www.google.com"); - contents->controller()->LoadURL(url, GURL(), PageTransition::TYPED); - NavigationEntry* entry = contents->controller()->GetLastCommittedEntry(); - EXPECT_TRUE(entry == NULL); - - // Committed entry should have content state after DidNavigate. - ViewHostMsg_FrameNavigate_Params params1; - InitNavigateParams(¶ms1, 1, url); - contents->TestDidNavigate(orig_rvh, params1); - entry = contents->controller()->GetLastCommittedEntry(); - EXPECT_FALSE(entry->content_state().empty()); - - // Navigate to same site. - const GURL url2("http://images.google.com"); - contents->controller()->LoadURL(url2, GURL(), PageTransition::TYPED); - entry = contents->controller()->GetLastCommittedEntry(); - EXPECT_FALSE(entry->content_state().empty()); - - // Committed entry should have content state after DidNavigate. - ViewHostMsg_FrameNavigate_Params params2; - InitNavigateParams(¶ms2, 2, url2); - contents->TestDidNavigate(orig_rvh, params2); - entry = contents->controller()->GetLastCommittedEntry(); - EXPECT_FALSE(entry->content_state().empty()); - - // Now go back. Committed entry should still have content state. - contents->controller()->GoBack(); - contents->TestDidNavigate(orig_rvh, params1); - entry = contents->controller()->GetLastCommittedEntry(); - EXPECT_FALSE(entry->content_state().empty()); -} - -// Test that NavigationEntries have the correct content state after opening -// a new window to about:blank. Prevents regression for bug 1116137. -TEST_F(WebContentsTest, NavigationEntryContentStateNewWindow) { - TestRenderViewHost* orig_rvh = contents->rvh(); - - // When opening a new window, it is navigated to about:blank internally. - // Currently, this results in two DidNavigate events. - const GURL url("about:blank"); - ViewHostMsg_FrameNavigate_Params params1; - InitNavigateParams(¶ms1, 1, url); - contents->TestDidNavigate(orig_rvh, params1); - contents->TestDidNavigate(orig_rvh, params1); - - // Should have a content state here. - NavigationEntry* entry = contents->controller()->GetLastCommittedEntry(); - EXPECT_FALSE(entry->content_state().empty()); -} - -// Tests to see that webkit preferences are properly loaded and copied over -// to a WebPreferences object. -TEST_F(WebContentsTest, WebKitPrefs) { - WebPreferences webkit_prefs = contents->TestGetWebkitPrefs(); - - // These values have been overridden by the profile preferences. - EXPECT_EQ(L"UTF-8", webkit_prefs.default_encoding); - EXPECT_EQ(20, webkit_prefs.default_font_size); - EXPECT_EQ(false, webkit_prefs.text_areas_are_resizable); - EXPECT_EQ(true, webkit_prefs.uses_universal_detector); - - // These should still be the default values. - EXPECT_EQ(L"Times New Roman", webkit_prefs.standard_font_family); - EXPECT_EQ(true, webkit_prefs.javascript_enabled); -} - -//////////////////////////////////////////////////////////////////////////////// -// Interstitial Tests -//////////////////////////////////////////////////////////////////////////////// - -// Test navigating to a page (with the navigation initiated from the browser, -// as when a URL is typed in the location bar) that shows an interstitial and -// creates a new navigation entry, then hiding it without proceeding. -TEST_F(WebContentsTest, - ShowInterstitialFromBrowserWithNewNavigationDontProceed) { - // Navigate to a page. - GURL url1("http://www.google.com"); - Navigate(1, url1); - EXPECT_EQ(1, contents->controller()->GetEntryCount()); - - // Initiate a browser navigation that will trigger the interstitial - contents->controller()->LoadURL(GURL("http://www.evil.com"), GURL(), - PageTransition::TYPED); - - // Show an interstitial. - TestInterstitialPage::InterstitialState state = - TestInterstitialPage::UNDECIDED; - bool deleted = false; - GURL url2("http://interstitial"); - TestInterstitialPage* interstitial = - new TestInterstitialPage(contents, true, url2, &state, &deleted); - TestInterstitialPageStateGuard state_guard(interstitial); - interstitial->Show(); - // The interstitial should not show until its navigation has committed. - EXPECT_FALSE(interstitial->is_showing()); - EXPECT_FALSE(contents->showing_interstitial_page()); - EXPECT_TRUE(contents->interstitial_page() == NULL); - // Let's commit the interstitial navigation. - interstitial->TestDidNavigate(1, url2); - EXPECT_TRUE(interstitial->is_showing()); - EXPECT_TRUE(contents->showing_interstitial_page()); - EXPECT_TRUE(contents->interstitial_page() == interstitial); - NavigationEntry* entry = contents->controller()->GetActiveEntry(); - ASSERT_TRUE(entry != NULL); - EXPECT_TRUE(entry->url() == url2); - - // Now don't proceed. - interstitial->DontProceed(); - EXPECT_TRUE(deleted); - EXPECT_EQ(TestInterstitialPage::CANCELED, state); - EXPECT_FALSE(contents->showing_interstitial_page()); - EXPECT_TRUE(contents->interstitial_page() == NULL); - entry = contents->controller()->GetActiveEntry(); - ASSERT_TRUE(entry != NULL); - EXPECT_TRUE(entry->url() == url1); - EXPECT_EQ(1, contents->controller()->GetEntryCount()); -} - -// Test navigating to a page (with the navigation initiated from the renderer, -// as when clicking on a link in the page) that shows an interstitial and -// creates a new navigation entry, then hiding it without proceeding. -TEST_F(WebContentsTest, - ShowInterstitiaFromRendererlWithNewNavigationDontProceed) { - // Navigate to a page. - GURL url1("http://www.google.com"); - Navigate(1, url1); - EXPECT_EQ(1, contents->controller()->GetEntryCount()); - - // Show an interstitial (no pending entry, the interstitial would have been - // triggered by clicking on a link). - TestInterstitialPage::InterstitialState state = - TestInterstitialPage::UNDECIDED; - bool deleted = false; - GURL url2("http://interstitial"); - TestInterstitialPage* interstitial = - new TestInterstitialPage(contents, true, url2, &state, &deleted); - TestInterstitialPageStateGuard state_guard(interstitial); - interstitial->Show(); - // The interstitial should not show until its navigation has committed. - EXPECT_FALSE(interstitial->is_showing()); - EXPECT_FALSE(contents->showing_interstitial_page()); - EXPECT_TRUE(contents->interstitial_page() == NULL); - // Let's commit the interstitial navigation. - interstitial->TestDidNavigate(1, url2); - EXPECT_TRUE(interstitial->is_showing()); - EXPECT_TRUE(contents->showing_interstitial_page()); - EXPECT_TRUE(contents->interstitial_page() == interstitial); - NavigationEntry* entry = contents->controller()->GetActiveEntry(); - ASSERT_TRUE(entry != NULL); - EXPECT_TRUE(entry->url() == url2); - - // Now don't proceed. - interstitial->DontProceed(); - EXPECT_TRUE(deleted); - EXPECT_EQ(TestInterstitialPage::CANCELED, state); - EXPECT_FALSE(contents->showing_interstitial_page()); - EXPECT_TRUE(contents->interstitial_page() == NULL); - entry = contents->controller()->GetActiveEntry(); - ASSERT_TRUE(entry != NULL); - EXPECT_TRUE(entry->url() == url1); - EXPECT_EQ(1, contents->controller()->GetEntryCount()); -} - -// Test navigating to a page that shows an interstitial without creating a new -// navigation entry (this happens when the interstitial is triggered by a -// sub-resource in the page), then hiding it without proceeding. -TEST_F(WebContentsTest, ShowInterstitialNoNewNavigationDontProceed) { - // Navigate to a page. - GURL url1("http://www.google.com"); - Navigate(1, url1); - EXPECT_EQ(1, contents->controller()->GetEntryCount()); - - // Show an interstitial. - TestInterstitialPage::InterstitialState state = - TestInterstitialPage::UNDECIDED; - bool deleted = false; - GURL url2("http://interstitial"); - TestInterstitialPage* interstitial = - new TestInterstitialPage(contents, false, url2, &state, &deleted); - TestInterstitialPageStateGuard state_guard(interstitial); - interstitial->Show(); - // The interstitial should not show until its navigation has committed. - EXPECT_FALSE(interstitial->is_showing()); - EXPECT_FALSE(contents->showing_interstitial_page()); - EXPECT_TRUE(contents->interstitial_page() == NULL); - // Let's commit the interstitial navigation. - interstitial->TestDidNavigate(1, url2); - EXPECT_TRUE(interstitial->is_showing()); - EXPECT_TRUE(contents->showing_interstitial_page()); - EXPECT_TRUE(contents->interstitial_page() == interstitial); - NavigationEntry* entry = contents->controller()->GetActiveEntry(); - ASSERT_TRUE(entry != NULL); - // The URL specified to the interstitial should have been ignored. - EXPECT_TRUE(entry->url() == url1); - - // Now don't proceed. - interstitial->DontProceed(); - EXPECT_TRUE(deleted); - EXPECT_EQ(TestInterstitialPage::CANCELED, state); - EXPECT_FALSE(contents->showing_interstitial_page()); - EXPECT_TRUE(contents->interstitial_page() == NULL); - entry = contents->controller()->GetActiveEntry(); - ASSERT_TRUE(entry != NULL); - EXPECT_TRUE(entry->url() == url1); - EXPECT_EQ(1, contents->controller()->GetEntryCount()); -} - -// Test navigating to a page (with the navigation initiated from the browser, -// as when a URL is typed in the location bar) that shows an interstitial and -// creates a new navigation entry, then proceeding. -TEST_F(WebContentsTest, - ShowInterstitialFromBrowserNewNavigationProceed) { - // Navigate to a page. - GURL url1("http://www.google.com"); - Navigate(1, url1); - EXPECT_EQ(1, contents->controller()->GetEntryCount()); - - // Initiate a browser navigation that will trigger the interstitial - contents->controller()->LoadURL(GURL("http://www.evil.com"), GURL(), - PageTransition::TYPED); - - // Show an interstitial. - TestInterstitialPage::InterstitialState state = - TestInterstitialPage::UNDECIDED; - bool deleted = false; - GURL url2("http://interstitial"); - TestInterstitialPage* interstitial = - new TestInterstitialPage(contents, true, url2, &state, &deleted); - TestInterstitialPageStateGuard state_guard(interstitial); - interstitial->Show(); - // The interstitial should not show until its navigation has committed. - EXPECT_FALSE(interstitial->is_showing()); - EXPECT_FALSE(contents->showing_interstitial_page()); - EXPECT_TRUE(contents->interstitial_page() == NULL); - // Let's commit the interstitial navigation. - interstitial->TestDidNavigate(1, url2); - EXPECT_TRUE(interstitial->is_showing()); - EXPECT_TRUE(contents->showing_interstitial_page()); - EXPECT_TRUE(contents->interstitial_page() == interstitial); - NavigationEntry* entry = contents->controller()->GetActiveEntry(); - ASSERT_TRUE(entry != NULL); - EXPECT_TRUE(entry->url() == url2); - - // Then proceed. - interstitial->Proceed(); - // The interstitial should show until the new navigation commits. - ASSERT_FALSE(deleted); - EXPECT_EQ(TestInterstitialPage::OKED, state); - EXPECT_TRUE(contents->showing_interstitial_page()); - EXPECT_TRUE(contents->interstitial_page() == interstitial); - - // Simulate the navigation to the page, that's when the interstitial gets - // hidden. - GURL url3("http://www.thepage.com"); - Navigate(2, url3); - - EXPECT_TRUE(deleted); - EXPECT_FALSE(contents->showing_interstitial_page()); - EXPECT_TRUE(contents->interstitial_page() == NULL); - entry = contents->controller()->GetActiveEntry(); - ASSERT_TRUE(entry != NULL); - EXPECT_TRUE(entry->url() == url3); - - EXPECT_EQ(2, contents->controller()->GetEntryCount()); -} - -// Test navigating to a page (with the navigation initiated from the renderer, -// as when clicking on a link in the page) that shows an interstitial and -// creates a new navigation entry, then proceeding. -TEST_F(WebContentsTest, - ShowInterstitialFromRendererNewNavigationProceed) { - // Navigate to a page. - GURL url1("http://www.google.com"); - Navigate(1, url1); - EXPECT_EQ(1, contents->controller()->GetEntryCount()); - - // Show an interstitial. - TestInterstitialPage::InterstitialState state = - TestInterstitialPage::UNDECIDED; - bool deleted = false; - GURL url2("http://interstitial"); - TestInterstitialPage* interstitial = - new TestInterstitialPage(contents, true, url2, &state, &deleted); - TestInterstitialPageStateGuard state_guard(interstitial); - interstitial->Show(); - // The interstitial should not show until its navigation has committed. - EXPECT_FALSE(interstitial->is_showing()); - EXPECT_FALSE(contents->showing_interstitial_page()); - EXPECT_TRUE(contents->interstitial_page() == NULL); - // Let's commit the interstitial navigation. - interstitial->TestDidNavigate(1, url2); - EXPECT_TRUE(interstitial->is_showing()); - EXPECT_TRUE(contents->showing_interstitial_page()); - EXPECT_TRUE(contents->interstitial_page() == interstitial); - NavigationEntry* entry = contents->controller()->GetActiveEntry(); - ASSERT_TRUE(entry != NULL); - EXPECT_TRUE(entry->url() == url2); - - // Then proceed. - interstitial->Proceed(); - // The interstitial should show until the new navigation commits. - ASSERT_FALSE(deleted); - EXPECT_EQ(TestInterstitialPage::OKED, state); - EXPECT_TRUE(contents->showing_interstitial_page()); - EXPECT_TRUE(contents->interstitial_page() == interstitial); - - // Simulate the navigation to the page, that's when the interstitial gets - // hidden. - GURL url3("http://www.thepage.com"); - Navigate(2, url3); - - EXPECT_TRUE(deleted); - EXPECT_FALSE(contents->showing_interstitial_page()); - EXPECT_TRUE(contents->interstitial_page() == NULL); - entry = contents->controller()->GetActiveEntry(); - ASSERT_TRUE(entry != NULL); - EXPECT_TRUE(entry->url() == url3); - - EXPECT_EQ(2, contents->controller()->GetEntryCount()); -} - -// Test navigating to a page that shows an interstitial without creating a new -// navigation entry (this happens when the interstitial is triggered by a -// sub-resource in the page), then proceeding. -TEST_F(WebContentsTest, ShowInterstitialNoNewNavigationProceed) { - // Navigate to a page so we have a navigation entry in the controller. - GURL url1("http://www.google.com"); - Navigate(1, url1); - EXPECT_EQ(1, contents->controller()->GetEntryCount()); - - // Show an interstitial. - TestInterstitialPage::InterstitialState state = - TestInterstitialPage::UNDECIDED; - bool deleted = false; - GURL url2("http://interstitial"); - TestInterstitialPage* interstitial = - new TestInterstitialPage(contents, false, url2, &state, &deleted); - TestInterstitialPageStateGuard state_guard(interstitial); - interstitial->Show(); - // The interstitial should not show until its navigation has committed. - EXPECT_FALSE(interstitial->is_showing()); - EXPECT_FALSE(contents->showing_interstitial_page()); - EXPECT_TRUE(contents->interstitial_page() == NULL); - // Let's commit the interstitial navigation. - interstitial->TestDidNavigate(1, url2); - EXPECT_TRUE(interstitial->is_showing()); - EXPECT_TRUE(contents->showing_interstitial_page()); - EXPECT_TRUE(contents->interstitial_page() == interstitial); - NavigationEntry* entry = contents->controller()->GetActiveEntry(); - ASSERT_TRUE(entry != NULL); - // The URL specified to the interstitial should have been ignored. - EXPECT_TRUE(entry->url() == url1); - - // Then proceed. - interstitial->Proceed(); - // Since this is not a new navigation, the previous page is dismissed right - // away and shows the original page. - EXPECT_TRUE(deleted); - EXPECT_EQ(TestInterstitialPage::OKED, state); - EXPECT_FALSE(contents->showing_interstitial_page()); - EXPECT_TRUE(contents->interstitial_page() == NULL); - entry = contents->controller()->GetActiveEntry(); - ASSERT_TRUE(entry != NULL); - EXPECT_TRUE(entry->url() == url1); - - EXPECT_EQ(1, contents->controller()->GetEntryCount()); -} - -// Test navigating to a page that shows an interstitial, then navigating away. -TEST_F(WebContentsTest, ShowInterstitialThenNavigate) { - // Show interstitial. - TestInterstitialPage::InterstitialState state = - TestInterstitialPage::UNDECIDED; - bool deleted = false; - GURL url("http://interstitial"); - TestInterstitialPage* interstitial = - new TestInterstitialPage(contents, true, url, &state, &deleted); - TestInterstitialPageStateGuard state_guard(interstitial); - interstitial->Show(); - interstitial->TestDidNavigate(1, url); - - // While interstitial showing, navigate to a new URL. - const GURL url2("http://www.yahoo.com"); - Navigate(1, url2); - - EXPECT_TRUE(deleted); - EXPECT_EQ(TestInterstitialPage::CANCELED, state); -} - -// Test navigating to a page that shows an interstitial, then close the tab. -TEST_F(WebContentsTest, ShowInterstitialThenCloseTab) { - // Show interstitial. - TestInterstitialPage::InterstitialState state = - TestInterstitialPage::UNDECIDED; - bool deleted = false; - GURL url("http://interstitial"); - TestInterstitialPage* interstitial = - new TestInterstitialPage(contents, true, url, &state, &deleted); - TestInterstitialPageStateGuard state_guard(interstitial); - interstitial->Show(); - interstitial->TestDidNavigate(1, url); - - // Now close the tab. - contents->CloseContents(); - contents = NULL; // So we don't detroy it again on TearDown. - EXPECT_TRUE(deleted); - EXPECT_EQ(TestInterstitialPage::CANCELED, state); -} - -// Test that after Proceed is called and an interstitial is still shown, no more -// commands get executed. -TEST_F(WebContentsTest, ShowInterstitialProceedMultipleCommands) { - // Navigate to a page so we have a navigation entry in the controller. - GURL url1("http://www.google.com"); - Navigate(1, url1); - EXPECT_EQ(1, contents->controller()->GetEntryCount()); - - // Show an interstitial. - TestInterstitialPage::InterstitialState state = - TestInterstitialPage::UNDECIDED; - bool deleted = false; - GURL url2("http://interstitial"); - TestInterstitialPage* interstitial = - new TestInterstitialPage(contents, true, url2, &state, &deleted); - TestInterstitialPageStateGuard state_guard(interstitial); - interstitial->Show(); - interstitial->TestDidNavigate(1, url2); - - // Run a command. - EXPECT_EQ(0, interstitial->command_received_count()); - interstitial->TestDomOperationResponse("toto"); - EXPECT_EQ(1, interstitial->command_received_count()); - - // Then proceed. - interstitial->Proceed(); - ASSERT_FALSE(deleted); - - // While the navigation to the new page is pending, send other commands, they - // should be ignored. - interstitial->TestDomOperationResponse("hello"); - interstitial->TestDomOperationResponse("hi"); - EXPECT_EQ(1, interstitial->command_received_count()); -} - -// Test showing an interstitial while another interstitial is already showing. -TEST_F(WebContentsTest, ShowInterstitialOnInterstitial) { - // Navigate to a page so we have a navigation entry in the controller. - GURL start_url("http://www.google.com"); - Navigate(1, start_url); - EXPECT_EQ(1, contents->controller()->GetEntryCount()); - - // Show an interstitial. - TestInterstitialPage::InterstitialState state1 = - TestInterstitialPage::UNDECIDED; - bool deleted1 = false; - GURL url1("http://interstitial1"); - TestInterstitialPage* interstitial1 = - new TestInterstitialPage(contents, true, url1, &state1, &deleted1); - TestInterstitialPageStateGuard state_guard1(interstitial1); - interstitial1->Show(); - interstitial1->TestDidNavigate(1, url1); - - // Now show another interstitial. - TestInterstitialPage::InterstitialState state2 = - TestInterstitialPage::UNDECIDED; - bool deleted2 = false; - GURL url2("http://interstitial2"); - TestInterstitialPage* interstitial2 = - new TestInterstitialPage(contents, true, url2, &state2, &deleted2); - TestInterstitialPageStateGuard state_guard2(interstitial2); - interstitial2->Show(); - interstitial2->TestDidNavigate(1, url2); - - // Showing interstitial2 should have caused interstitial1 to go away. - EXPECT_TRUE(deleted1); - EXPECT_EQ(TestInterstitialPage::CANCELED, state1); - - // Let's make sure interstitial2 is working as intended. - ASSERT_FALSE(deleted2); - EXPECT_EQ(TestInterstitialPage::UNDECIDED, state2); - interstitial2->Proceed(); - GURL landing_url("http://www.thepage.com"); - Navigate(2, landing_url); - - EXPECT_TRUE(deleted2); - EXPECT_FALSE(contents->showing_interstitial_page()); - EXPECT_TRUE(contents->interstitial_page() == NULL); - NavigationEntry* entry = contents->controller()->GetActiveEntry(); - ASSERT_TRUE(entry != NULL); - EXPECT_TRUE(entry->url() == landing_url); - EXPECT_EQ(2, contents->controller()->GetEntryCount()); -} - -// Test that navigating away from an interstitial while it's loading cause it -// not to show. -TEST_F(WebContentsTest, NavigateBeforeInterstitialShows) { - // Show an interstitial. - TestInterstitialPage::InterstitialState state = - TestInterstitialPage::UNDECIDED; - bool deleted = false; - GURL interstitial_url("http://interstitial"); - TestInterstitialPage* interstitial = - new TestInterstitialPage(contents, true, interstitial_url, - &state, &deleted); - TestInterstitialPageStateGuard state_guard(interstitial); - interstitial->Show(); - - // Let's simulate a navigation initiated from the browser before the - // interstitial finishes loading. - const GURL url("http://www.google.com"); - contents->controller()->LoadURL(url, GURL(), PageTransition::TYPED); - ASSERT_FALSE(deleted); - EXPECT_FALSE(interstitial->is_showing()); - - // Now let's make the interstitial navigation commit. - interstitial->TestDidNavigate(1, interstitial_url); - - // After it loaded the interstitial should be gone. - EXPECT_TRUE(deleted); - EXPECT_EQ(TestInterstitialPage::CANCELED, state); -} - -// Test showing an interstitial and have its renderer crash. -TEST_F(WebContentsTest, InterstitialCrasher) { - // Show an interstitial. - TestInterstitialPage::InterstitialState state = - TestInterstitialPage::UNDECIDED; - bool deleted = false; - GURL url("http://interstitial"); - TestInterstitialPage* interstitial = - new TestInterstitialPage(contents, true, url, &state, &deleted); - TestInterstitialPageStateGuard state_guard(interstitial); - interstitial->Show(); - // Simulate a renderer crash before the interstitial is shown. - interstitial->TestRendererGone(); - // The interstitial should have been dismissed. - EXPECT_TRUE(deleted); - EXPECT_EQ(TestInterstitialPage::CANCELED, state); - - // Now try again but this time crash the intersitial after it was shown. - interstitial = - new TestInterstitialPage(contents, true, url, &state, &deleted); - interstitial->Show(); - interstitial->TestDidNavigate(1, url); - // Simulate a renderer crash. - interstitial->TestRendererGone(); - // The interstitial should have been dismissed. - EXPECT_TRUE(deleted); - EXPECT_EQ(TestInterstitialPage::CANCELED, state); -} diff --git a/chrome/browser/web_contents_view.cc b/chrome/browser/web_contents_view.cc deleted file mode 100644 index 3860fdf..0000000 --- a/chrome/browser/web_contents_view.cc +++ /dev/null @@ -1,60 +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/web_contents_view.h" - -#include "chrome/browser/render_widget_host.h" - -void WebContentsView::RenderWidgetHostDestroyed(RenderWidgetHost* host) { - for (PendingWidgetViews::iterator i = pending_widget_views_.begin(); - i != pending_widget_views_.end(); ++i) { - if (host->view() == i->second) { - pending_widget_views_.erase(i); - return; - } - } -} - -void WebContentsView::CreateNewWindow(int route_id, HANDLE modal_dialog_event) { - // Save the created window associated with the route so we can show it later. - pending_contents_[route_id] = CreateNewWindowInternal(route_id, - modal_dialog_event); -} - -void WebContentsView::CreateNewWidget(int route_id, bool activatable) { - // Save the created widget associated with the route so we can show it later. - pending_widget_views_[route_id] = CreateNewWidgetInternal(route_id, - activatable); -} - -void WebContentsView::ShowCreatedWindow(int route_id, - WindowOpenDisposition disposition, - const gfx::Rect& initial_pos, - bool user_gesture) { - PendingContents::iterator iter = pending_contents_.find(route_id); - if (iter == pending_contents_.end()) { - DCHECK(false); - return; - } - - WebContents* new_web_contents = iter->second; - pending_contents_.erase(route_id); - - ShowCreatedWindowInternal(new_web_contents, disposition, initial_pos, - user_gesture); -} - -void WebContentsView::ShowCreatedWidget(int route_id, - const gfx::Rect& initial_pos) { - PendingWidgetViews::iterator iter = pending_widget_views_.find(route_id); - if (iter == pending_widget_views_.end()) { - DCHECK(false); - return; - } - - RenderWidgetHostView* widget_host_view = iter->second; - pending_widget_views_.erase(route_id); - - ShowCreatedWidgetInternal(widget_host_view, initial_pos); -} diff --git a/chrome/browser/web_contents_view.h b/chrome/browser/web_contents_view.h deleted file mode 100644 index 232b449..0000000 --- a/chrome/browser/web_contents_view.h +++ /dev/null @@ -1,191 +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. - -#ifndef CHROME_BROWSER_WEB_CONTENTS_VIEW_H_ -#define CHROME_BROWSER_WEB_CONTENTS_VIEW_H_ - -#include - -#include -#include - -#include "base/basictypes.h" -#include "base/gfx/rect.h" -#include "base/gfx/size.h" -#include "chrome/browser/render_view_host_delegate.h" - -class Browser; -class RenderViewHost; -class RenderWidgetHost; -class RenderWidgetHostView; -class RenderWidgetHostViewWin; // TODO(brettw) this should not be necessary. -class WebContents; -struct WebDropData; -class WebKeyboardEvent; - -// The WebContentsView is an interface that is implemented by the platform- -// dependent web contents views. The WebContents 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 WebContentsView : public RenderViewHostDelegate::View { - public: - virtual ~WebContentsView() {} - - virtual WebContents* GetWebContents() = 0; - - virtual void CreateView() = 0; - - // Sets up the View that holds the rendered web page, receives messages for - // it and contains page plugins. - // TODO(brettw) make this so we don't need to return the Win version (see the - // caller in WebContents). - virtual RenderWidgetHostViewWin* CreateViewForWidget( - RenderWidgetHost* render_widget_host) = 0; - - // Returns the HWND that contains the contents of the tab. - // TODO(brettw) this should not be necessary in this cross-platform interface. - virtual HWND GetContainerHWND() const = 0; - - // Returns the HWND 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 HWND). - // TODO(brettw) this should not be necessary in this cross-platform interface. - virtual HWND GetContentHWND() 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()); - } - - // Called when the WebContents is being destroyed. This should clean up child - // windows that are part of the view. - // - // TODO(brettw) It seems like this might be able to be done internally as the - // window is being torn down without input from the WebContents. Try to - // implement functions that way rather than adding stuff here. - virtual void OnContentsDestroy() = 0; - - // 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; - - // Schedules a complete repaint of the window. This is used for cases where - // the existing contents became invalid due to an external event, such as the - // renderer crashing. - virtual void Invalidate() = 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); - - // Find in page -------------------------------------------------------------- - - // Opens the find in page window if it isn't already open. It will advance to - // the next match if |find_next| is set and there is a search string, - // otherwise, the find window will merely be opened. |forward_direction| - // indicates the direction to search when find_next is set, otherwise it is - // ignored. - virtual void FindInPage(const Browser& browser, - bool find_next, bool forward_direction) = 0; - - // Hides the find bar if there is one shown. Does nothing otherwise. The find - // bar will not be deleted, merely hidden. This ensures that any search terms - // are preserved if the user subsequently opens the find bar. - // - // If |end_session| is true, then the find session will be ended, which - // indicates the user requested they no longer be in find mode for that tab. - // The find bar will not be restored when we switch back to the tab. - // Otherwise, we assume that the find bar is being hidden because the tab is - // being hidden, and all state like visibility and tickmarks will be restored - // when the tab comes back. - virtual void HideFindBar(bool end_session) = 0; - - // Called when the tab is reparented to a new browser window. On MS Windows, - // we have to change the parent of our find bar to go with the new window. - // - // TODO(brettw) this seems like it could be improved. Possibly all doohickies - // around the tab like this, the download bar etc. should be managed by the - // BrowserView2 object. - virtual void ReparentFindWindow(Browser* new_browser) const = 0; - - // Computes the location of the find bar and whether it is fully visible in - // its parent window. The return value indicates if the window is visible at - // all. Both out arguments are required. - // - // This is used for UI tests of the find bar. If the find bar is not currently - // shown (return value of false), the out params will be {(0, 0), false}. - virtual bool GetFindBarWindowInfo(gfx::Point* position, - bool* fully_visible) const = 0; - - protected: - WebContentsView() {} // Abstract interface. - - // Internal interface for some functions in the RenderViewHostDelegate::View - // interface. Subclasses should implement this rather than the corresponding - // ...::View functions directly, since the routing stuff will already be - // computed. They should implement the rest of the functions as normal. - // - // The only difference is that the Create functions return the newly - // created objects so that they can be associated with the given routes. When - // they are shown later, we'll look them up again and pass the objects to - // the Show functions rather than the route ID. - virtual WebContents* CreateNewWindowInternal(int route_id, - HANDLE modal_dialog_event) = 0; - virtual RenderWidgetHostView* CreateNewWidgetInternal(int route_id, - bool activatable) = 0; - virtual void ShowCreatedWindowInternal(WebContents* new_web_contents, - WindowOpenDisposition disposition, - const gfx::Rect& initial_pos, - bool user_gesture) = 0; - virtual void ShowCreatedWidgetInternal(RenderWidgetHostView* widget_host_view, - const gfx::Rect& initial_pos) = 0; - - 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, HANDLE modal_dialog_event); - virtual void CreateNewWidget(int route_id, bool activatable); - 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); - - // Tracks created WebContents objects that have not been shown yet. They are - // identified by the route ID passed to CreateNewWindow. - typedef std::map 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 PendingWidgetViews; - PendingWidgetViews pending_widget_views_; - - DISALLOW_COPY_AND_ASSIGN(WebContentsView); -}; - -#endif // CHROME_BROWSER_WEB_CONTENTS_VIEW_H_ diff --git a/chrome/browser/web_contents_view_win.cc b/chrome/browser/web_contents_view_win.cc deleted file mode 100644 index 525ea4a..0000000 --- a/chrome/browser/web_contents_view_win.cc +++ /dev/null @@ -1,646 +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/web_contents_view_win.h" - -#include - -#include "chrome/browser/bookmarks/bookmark_drag_data.h" -#include "chrome/browser/browser.h" -#include "chrome/browser/browser_process.h" -#include "chrome/browser/download/download_request_manager.h" -#include "chrome/browser/interstitial_page.h" -#include "chrome/browser/render_view_context_menu.h" -#include "chrome/browser/render_view_context_menu_controller.h" -#include "chrome/browser/render_view_host.h" -#include "chrome/browser/render_widget_host_view_win.h" -#include "chrome/browser/tab_contents_delegate.h" -#include "chrome/browser/views/find_bar_win.h" -#include "chrome/browser/views/sad_tab_view.h" -#include "chrome/browser/web_contents.h" -#include "chrome/browser/web_drag_source.h" -#include "chrome/browser/web_drop_target.h" -#include "chrome/common/gfx/chrome_canvas.h" -#include "chrome/common/os_exchange_data.h" -#include "webkit/glue/plugins/webplugin_delegate_impl.h" - -namespace { - -// Windows callback for OnDestroy to detach the plugin windows. -BOOL CALLBACK DetachPluginWindowsCallback(HWND window, LPARAM param) { - if (WebPluginDelegateImpl::IsPluginDelegateWindow(window)) { - ::ShowWindow(window, SW_HIDE); - SetParent(window, NULL); - } - return TRUE; -} - -} // namespace - -WebContentsViewWin::WebContentsViewWin(WebContents* web_contents) - : web_contents_(web_contents), - ignore_next_char_event_(false) { -} - -WebContentsViewWin::~WebContentsViewWin() { -} - -WebContents* WebContentsViewWin::GetWebContents() { - return web_contents_; -} - -void WebContentsViewWin::CreateView() { - set_delete_on_destroy(false); - // Since we create these windows parented to the desktop window initially, we - // don't want to create them initially visible. - set_window_style(WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS); - WidgetWin::Init(GetDesktopWindow(), gfx::Rect(), false); - - // Remove the root view drop target so we can register our own. - RevokeDragDrop(GetHWND()); - drop_target_ = new WebDropTarget(GetHWND(), web_contents_); -} - -RenderWidgetHostViewWin* WebContentsViewWin::CreateViewForWidget( - RenderWidgetHost* render_widget_host) { - DCHECK(!render_widget_host->view()); - RenderWidgetHostViewWin* view = - new RenderWidgetHostViewWin(render_widget_host); - view->Create(GetHWND()); - view->ShowWindow(SW_SHOW); - return view; -} - -HWND WebContentsViewWin::GetContainerHWND() const { - return GetHWND(); -} - -HWND WebContentsViewWin::GetContentHWND() const { - if (!web_contents_->render_widget_host_view()) - return NULL; - return web_contents_->render_widget_host_view()->GetPluginHWND(); -} - -void WebContentsViewWin::GetContainerBounds(gfx::Rect* out) const { - GetBounds(out, false); -} - -void WebContentsViewWin::StartDragging(const WebDropData& drop_data) { - scoped_refptr data(new OSExchangeData); - - // TODO(tc): Generate an appropriate drag image. - - // We set the file contents before the URL because the URL also sets file - // contents (to a .URL shortcut). We want to prefer file content data over a - // shortcut so we add it first. - if (!drop_data.file_contents.empty()) { - data->SetFileContents(drop_data.file_description_filename, - drop_data.file_contents); - } - if (!drop_data.text_html.empty()) - data->SetHtml(drop_data.text_html, drop_data.html_base_url); - if (drop_data.url.is_valid()) { - if (drop_data.url.SchemeIs("javascript")) { - // We don't want to allow javascript URLs to be dragged to the desktop, - // but we do want to allow them to be added to the bookmarks bar - // (bookmarklets). - BookmarkDragData::Element bm_elt; - bm_elt.is_url = true; - bm_elt.url = drop_data.url; - bm_elt.title = drop_data.url_title; - - BookmarkDragData bm_drag_data; - bm_drag_data.elements.push_back(bm_elt); - - bm_drag_data.Write(web_contents_->profile(), data); - } else { - data->SetURL(drop_data.url, drop_data.url_title); - } - } - if (!drop_data.plain_text.empty()) - data->SetString(drop_data.plain_text); - - scoped_refptr drag_source( - new WebDragSource(GetHWND(), web_contents_->render_view_host())); - - DWORD effects; - - // We need to enable recursive tasks on the message loop so we can get - // updates while in the system DoDragDrop loop. - bool old_state = MessageLoop::current()->NestableTasksAllowed(); - MessageLoop::current()->SetNestableTasksAllowed(true); - DoDragDrop(data, drag_source, DROPEFFECT_COPY | DROPEFFECT_LINK, &effects); - MessageLoop::current()->SetNestableTasksAllowed(old_state); - - if (web_contents_->render_view_host()) - web_contents_->render_view_host()->DragSourceSystemDragEnded(); -} - -void WebContentsViewWin::OnContentsDestroy() { - // TODO(brettw) this seems like maybe it can be moved into OnDestroy and this - // function can be deleted? If you're adding more here, consider whether it - // can be moved into OnDestroy which is a Windows message handler as the - // window is being torn down. - - // When a tab is closed all its child plugin windows are destroyed - // automatically. This happens before plugins get any notification that its - // instances are tearing down. - // - // Plugins like Quicktime assume that their windows will remain valid as long - // as they have plugin instances active. Quicktime crashes in this case - // because its windowing code cleans up an internal data structure that the - // handler for NPP_DestroyStream relies on. - // - // The fix is to detach plugin windows from web contents when it is going - // away. This will prevent the plugin windows from getting destroyed - // automatically. The detached plugin windows will get cleaned up in proper - // sequence as part of the usual cleanup when the plugin instance goes away. - EnumChildWindows(GetHWND(), DetachPluginWindowsCallback, NULL); - - // Close the find bar if any. - if (find_bar_.get()) - find_bar_->Close(); -} - -void WebContentsViewWin::OnDestroy() { - if (drop_target_.get()) { - RevokeDragDrop(GetHWND()); - drop_target_ = NULL; - } -} - -void WebContentsViewWin::SetPageTitle(const std::wstring& title) { - if (GetContainerHWND()) { - // It's possible to get this after the hwnd has been destroyed. - ::SetWindowText(GetContainerHWND(), title.c_str()); - // TODO(brettw) this call seems messy the way it reaches into the widget - // view, and I'm not sure it's necessary. Maybe we should just remove it. - ::SetWindowText(web_contents_->render_widget_host_view()->GetPluginHWND(), - title.c_str()); - } -} - -void WebContentsViewWin::Invalidate() { - // Note that it's possible to get this message after the window was destroyed. - if (::IsWindow(GetContainerHWND())) - InvalidateRect(GetContainerHWND(), NULL, FALSE); -} - -void WebContentsViewWin::SizeContents(const gfx::Size& size) { - // TODO(brettw) this is a hack and should be removed. See web_contents_view.h. - WasSized(size); -} - -void WebContentsViewWin::FindInPage(const Browser& browser, - bool find_next, bool forward_direction) { - if (!find_bar_.get()) { - // We want the Chrome top-level (Frame) window. - HWND hwnd = reinterpret_cast(browser.window()->GetNativeHandle()); - find_bar_.reset(new FindBarWin(this, hwnd)); - } else { - find_bar_->Show(); - } - - if (find_next && !find_bar_->find_string().empty()) - find_bar_->StartFinding(forward_direction); -} - -void WebContentsViewWin::HideFindBar(bool end_session) { - if (find_bar_.get()) { - if (end_session) - find_bar_->EndFindSession(); - else - find_bar_->DidBecomeUnselected(); - } -} - -void WebContentsViewWin::ReparentFindWindow(Browser* new_browser) const { - if (find_bar_.get()) { - find_bar_->SetParent( - reinterpret_cast(new_browser->window()->GetNativeHandle())); - } -} - -bool WebContentsViewWin::GetFindBarWindowInfo(gfx::Point* position, - bool* fully_visible) const { - CRect window_rect; - if (!find_bar_.get() || - !::IsWindow(find_bar_->GetHWND()) || - !::GetWindowRect(find_bar_->GetHWND(), &window_rect)) { - *position = gfx::Point(0, 0); - *fully_visible = false; - return false; - } - - *position = gfx::Point(window_rect.TopLeft().x, window_rect.TopLeft().y); - *fully_visible = find_bar_->IsVisible() && !find_bar_->IsAnimating(); - return true; -} - -void WebContentsViewWin::UpdateDragCursor(bool is_drop_target) { - drop_target_->set_is_drop_target(is_drop_target); -} - -void WebContentsViewWin::TakeFocus(bool reverse) { - views::FocusManager* focus_manager = - views::FocusManager::GetFocusManager(GetContainerHWND()); - - // We may not have a focus manager if the tab has been switched before this - // message arrived. - if (focus_manager) - focus_manager->AdvanceFocus(reverse); -} - -void WebContentsViewWin::HandleKeyboardEvent(const WebKeyboardEvent& event) { - // Previous calls to TranslateMessage can generate CHAR events as well as - // KEY_DOWN events, even if the latter triggered an accelerator. In these - // cases, we discard the CHAR events. - if (event.type == WebInputEvent::CHAR && ignore_next_char_event_) { - ignore_next_char_event_ = false; - return; - } - ignore_next_char_event_ = false; - - // The renderer returned a keyboard event it did not process. This may be - // a keyboard shortcut that we have to process. - if (event.type == WebInputEvent::KEY_DOWN) { - views::FocusManager* focus_manager = - views::FocusManager::GetFocusManager(GetHWND()); - // We may not have a focus_manager at this point (if the tab has been - // switched by the time this message returned). - if (focus_manager) { - views::Accelerator accelerator(event.key_code, - (event.modifiers & WebInputEvent::SHIFT_KEY) == - WebInputEvent::SHIFT_KEY, - (event.modifiers & WebInputEvent::CTRL_KEY) == - WebInputEvent::CTRL_KEY, - (event.modifiers & WebInputEvent::ALT_KEY) == - WebInputEvent::ALT_KEY); - if (focus_manager->ProcessAccelerator(accelerator, false)) { - ignore_next_char_event_ = true; - return; - } - } - } - - // Any unhandled keyboard/character messages should be defproced. - // This allows stuff like Alt+F4, etc to work correctly. - DefWindowProc(event.actual_message.hwnd, - event.actual_message.message, - event.actual_message.wParam, - event.actual_message.lParam); -} - -void WebContentsViewWin::OnFindReply(int request_id, - int number_of_matches, - const gfx::Rect& selection_rect, - int active_match_ordinal, - bool final_update) { - if (find_bar_.get()) { - find_bar_->OnFindReply(request_id, number_of_matches, selection_rect, - active_match_ordinal, final_update); - } -} - -void WebContentsViewWin::ShowContextMenu( - const ViewHostMsg_ContextMenu_Params& params) { - RenderViewContextMenuController menu_controller(web_contents_, params); - RenderViewContextMenu menu(&menu_controller, - GetHWND(), - params.type, - params.misspelled_word, - params.dictionary_suggestions, - web_contents_->profile()); - - POINT screen_pt = { params.x, params.y }; - MapWindowPoints(GetHWND(), HWND_DESKTOP, &screen_pt, 1); - - // Enable recursive tasks on the message loop so we can get updates while - // the context menu is being displayed. - bool old_state = MessageLoop::current()->NestableTasksAllowed(); - MessageLoop::current()->SetNestableTasksAllowed(true); - menu.RunMenuAt(screen_pt.x, screen_pt.y); - MessageLoop::current()->SetNestableTasksAllowed(old_state); -} - -WebContents* WebContentsViewWin::CreateNewWindowInternal( - int route_id, - HANDLE modal_dialog_event) { - // Create the new web contents. This will automatically create the new - // WebContentsView. In the future, we may want to create the view separately. - WebContents* new_contents = - new WebContents(web_contents_->profile(), - web_contents_->GetSiteInstance(), - web_contents_->render_view_factory_, - route_id, - modal_dialog_event); - new_contents->SetupController(web_contents_->profile()); - WebContentsView* new_view = new_contents->view(); - - new_view->CreateView(); - - // TODO(brettw) it seems bogus that we have to call this function on the - // newly created object and give it one of its own member variables. - new_view->CreateViewForWidget(new_contents->render_view_host()); - return new_contents; -} - -RenderWidgetHostView* WebContentsViewWin::CreateNewWidgetInternal( - int route_id, - bool activatable) { - // Create the widget and its associated view. - // TODO(brettw) can widget creation be cross-platform? - RenderWidgetHost* widget_host = - new RenderWidgetHost(web_contents_->process(), route_id); - RenderWidgetHostViewWin* widget_view = - new RenderWidgetHostViewWin(widget_host); - - // We set the parent HWDN explicitly as pop-up HWNDs are parented and owned by - // the first non-child HWND of the HWND that was specified to the CreateWindow - // call. - // TODO(brettw) this should not need to get the current RVHView from the - // WebContents. We should have it somewhere ourselves. - widget_view->set_parent_hwnd( - web_contents_->render_widget_host_view()->GetPluginHWND()); - widget_view->set_close_on_deactivate(true); - widget_view->set_activatable(activatable); - - return widget_view; -} - -void WebContentsViewWin::ShowCreatedWindowInternal( - WebContents* new_web_contents, - WindowOpenDisposition disposition, - const gfx::Rect& initial_pos, - bool user_gesture) { - if (!new_web_contents->render_widget_host_view() || - !new_web_contents->process()->channel()) { - // The view has gone away or the renderer crashed. Nothing to do. - return; - } - - // TODO(brettw) this seems bogus to reach into here and initialize the host. - new_web_contents->render_view_host()->Init(); - web_contents_->AddNewContents(new_web_contents, disposition, initial_pos, - user_gesture); -} - -void WebContentsViewWin::ShowCreatedWidgetInternal( - RenderWidgetHostView* widget_host_view, - const gfx::Rect& initial_pos) { - // TODO(beng): (Cleanup) move all this windows-specific creation and showing - // code into RenderWidgetHostView behind some API that a - // ChromeView can also reasonably implement. - RenderWidgetHostViewWin* widget_host_view_win = - static_cast(widget_host_view); - - RenderWidgetHost* widget_host = widget_host_view->GetRenderWidgetHost(); - if (!widget_host->process()->channel()) { - // The view has gone away or the renderer crashed. Nothing to do. - return; - } - - // This logic should be implemented by RenderWidgetHostHWND (as mentioned - // above) in the ::Init function, which should take a parent and some initial - // bounds. - widget_host_view_win->Create(GetContainerHWND(), NULL, NULL, - WS_POPUP, WS_EX_TOOLWINDOW); - widget_host_view_win->MoveWindow(initial_pos.x(), initial_pos.y(), - initial_pos.width(), initial_pos.height(), - TRUE); - widget_host_view_win->ShowWindow(widget_host_view_win->activatable() ? - SW_SHOW : SW_SHOWNA); - widget_host->Init(); -} - -void WebContentsViewWin::OnHScroll(int scroll_type, short position, - HWND scrollbar) { - ScrollCommon(WM_HSCROLL, scroll_type, position, scrollbar); -} - -void WebContentsViewWin::OnMouseLeave() { - // Let our delegate know that the mouse moved (useful for resetting status - // bubble state). - if (web_contents_->delegate()) - web_contents_->delegate()->ContentsMouseEvent(web_contents_, WM_MOUSELEAVE); - SetMsgHandled(FALSE); -} - -LRESULT WebContentsViewWin::OnMouseRange(UINT msg, - WPARAM w_param, LPARAM l_param) { - switch (msg) { - case WM_LBUTTONDOWN: - case WM_MBUTTONDOWN: - case WM_RBUTTONDOWN: { - // Make sure this TabContents is activated when it is clicked on. - if (web_contents_->delegate()) - web_contents_->delegate()->ActivateContents(web_contents_); - DownloadRequestManager* drm = - g_browser_process->download_request_manager(); - if (drm) - drm->OnUserGesture(web_contents_); - break; - } - case WM_MOUSEMOVE: - // Let our delegate know that the mouse moved (useful for resetting status - // bubble state). - if (web_contents_->delegate()) { - web_contents_->delegate()->ContentsMouseEvent(web_contents_, - WM_MOUSEMOVE); - } - break; - default: - break; - } - - return 0; -} - -void WebContentsViewWin::OnPaint(HDC junk_dc) { - if (web_contents_->render_view_host() && - !web_contents_->render_view_host()->IsRenderViewLive()) { - if (!sad_tab_.get()) - sad_tab_.reset(new SadTabView); - CRect cr; - GetClientRect(&cr); - sad_tab_->SetBounds(gfx::Rect(cr)); - ChromeCanvasPaint canvas(GetHWND(), true); - sad_tab_->ProcessPaint(&canvas); - return; - } - - // We need to do this to validate the dirty area so we don't end up in a - // WM_PAINTstorm that causes other mysterious bugs (such as WM_TIMERs not - // firing etc). It doesn't matter that we don't have any non-clipped area. - CPaintDC dc(GetHWND()); - SetMsgHandled(FALSE); -} - -// A message is reflected here from view(). -// Return non-zero to indicate that it is handled here. -// Return 0 to allow view() to further process it. -LRESULT WebContentsViewWin::OnReflectedMessage(UINT msg, WPARAM w_param, - LPARAM l_param) { - MSG* message = reinterpret_cast(l_param); - switch (message->message) { - case WM_MOUSEWHEEL: - // This message is reflected from the view() to this window. - if (GET_KEYSTATE_WPARAM(message->wParam) & MK_CONTROL) { - WheelZoom(GET_WHEEL_DELTA_WPARAM(message->wParam)); - return 1; - } - break; - case WM_HSCROLL: - case WM_VSCROLL: - if (ScrollZoom(LOWORD(message->wParam))) - return 1; - default: - break; - } - - return 0; -} - -void WebContentsViewWin::OnSetFocus(HWND window) { - // TODO(jcampan): figure out why removing this prevents tabs opened in the - // background from properly taking focus. - // We NULL-check the render_view_host_ here because Windows can send us - // messages during the destruction process after it has been destroyed. - if (web_contents_->render_widget_host_view()) { - HWND inner_hwnd = web_contents_->render_widget_host_view()->GetPluginHWND(); - if (::IsWindow(inner_hwnd)) - ::SetFocus(inner_hwnd); - } -} - -void WebContentsViewWin::OnVScroll(int scroll_type, short position, - HWND scrollbar) { - ScrollCommon(WM_VSCROLL, scroll_type, position, scrollbar); -} - -void WebContentsViewWin::OnWindowPosChanged(WINDOWPOS* window_pos) { - if (window_pos->flags & SWP_HIDEWINDOW) { - WasHidden(); - } else { - // The WebContents was shown by a means other than the user selecting a - // Tab, e.g. the window was minimized then restored. - if (window_pos->flags & SWP_SHOWWINDOW) - WasShown(); - - // Unless we were specifically told not to size, cause the renderer to be - // sized to the new bounds, which forces a repaint. Not required for the - // simple minimize-restore case described above, for example, since the - // size hasn't changed. - if (!(window_pos->flags & SWP_NOSIZE)) - WasSized(gfx::Size(window_pos->cx, window_pos->cy)); - - // If we have a FindInPage dialog, notify it that the window changed. - if (find_bar_.get() && find_bar_->IsVisible()) - find_bar_->MoveWindowIfNecessary(gfx::Rect()); - } -} - -void WebContentsViewWin::OnSize(UINT param, const CSize& size) { - WidgetWin::OnSize(param, size); - - // Hack for thinkpad touchpad driver. - // Set fake scrollbars so that we can get scroll messages, - SCROLLINFO si = {0}; - si.cbSize = sizeof(si); - si.fMask = SIF_ALL; - - si.nMin = 1; - si.nMax = 100; - si.nPage = 10; - si.nPos = 50; - - ::SetScrollInfo(GetHWND(), SB_HORZ, &si, FALSE); - ::SetScrollInfo(GetHWND(), SB_VERT, &si, FALSE); -} - -LRESULT WebContentsViewWin::OnNCCalcSize(BOOL w_param, LPARAM l_param) { - // Hack for thinkpad mouse wheel driver. We have set the fake scroll bars - // to receive scroll messages from thinkpad touchpad driver. Suppress - // painting of scrollbars by returning 0 size for them. - return 0; -} - -void WebContentsViewWin::OnNCPaint(HRGN rgn) { - // Suppress default WM_NCPAINT handling. We don't need to do anything - // here since the view will draw everything correctly. -} - -void WebContentsViewWin::ScrollCommon(UINT message, int scroll_type, - short position, HWND scrollbar) { - // This window can receive scroll events as a result of the ThinkPad's - // Trackpad scroll wheel emulation. - if (!ScrollZoom(scroll_type)) { - // Reflect scroll message to the view() to give it a chance - // to process scrolling. - SendMessage(GetContentHWND(), message, MAKELONG(scroll_type, position), - (LPARAM) scrollbar); - } -} - -void WebContentsViewWin::WasHidden() { - web_contents_->HideContents(); - if (find_bar_.get()) - find_bar_->DidBecomeUnselected(); -} - -void WebContentsViewWin::WasShown() { - web_contents_->ShowContents(); - if (find_bar_.get()) - find_bar_->DidBecomeSelected(); -} - -void WebContentsViewWin::WasSized(const gfx::Size& size) { - if (web_contents_->interstitial_page()) - web_contents_->interstitial_page()->SetSize(size); - if (web_contents_->render_widget_host_view()) - web_contents_->render_widget_host_view()->SetSize(size); - if (find_bar_.get()) - find_bar_->RespondToResize(size); - - // TODO(brettw) this function can probably be moved to this class. - web_contents_->RepositionSupressedPopupsToFit(size); -} - -bool WebContentsViewWin::ScrollZoom(int scroll_type) { - // If ctrl is held, zoom the UI. There are three issues with this: - // 1) Should the event be eaten or forwarded to content? We eat the event, - // which is like Firefox and unlike IE. - // 2) Should wheel up zoom in or out? We zoom in (increase font size), which - // is like IE and Google maps, but unlike Firefox. - // 3) Should the mouse have to be over the content area? We zoom as long as - // content has focus, although FF and IE require that the mouse is over - // content. This is because all events get forwarded when content has - // focus. - if (GetAsyncKeyState(VK_CONTROL) & 0x8000) { - int distance = 0; - switch (scroll_type) { - case SB_LINEUP: - distance = WHEEL_DELTA; - break; - case SB_LINEDOWN: - distance = -WHEEL_DELTA; - break; - // TODO(joshia): Handle SB_PAGEUP, SB_PAGEDOWN, SB_THUMBPOSITION, - // and SB_THUMBTRACK for completeness - default: - break; - } - - WheelZoom(distance); - return true; - } - return false; -} - -void WebContentsViewWin::WheelZoom(int distance) { - if (web_contents_->delegate()) { - bool zoom_in = distance > 0; - web_contents_->delegate()->ContentsZoomChange(zoom_in); - } -} diff --git a/chrome/browser/web_contents_view_win.h b/chrome/browser/web_contents_view_win.h deleted file mode 100644 index 604c462..0000000 --- a/chrome/browser/web_contents_view_win.h +++ /dev/null @@ -1,128 +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. - -#ifndef CHROME_BROWSER_WEB_CONTENTS_VIEW_WIN_H_ -#define CHROME_BROWSER_WEB_CONTENTS_VIEW_WIN_H_ - -#include "base/gfx/size.h" -#include "base/scoped_ptr.h" -#include "chrome/browser/web_contents_view.h" -#include "chrome/views/widget_win.h" - -class FindBarWin; -class SadTabView; -struct WebDropData; -class WebDropTarget; - -// Windows-specific implementation of the WebContentsView. It is a HWND that -// contains all of the contents of the tab and associated child views. -class WebContentsViewWin : public WebContentsView, - public views::WidgetWin { - public: - // The corresponding WebContents is passed in the constructor, and manages our - // lifetime. This doesn't need to be the case, but is this way currently - // because that's what was easiest when they were split. - explicit WebContentsViewWin(WebContents* web_contents); - virtual ~WebContentsViewWin(); - - // WebContentsView implementation -------------------------------------------- - - virtual WebContents* GetWebContents(); - virtual void CreateView(); - virtual RenderWidgetHostViewWin* CreateViewForWidget( - RenderWidgetHost* render_widget_host); - virtual HWND GetContainerHWND() const; - virtual HWND GetContentHWND() const; - virtual void GetContainerBounds(gfx::Rect* out) const; - virtual void OnContentsDestroy(); - virtual void SetPageTitle(const std::wstring& title); - virtual void Invalidate(); - virtual void SizeContents(const gfx::Size& size); - virtual void FindInPage(const Browser& browser, - bool find_next, bool forward_direction); - virtual void HideFindBar(bool end_session); - virtual void ReparentFindWindow(Browser* new_browser) const; - virtual bool GetFindBarWindowInfo(gfx::Point* position, - bool* fully_visible) const; - - // Backend implementation of RenderViewHostDelegate::View. - virtual WebContents* CreateNewWindowInternal( - int route_id, HANDLE modal_dialog_event); - virtual RenderWidgetHostView* CreateNewWidgetInternal(int route_id, - bool activatable); - virtual void ShowCreatedWindowInternal(WebContents* new_web_contents, - WindowOpenDisposition disposition, - const gfx::Rect& initial_pos, - bool user_gesture); - virtual void ShowCreatedWidgetInternal(RenderWidgetHostView* widget_host_view, - const gfx::Rect& initial_pos); - virtual void ShowContextMenu( - const ViewHostMsg_ContextMenu_Params& params); - virtual void StartDragging(const WebDropData& drop_data); - virtual void UpdateDragCursor(bool is_drop_target); - virtual void TakeFocus(bool reverse); - virtual void HandleKeyboardEvent(const WebKeyboardEvent& event); - virtual void OnFindReply(int request_id, - int number_of_matches, - const gfx::Rect& selection_rect, - int active_match_ordinal, - bool final_update); - - private: - // Windows events ------------------------------------------------------------ - - // Overrides from WidgetWin. - virtual void OnDestroy(); - virtual void OnHScroll(int scroll_type, short position, HWND scrollbar); - virtual void OnMouseLeave(); - virtual LRESULT OnMouseRange(UINT msg, WPARAM w_param, LPARAM l_param); - virtual void OnPaint(HDC junk_dc); - virtual LRESULT OnReflectedMessage(UINT msg, WPARAM w_param, LPARAM l_param); - virtual void OnSetFocus(HWND window); - virtual void OnVScroll(int scroll_type, short position, HWND scrollbar); - virtual void OnWindowPosChanged(WINDOWPOS* window_pos); - virtual void OnSize(UINT param, const CSize& size); - virtual LRESULT OnNCCalcSize(BOOL w_param, LPARAM l_param); - virtual void OnNCPaint(HRGN rgn); - - // Backend for all scroll messages, the |message| parameter indicates which - // one it is. - void ScrollCommon(UINT message, int scroll_type, short position, - HWND scrollbar); - - // Handles notifying the WebContents and other operations when the window was - // shown or hidden. - void WasHidden(); - void WasShown(); - - // Handles resizing of the contents. This will notify the RenderWidgetHostView - // of the change, reposition popups, and the find in page bar. - void WasSized(const gfx::Size& size); - - // TODO(brettw) comment these. They're confusing. - bool ScrollZoom(int scroll_type); - void WheelZoom(int distance); - - // --------------------------------------------------------------------------- - - WebContents* web_contents_; - - // For find in page. This may be NULL if there is no find bar, and if it is - // non-NULL, it may or may not be visible. - scoped_ptr find_bar_; - - // A drop target object that handles drags over this WebContents. - scoped_refptr drop_target_; - - // Used to render the sad tab. This will be non-NULL only when the sad tab is - // visible. - scoped_ptr sad_tab_; - - // Whether to ignore the next CHAR keyboard event. - bool ignore_next_char_event_; - - DISALLOW_COPY_AND_ASSIGN(WebContentsViewWin); -}; - -#endif // CHROME_BROWSER_WEB_CONTENTS_VIEW_WIN_H_ diff --git a/chrome/browser/web_drag_source.cc b/chrome/browser/web_drag_source.cc deleted file mode 100644 index 9a197ae..0000000 --- a/chrome/browser/web_drag_source.cc +++ /dev/null @@ -1,45 +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 -#include -#include - -#include "chrome/browser/web_drag_source.h" - -#include "chrome/browser/render_view_host.h" - -namespace { - -static void GetCursorPositions(HWND hwnd, CPoint* client, CPoint* screen) { - GetCursorPos(screen); - *client = *screen; - ScreenToClient(hwnd, client); -} - -} // namespace -/////////////////////////////////////////////////////////////////////////////// -// WebDragSource, public: - -WebDragSource::WebDragSource(HWND source_hwnd, - RenderViewHost* render_view_host) - : BaseDragSource(), - source_hwnd_(source_hwnd), - render_view_host_(render_view_host) { -} - -void WebDragSource::OnDragSourceDrop() { - CPoint client; - CPoint screen; - GetCursorPositions(source_hwnd_, &client, &screen); - render_view_host_->DragSourceEndedAt(client.x, client.y, screen.x, screen.y); -} - -void WebDragSource::OnDragSourceMove() { - CPoint client; - CPoint screen; - GetCursorPositions(source_hwnd_, &client, &screen); - render_view_host_->DragSourceMovedTo(client.x, client.y, screen.x, screen.y); -} - diff --git a/chrome/browser/web_drag_source.h b/chrome/browser/web_drag_source.h deleted file mode 100644 index f8aa628..0000000 --- a/chrome/browser/web_drag_source.h +++ /dev/null @@ -1,49 +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. - -#ifndef CHROME_BROWSER_WEB_DRAG_SOURCE_H__ -#define CHROME_BROWSER_WEB_DRAG_SOURCE_H__ - -#include "base/base_drag_source.h" -#include "base/basictypes.h" - -class RenderViewHost; - -/////////////////////////////////////////////////////////////////////////////// -// -// WebDragSource -// -// An IDropSource implementation for a WebContents. Handles notifications sent -// by an active drag-drop operation as the user mouses over other drop targets -// on their system. This object tells Windows whether or not the drag should -// continue, and supplies the appropriate cursors. -// -class WebDragSource : public BaseDragSource { - public: - // Create a new DragSource for a given HWND and RenderViewHost. - WebDragSource(HWND source_hwnd, RenderViewHost* render_view_host); - virtual ~WebDragSource() { } - - protected: - // BaseDragSource - virtual void OnDragSourceDrop(); - virtual void OnDragSourceMove(); - - private: - // Cannot construct thusly. - WebDragSource(); - - // Keep a reference to the HWND so we can translate the cursor position. - HWND source_hwnd_; - - // We use this as a channel to the renderer to tell it about various drag - // drop events that it needs to know about (such as when a drag operation it - // initiated terminates). - RenderViewHost* render_view_host_; - - DISALLOW_EVIL_CONSTRUCTORS(WebDragSource); -}; - -#endif // #ifndef CHROME_BROWSER_WEB_DRAG_SOURCE_H__ - diff --git a/chrome/browser/web_drop_target.cc b/chrome/browser/web_drop_target.cc deleted file mode 100644 index fe5ee53..0000000 --- a/chrome/browser/web_drop_target.cc +++ /dev/null @@ -1,182 +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 -#include - -#include "chrome/browser/web_drop_target.h" - -#include "base/clipboard_util.h" -#include "base/gfx/point.h" -#include "chrome/browser/render_view_host.h" -#include "chrome/browser/web_contents.h" -#include "chrome/common/os_exchange_data.h" -#include "googleurl/src/gurl.h" -#include "net/base/net_util.h" -#include "webkit/glue/webdropdata.h" -#include "webkit/glue/window_open_disposition.h" - -namespace { - -// A helper method for getting the preferred drop effect. -DWORD GetPreferredDropEffect(DWORD effect) { - if (effect & DROPEFFECT_COPY) - return DROPEFFECT_COPY; - if (effect & DROPEFFECT_LINK) - return DROPEFFECT_LINK; - if (effect & DROPEFFECT_MOVE) - return DROPEFFECT_MOVE; - return DROPEFFECT_NONE; -} - -} // anonymous namespace - -// InterstitialDropTarget is like a BaseDropTarget implementation that -// WebDropTarget passes through to if an interstitial is showing. Rather than -// passing messages on to the renderer, we just check to see if there's a link -// in the drop data and handle links as navigations. -class InterstitialDropTarget { - public: - explicit InterstitialDropTarget(WebContents* web_contents) - : web_contents_(web_contents) {} - - DWORD OnDragEnter(IDataObject* data_object, DWORD effect) { - return ClipboardUtil::HasUrl(data_object) ? GetPreferredDropEffect(effect) - : DROPEFFECT_NONE; - } - - DWORD OnDragOver(IDataObject* data_object, DWORD effect) { - return ClipboardUtil::HasUrl(data_object) ? GetPreferredDropEffect(effect) - : DROPEFFECT_NONE; - } - - void OnDragLeave(IDataObject* data_object) { - } - - DWORD OnDrop(IDataObject* data_object, DWORD effect) { - if (ClipboardUtil::HasUrl(data_object)) { - std::wstring url; - std::wstring title; - ClipboardUtil::GetUrl(data_object, &url, &title); - web_contents_->OpenURL(GURL(url), GURL(), CURRENT_TAB, - PageTransition::AUTO_BOOKMARK); - return GetPreferredDropEffect(effect); - } - return DROPEFFECT_NONE; - } - - private: - WebContents* web_contents_; - - DISALLOW_EVIL_CONSTRUCTORS(InterstitialDropTarget); -}; - -/////////////////////////////////////////////////////////////////////////////// -// WebDropTarget, public: - -WebDropTarget::WebDropTarget(HWND source_hwnd, WebContents* web_contents) - : BaseDropTarget(source_hwnd), - web_contents_(web_contents), - current_rvh_(NULL), - is_drop_target_(false), - interstitial_drop_target_(new InterstitialDropTarget(web_contents)) { -} - -WebDropTarget::~WebDropTarget() { -} - -DWORD WebDropTarget::OnDragEnter(IDataObject* data_object, - DWORD key_state, - POINT cursor_position, - DWORD effect) { - current_rvh_ = web_contents_->render_view_host(); - - // Don't pass messages to the renderer if an interstitial page is showing - // because we don't want the interstitial page to navigate. Instead, - // pass the messages on to a separate interstitial DropTarget handler. - if (web_contents_->showing_interstitial_page()) - return interstitial_drop_target_->OnDragEnter(data_object, effect); - - // TODO(tc): PopulateWebDropData can be slow depending on what is in the - // IDataObject. Maybe we can do this in a background thread. - WebDropData drop_data; - WebDropData::PopulateWebDropData(data_object, &drop_data); - - if (drop_data.url.is_empty()) - OSExchangeData::GetPlainTextURL(data_object, &drop_data.url); - - is_drop_target_ = true; - - POINT client_pt = cursor_position; - ScreenToClient(GetHWND(), &client_pt); - web_contents_->render_view_host()->DragTargetDragEnter(drop_data, - gfx::Point(client_pt.x, client_pt.y), - gfx::Point(cursor_position.x, cursor_position.y)); - - // We lie here and always return a DROPEFFECT because we don't want to - // wait for the IPC call to return. - return GetPreferredDropEffect(effect); -} - -DWORD WebDropTarget::OnDragOver(IDataObject* data_object, - DWORD key_state, - POINT cursor_position, - DWORD effect) { - DCHECK(current_rvh_); - if (current_rvh_ != web_contents_->render_view_host()) - OnDragEnter(data_object, key_state, cursor_position, effect); - - if (web_contents_->showing_interstitial_page()) - return interstitial_drop_target_->OnDragOver(data_object, effect); - - POINT client_pt = cursor_position; - ScreenToClient(GetHWND(), &client_pt); - web_contents_->render_view_host()->DragTargetDragOver( - gfx::Point(client_pt.x, client_pt.y), - gfx::Point(cursor_position.x, cursor_position.y)); - - if (!is_drop_target_) - return DROPEFFECT_NONE; - - return GetPreferredDropEffect(effect); -} - -void WebDropTarget::OnDragLeave(IDataObject* data_object) { - DCHECK(current_rvh_); - if (current_rvh_ != web_contents_->render_view_host()) - return; - - if (web_contents_->showing_interstitial_page()) { - interstitial_drop_target_->OnDragLeave(data_object); - } else { - web_contents_->render_view_host()->DragTargetDragLeave(); - } -} - -DWORD WebDropTarget::OnDrop(IDataObject* data_object, - DWORD key_state, - POINT cursor_position, - DWORD effect) { - DCHECK(current_rvh_); - if (current_rvh_ != web_contents_->render_view_host()) - OnDragEnter(data_object, key_state, cursor_position, effect); - - if (web_contents_->showing_interstitial_page()) - interstitial_drop_target_->OnDragOver(data_object, effect); - - if (web_contents_->showing_interstitial_page()) - return interstitial_drop_target_->OnDrop(data_object, effect); - - POINT client_pt = cursor_position; - ScreenToClient(GetHWND(), &client_pt); - web_contents_->render_view_host()->DragTargetDrop( - gfx::Point(client_pt.x, client_pt.y), - gfx::Point(cursor_position.x, cursor_position.y)); - - current_rvh_ = NULL; - - // We lie and always claim that the drop operation didn't happen because we - // don't want to wait for the renderer to respond. - return DROPEFFECT_NONE; -} diff --git a/chrome/browser/web_drop_target.h b/chrome/browser/web_drop_target.h deleted file mode 100644 index 28f4073..0000000 --- a/chrome/browser/web_drop_target.h +++ /dev/null @@ -1,74 +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. - -#ifndef CHROME_BROWSER_WEB_DROP_TARGET_H__ -#define CHROME_BROWSER_WEB_DROP_TARGET_H__ - -#include "base/base_drop_target.h" -#include "base/scoped_ptr.h" - -class InterstitialDropTarget; -class RenderViewHost; -class WebContents; - -/////////////////////////////////////////////////////////////////////////////// -// -// WebDropTarget -// -// A helper object that provides drop capabilities to a WebContents. The -// DropTarget handles drags that enter the region of the WebContents by -// passing on the events to the renderer. -// -class WebDropTarget : public BaseDropTarget { - public: - // Create a new WebDropTarget associating it with the given HWND and - // WebContents. - WebDropTarget(HWND source_hwnd, WebContents* contents); - virtual ~WebDropTarget(); - - void set_is_drop_target(bool is_drop_target) { - is_drop_target_ = is_drop_target; - } - - protected: - virtual DWORD OnDragEnter(IDataObject* data_object, - DWORD key_state, - POINT cursor_position, - DWORD effect); - - virtual DWORD OnDragOver(IDataObject* data_object, - DWORD key_state, - POINT cursor_position, - DWORD effect); - - virtual void OnDragLeave(IDataObject* data_object); - - virtual DWORD OnDrop(IDataObject* data_object, - DWORD key_state, - POINT cursor_position, - DWORD effect); - - private: - // Our associated WebContents. - WebContents* web_contents_; - - // We keep track of the render view host we're dragging over. If it changes - // during a drag, we need to re-send the DragEnter message. WARNING: - // this pointer should never be dereferenced. We only use it for comparing - // pointers. - RenderViewHost* current_rvh_; - - // Used to determine what cursor we should display when dragging over web - // content area. This can be updated async during a drag operation. - bool is_drop_target_; - - // A special drop target handler for when we try to d&d while an interstitial - // page is showing. - scoped_ptr interstitial_drop_target_; - - DISALLOW_EVIL_CONSTRUCTORS(WebDropTarget); -}; - -#endif // #ifndef CHROME_BROWSER_WEB_DROP_TARGET_H__ - -- cgit v1.1