diff options
Diffstat (limited to 'chrome')
20 files changed, 1654 insertions, 1704 deletions
diff --git a/chrome/browser/automation/automation_provider.cc b/chrome/browser/automation/automation_provider.cc index 7b4f600..7705d94 100644 --- a/chrome/browser/automation/automation_provider.cc +++ b/chrome/browser/automation/automation_provider.cc @@ -169,7 +169,7 @@ class NavigationControllerRestoredObserver : public NotificationObserver { bool FinishedRestoring() { return (!controller_->needs_reload() && !controller_->GetPendingEntry() && - !controller_->active_contents()->IsLoading()); + !controller_->active_contents()->is_loading()); } void SendDone() { @@ -1637,8 +1637,8 @@ void AutomationProvider::GetConstrainedWindow(const IPC::Message& message, NavigationController* nav_controller = tab_tracker_->GetResource(handle); TabContents* tab = nav_controller->active_contents(); - if (tab && index < static_cast<int>(tab->child_windows().size())) { - ConstrainedWindow* window = tab->child_windows()[index]; + if (tab && index < static_cast<int>(tab->child_windows_.size())) { + ConstrainedWindow* window = tab->child_windows_[index]; cwindow_handle = cwindow_tracker_->Add(window); } } diff --git a/chrome/browser/browser_about_handler.cc b/chrome/browser/browser_about_handler.cc index 4b8ac12..a7073d2 100644 --- a/chrome/browser/browser_about_handler.cc +++ b/chrome/browser/browser_about_handler.cc @@ -198,7 +198,7 @@ BrowserAboutHandler::BrowserAboutHandler(Profile* profile, SiteInstance* instance, RenderViewHostFactory* render_view_factory) : WebContents(profile, instance, render_view_factory, MSG_ROUTING_NONE, NULL) { - type_ = TAB_CONTENTS_ABOUT_UI; + set_type(TAB_CONTENTS_ABOUT_UI); // We only need to register the AboutSource once and it is // kept globally. There is currently no way to remove a data source. diff --git a/chrome/browser/browser_commands.cc b/chrome/browser/browser_commands.cc index 063e99a..8a760c1 100644 --- a/chrome/browser/browser_commands.cc +++ b/chrome/browser/browser_commands.cc @@ -230,7 +230,7 @@ bool Browser::IsCommandEnabled(int id) const { } case IDC_STOP: { TabContents* current_tab = GetSelectedTabContents(); - return (current_tab && current_tab->IsLoading()); + return (current_tab && current_tab->is_loading()); } case IDC_CLOSETAB: { return !IsApplication(); @@ -514,24 +514,30 @@ void Browser::ExecuteCommand(int id) { case IDC_ZOOM_PLUS: { UserMetrics::RecordAction(L"ZoomPlus", profile_); TabContents* current_tab = GetSelectedTabContents(); - DCHECK(current_tab); - current_tab->AlterTextSize(text_zoom::TEXT_LARGER); + if (current_tab->AsWebContents()) { + current_tab->AsWebContents()->render_view_host()->AlterTextSize( + text_zoom::TEXT_LARGER); + } break; } case IDC_ZOOM_MINUS: { UserMetrics::RecordAction(L"ZoomMinus", profile_); TabContents* current_tab = GetSelectedTabContents(); - DCHECK(current_tab); - current_tab->AlterTextSize(text_zoom::TEXT_SMALLER); + if (current_tab->AsWebContents()) { + current_tab->AsWebContents()->render_view_host()->AlterTextSize( + text_zoom::TEXT_SMALLER); + } break; } case IDC_ZOOM_NORMAL: { UserMetrics::RecordAction(L"ZoomNormal", profile_); TabContents* current_tab = GetSelectedTabContents(); - DCHECK(current_tab); - current_tab->AlterTextSize(text_zoom::TEXT_STANDARD); + if (current_tab->AsWebContents()) { + current_tab->AsWebContents()->render_view_host()->AlterTextSize( + text_zoom::TEXT_STANDARD); + } break; } @@ -629,7 +635,7 @@ void Browser::ExecuteCommand(int id) { CharacterEncoding::GetCanonicalEncodingNameByCommandId(id); TabContents* current_tab = GetSelectedTabContents(); if (!cur_encoding_name.empty() && current_tab) - current_tab->SetPageEncoding(cur_encoding_name); + current_tab->set_encoding(cur_encoding_name); // Update user recently selected encoding list. std::wstring new_selected_encoding_list; if (CharacterEncoding::UpdateRecentlySelectdEncoding( diff --git a/chrome/browser/debugger/debugger_contents.cc b/chrome/browser/debugger/debugger_contents.cc index e8eb8963..74758ca 100644 --- a/chrome/browser/debugger/debugger_contents.cc +++ b/chrome/browser/debugger/debugger_contents.cc @@ -103,7 +103,7 @@ class DebuggerHandler : public DOMMessageHandler { DebuggerContents::DebuggerContents(Profile* profile, SiteInstance* instance) : DOMUIHost(profile, instance, NULL) { - type_ = TAB_CONTENTS_DEBUGGER; + set_type(TAB_CONTENTS_DEBUGGER); } void DebuggerContents::AttachMessageHandlers() { diff --git a/chrome/browser/dom_ui/dom_ui_host.cc b/chrome/browser/dom_ui/dom_ui_host.cc index b46affd..2541e71 100644 --- a/chrome/browser/dom_ui/dom_ui_host.cc +++ b/chrome/browser/dom_ui/dom_ui_host.cc @@ -20,7 +20,7 @@ DOMUIHost::DOMUIHost(Profile* profile, MSG_ROUTING_NONE, NULL) { // Implementors of this class will have a specific tab contents type. - type_ = TAB_CONTENTS_UNKNOWN_TYPE; + set_type(TAB_CONTENTS_UNKNOWN_TYPE); } DOMUIHost::~DOMUIHost() { diff --git a/chrome/browser/dom_ui/html_dialog_contents.cc b/chrome/browser/dom_ui/html_dialog_contents.cc index 60314f3..50dbc0c 100644 --- a/chrome/browser/dom_ui/html_dialog_contents.cc +++ b/chrome/browser/dom_ui/html_dialog_contents.cc @@ -13,7 +13,7 @@ HtmlDialogContents::HtmlDialogContents(Profile* profile, RenderViewHostFactory* rvf) : DOMUIHost(profile, instance, rvf), delegate_(NULL) { - type_ = TAB_CONTENTS_HTML_DIALOG; + set_type(TAB_CONTENTS_HTML_DIALOG); } HtmlDialogContents::~HtmlDialogContents() { diff --git a/chrome/browser/dom_ui/new_tab_ui.cc b/chrome/browser/dom_ui/new_tab_ui.cc index 3d0cdf1..c96a5b5 100644 --- a/chrome/browser/dom_ui/new_tab_ui.cc +++ b/chrome/browser/dom_ui/new_tab_ui.cc @@ -743,7 +743,7 @@ NewTabUIContents::NewTabUIContents(Profile* profile, motd_message_id_(0), incognito_(false), most_visited_handler_(NULL) { - type_ = TAB_CONTENTS_NEW_TAB_UI; + set_type(TAB_CONTENTS_NEW_TAB_UI); set_forced_title(l10n_util::GetString(IDS_NEW_TAB_TITLE)); if (profile->IsOffTheRecord()) diff --git a/chrome/browser/encoding_menu_controller_delegate.cc b/chrome/browser/encoding_menu_controller_delegate.cc index d7a7bc8..f5fd29a 100644 --- a/chrome/browser/encoding_menu_controller_delegate.cc +++ b/chrome/browser/encoding_menu_controller_delegate.cc @@ -28,7 +28,7 @@ bool EncodingMenuControllerDelegate::IsItemChecked(int id) const { TabContents* current_tab = browser_->GetSelectedTabContents(); if (!current_tab) return false; - std::wstring encoding_name = current_tab->GetEncoding(); + std::wstring encoding_name = current_tab->encoding(); if (encoding_name.empty()) encoding_name = profile->GetPrefs()->GetString(prefs::kDefaultCharset); switch (id) { diff --git a/chrome/browser/native_ui_contents.cc b/chrome/browser/native_ui_contents.cc index 0a1dfad..b54865c 100644 --- a/chrome/browser/native_ui_contents.cc +++ b/chrome/browser/native_ui_contents.cc @@ -322,7 +322,7 @@ void NativeUIContents::SetInitialFocus() { if (browser) browser->FocusLocationBar(); else - ::SetFocus(GetHWND()); + TabContents::SetInitialFocus(); // Will set focus to our HWND. } } diff --git a/chrome/browser/navigation_controller.cc b/chrome/browser/navigation_controller.cc index 38fcf65..0cecdc3 100644 --- a/chrome/browser/navigation_controller.cc +++ b/chrome/browser/navigation_controller.cc @@ -907,13 +907,13 @@ void NavigationController::DiscardPendingEntry() { NavigationEntry* last_entry = GetLastCommittedEntry(); if (last_entry && last_entry->tab_type() != active_contents_->type()) { TabContents* from_contents = active_contents_; - from_contents->SetActive(false); + 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_->SetActive(true); + 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 @@ -992,14 +992,14 @@ void NavigationController::NavigateToPendingEntry(bool reload) { pending_entry_->ssl() = NavigationEntry::SSLStatus(); if (from_contents && from_contents->type() != pending_entry_->tab_type()) - from_contents->SetActive(false); + from_contents->set_is_active(false); HWND parent = from_contents ? GetParent(from_contents->GetContainerHWND()) : 0; TabContents* contents = GetTabContentsCreateIfNecessary(parent, *pending_entry_); - contents->SetActive(true); + contents->set_is_active(true); active_contents_ = contents; if (from_contents && from_contents != contents) { diff --git a/chrome/browser/render_view_host_delegate.h b/chrome/browser/render_view_host_delegate.h index 036a88cb..eb1cef6 100644 --- a/chrome/browser/render_view_host_delegate.h +++ b/chrome/browser/render_view_host_delegate.h @@ -235,12 +235,6 @@ class RenderViewHostDelegate { virtual void GetHistoryListCount(int* back_list_count, int* forward_list_count) { } - // The page wants to open a plugin to display the given URL, of a certain - // content type. |reply_msg| contains the name of the plugin. - virtual void OpenChannelToPlugin(const GURL& url, - const std::string& mime_type, - IPC::Message* reply_msg) { } - // A file chooser should be shown. virtual void RunFileChooser(const std::wstring& default_file) { } diff --git a/chrome/browser/tab_contents.cc b/chrome/browser/tab_contents.cc index 17fd07c..7794b32 100644 --- a/chrome/browser/tab_contents.cc +++ b/chrome/browser/tab_contents.cc @@ -19,17 +19,29 @@ #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) - : is_loading_(false), - response_started_(false), - is_active_(true), - type_(type), + : type_(type), delegate_(NULL), controller_(NULL), - max_page_id_(-1), - saved_location_bar_state_(NULL), + is_loading_(false), + is_active_(true), is_crashed_(false), - shelf_visible_(false) { + waiting_for_response_(false), + saved_location_bar_state_(NULL), + shelf_visible_(false), + max_page_id_(-1), + capturing_contents_(false) { last_focused_view_storage_id_ = ChromeViews::ViewStorage::GetSharedInstance()->CreateStorageID(); } @@ -45,42 +57,49 @@ TabContents::~TabContents() { view_storage->RemoveView(last_focused_view_storage_id_); } -void TabContents::HideContents() { - // Hide the contents before adjusting its parent to avoid a full desktop - // flicker. - ShowWindow(GetContainerHWND(), SW_HIDE); - - // Reset the parent to NULL to ensure hidden tabs don't receive messages. - SetParent(GetContainerHWND(), NULL); +// static +void TabContents::RegisterUserPrefs(PrefService* prefs) { + prefs->RegisterBooleanPref(prefs::kBlockPopups, false); +} - // Remove any focus manager related information. - ChromeViews::FocusManager::UninstallFocusSubclass(GetContainerHWND()); - WasHidden(); +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. } -int32 TabContents::GetMaxPageID() { - if (GetSiteInstance()) - return GetSiteInstance()->max_page_id(); - else - return max_page_id_; -} +void TabContents::Destroy() { + // 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<int>(child_windows_.size()); + for (int i = size - 1; i >= 0; --i) { + ConstrainedWindow* window = child_windows_[i]; + if (window) + window->CloseConstrainedWindow(); + } -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); + // Notify any observer that have a reference on this tab contents. + NotificationService::current()->Notify(NOTIFY_TAB_CONTENTS_DESTROYED, + Source<TabContents>(this), + NotificationService::NoDetails()); - if (AsWebContents()) - AsWebContents()->process()->UpdateMaxPageID(page_id); - else - max_page_id_ = std::max(max_page_id_, page_id); -} + // 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()); -const std::wstring TabContents::GetDefaultTitle() const { - return l10n_util::GetString(IDS_DEFAULT_TAB_TITLE); + // 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) { @@ -88,19 +107,22 @@ void TabContents::SetupController(Profile* profile) { controller_ = new NavigationController(this, profile); } -const GURL& TabContents::GetURL() const { - DCHECK(controller_); - - static const GURL kEmptyURL; +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() : kEmptyURL; + return entry ? entry->display_url() : GURL::EmptyGURL(); } const std::wstring& TabContents::GetTitle() const { - DCHECK(controller_); - // We always want to 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 @@ -113,9 +135,31 @@ const std::wstring& TabContents::GetTitle() const { return EmptyWString(); } -SkBitmap TabContents::GetFavIcon() const { - DCHECK(controller_); +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_->GetLastCommittedEntry(); @@ -154,43 +198,51 @@ bool TabContents::GetSSLEVText(std::wstring* ev_text, return SSLManager::GetEVCertNames(*cert, ev_text, ev_tooltip_text); } -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::SetIsCrashed(bool state) { + if (state == is_crashed_) + return; + + is_crashed_ = state; + if (delegate_) + delegate_->ContentsStateChanged(this); } -void TabContents::Destroy() { - // 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<int>(child_windows_.size()); - for (int i = size - 1; i >= 0; --i) { - ConstrainedWindow* window = child_windows_[i]; - if (window) - window->CloseConstrainedWindow(); - } +void TabContents::NotifyNavigationStateChanged(unsigned changed_flags) { + if (delegate_) + delegate_->NavigationStateChanged(this, changed_flags); +} - // Notify any observer that have a reference on this tab contents. - NotificationService::current()->Notify(NOTIFY_TAB_CONTENTS_DESTROYED, +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<TabContents>(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(); +void TabContents::Activate() { + if (delegate_) + delegate_->ActivateContents(this); +} - delete this; +void TabContents::OpenURL(const GURL& url, + WindowOpenDisposition disposition, + PageTransition::Type transition) { + if (delegate_) + delegate_->OpenURLFromTab(this, url, disposition, transition); +} - controller->TabContentsWasDestroyed(type); +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( @@ -236,66 +288,6 @@ void TabContents::AddConstrainedPopup(TabContents* new_contents, RepositionSupressedPopupsToFit(new_size); } -void TabContents::SetIsLoading(bool is_loading, - LoadNotificationDetails* details) { - if (is_loading == is_loading_) - return; - - is_loading_ = is_loading; - response_started_ = 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<NavigationController>(this->controller()), - details ? Details<LoadNotificationDetails>(details) : - NotificationService::NoDetails()); -} - -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; -} - -void TabContents::NotifyNavigationStateChanged(unsigned changed_flags) { - if (delegate_) - delegate_->NavigationStateChanged(this, changed_flags); -} - -static 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; -} - -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<TabContents>(this), - NotificationService::NoDetails()); -} - -void TabContents::Activate() { - if (delegate_) - delegate_->ActivateContents(this); -} - void TabContents::CloseAllSuppressedPopups() { // Close all auto positioned child windows to "clean up" the workspace. int count = static_cast<int>(child_windows_.size()); @@ -306,88 +298,20 @@ void TabContents::CloseAllSuppressedPopups() { } } -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); - } -} - - -/////////////////////////////////////////////////////////////////////////////// -// TabContents, ConstrainedTabContentsDelegate implementation: - -void TabContents::AddNewContents(ConstrainedWindow* window, - TabContents* new_contents, - WindowOpenDisposition disposition, - const gfx::Rect& initial_pos, - bool user_gesture) { - AddNewContents(new_contents, disposition, initial_pos, user_gesture); -} - -void TabContents::OpenURL(ConstrainedWindow* window, - const GURL& url, - WindowOpenDisposition disposition, - PageTransition::Type transition) { - OpenURL(url, disposition, transition); -} - -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 (::IsWindow(GetContainerHWND())) { - CRect client_rect; - GetClientRect(GetContainerHWND(), &client_rect); - RepositionSupressedPopupsToFit( - gfx::Size(client_rect.Width(), client_rect.Height())); - } -} - -void TabContents::DetachContents(ConstrainedWindow* window, - TabContents* contents, - const gfx::Rect& contents_bounds, - const gfx::Point& mouse_pt, - int frame_component) { - WillClose(window); - if (delegate_) { - delegate_->StartDraggingDetachedContents( - this, contents, contents_bounds, mouse_pt, frame_component); - } -} +void TabContents::HideContents() { + // Hide the contents before adjusting its parent to avoid a full desktop + // flicker. + ShowWindow(GetContainerHWND(), SW_HIDE); -void TabContents::DidMoveOrResize(ConstrainedWindow* window) { - UpdateWindow(GetContainerHWND()); -} + // Reset the parent to NULL to ensure hidden tabs don't receive messages. + SetParent(GetContainerHWND(), NULL); -/////////////////////////////////////////////////////////////////////////////// -// PageNavigator methods + // Remove any focus manager related information. + ChromeViews::FocusManager::UninstallFocusSubclass(GetContainerHWND()); -void TabContents::OpenURL(const GURL& url, - WindowOpenDisposition disposition, - PageTransition::Type transition) { - if (delegate_) - delegate_->OpenURLFromTab(this, url, disposition, transition); + WasHidden(); } -/////////////////////////////////////////////////////////////////////////////// - void TabContents::Focus() { ChromeViews::FocusManager* focus_manager = ChromeViews::FocusManager::GetFocusManager(GetContainerHWND()); @@ -456,21 +380,8 @@ void TabContents::RestoreFocus() { } } -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() - ChromeViews::NativeScrollBar::GetVerticalScrollBarWidth(), - new_size.height()); - int window_count = static_cast<int>(child_windows_.size()); - for (int i = window_count - 1; i >= 0; --i) { - ConstrainedWindow* window = child_windows_.at(i); - if (window->IsSuppressedConstrainedWindow()) - window->RepositionConstrainedWindowTo(anchor_position); - } +void TabContents::SetInitialFocus() { + ::SetFocus(GetContainerHWND()); } void TabContents::SetDownloadShelfVisible(bool visible) { @@ -491,40 +402,31 @@ void TabContents::SetDownloadShelfVisible(bool visible) { ToolbarSizeChanged(false); } -void TabContents::ReleaseDownloadShelfView() { - download_shelf_view_.release(); -} - -void TabContents::SetInitialFocus() { - ::SetFocus(GetContainerHWND()); +void TabContents::ToolbarSizeChanged(bool is_animating) { + TabContentsDelegate* d = delegate(); + if (d) + d->ToolbarSizeChanged(this, is_animating); } -void TabContents::SetIsCrashed(bool state) { - if (state == is_crashed_) - return; +void TabContents::OnStartDownload(DownloadItem* download) { + DCHECK(download); + TabContents* tab_contents = this; - is_crashed_ = state; - if (delegate_) - delegate_->ContentsStateChanged(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; -bool TabContents::IsCrashed() const { - return is_crashed_; -} + // GetDownloadShelfView creates the download shelf if it was not yet created. + tab_contents->GetDownloadShelfView()->AddDownload(download); + tab_contents->SetDownloadShelfVisible(true); -bool TabContents::SupportsURL(GURL* url) { - GURL u(*url); - if (TabContents::TypeForURL(&u) == type()) { - *url = u; - return 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); } - return false; -} - -void TabContents::ToolbarSizeChanged(bool is_animating) { - TabContentsDelegate* d = delegate(); - if (d) - d->ToolbarSizeChanged(this, is_animating); } DownloadShelfView* TabContents::GetDownloadShelfView() { @@ -542,6 +444,51 @@ void TabContents::MigrateShelfViewFrom(TabContents* tab_contents) { tab_contents->ReleaseDownloadShelfView(); } +void TabContents::AddNewContents(ConstrainedWindow* window, + TabContents* new_contents, + WindowOpenDisposition disposition, + const gfx::Rect& initial_pos, + bool user_gesture) { + AddNewContents(new_contents, disposition, initial_pos, user_gesture); +} + +void TabContents::OpenURL(ConstrainedWindow* window, + const GURL& url, + WindowOpenDisposition disposition, + PageTransition::Type transition) { + OpenURL(url, disposition, transition); +} + +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 (::IsWindow(GetContainerHWND())) { + CRect client_rect; + GetClientRect(GetContainerHWND(), &client_rect); + RepositionSupressedPopupsToFit( + gfx::Size(client_rect.Width(), client_rect.Height())); + } +} + +void TabContents::DetachContents(ConstrainedWindow* window, + TabContents* contents, + const gfx::Rect& contents_bounds, + const gfx::Point& mouse_pt, + int frame_component) { + WillClose(window); + if (delegate_) { + delegate_->StartDraggingDetachedContents( + this, contents, contents_bounds, mouse_pt, frame_component); + } +} + +void TabContents::DidMoveOrResize(ConstrainedWindow* window) { + UpdateWindow(GetContainerHWND()); +} + // static void TabContents::MigrateShelfView(TabContents* from, TabContents* to) { bool was_shelf_visible = from->IsDownloadShelfVisible(); @@ -550,8 +497,46 @@ void TabContents::MigrateShelfView(TabContents* from, TabContents* to) { to->SetDownloadShelfVisible(was_shelf_visible); } -// static -void TabContents::RegisterUserPrefs(PrefService* prefs) { - prefs->RegisterBooleanPref(prefs::kBlockPopups, false); +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<NavigationController>(this->controller()), + details ? Details<LoadNotificationDetails>(details) : + NotificationService::NoDetails()); } +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() - + ChromeViews::NativeScrollBar::GetVerticalScrollBarWidth(), + new_size.height()); + int window_count = static_cast<int>(child_windows_.size()); + for (int i = window_count - 1; i >= 0; --i) { + ConstrainedWindow* window = child_windows_.at(i); + if (window->IsSuppressedConstrainedWindow()) + window->RepositionConstrainedWindowTo(anchor_position); + } +} + +void TabContents::ReleaseDownloadShelfView() { + download_shelf_view_.release(); +} diff --git a/chrome/browser/tab_contents.h b/chrome/browser/tab_contents.h index 5630cc4..187822b 100644 --- a/chrome/browser/tab_contents.h +++ b/chrome/browser/tab_contents.h @@ -17,8 +17,8 @@ #include "chrome/common/text_zoom.h" namespace gfx { - class Rect; - class Size; +class Rect; +class Size; } class DOMUIHost; @@ -50,14 +50,8 @@ class WebContents; // 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 ConstrainedTabContentsDelegate, - public NotificationObserver { - // Used to access the child_windows_ (ConstrainedWindowList) for testing - // automation purposes. - friend class AutomationProvider; - + public ConstrainedTabContentsDelegate { public: // Flags passed to the TabContentsDelegate.NavigationStateChanged to tell it // what has changed. Combine them to update more than one thing. @@ -71,6 +65,11 @@ class TabContents : public PageNavigator, 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, @@ -90,28 +89,24 @@ class TabContents : public PageNavigator, static TabContentsFactory* RegisterFactory(TabContentsType type, TabContentsFactory* factory); - // 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(HWND parent_hwnd, const gfx::Rect& initial_bounds) {} + // Creation & destruction ---------------------------------------------------- - // 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; } + // Request this tab to shut down. This kills the tab's NavigationController, + // which then Destroy()s all tabs it controls. + void CloseContents(); - // Returns the bounds of this TabContents in the screen coordinate system. - virtual void GetContainerBounds(gfx::Rect *out) const { - out->SetRect(0, 0, 0, 0); - } + // 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(); - // Show, Hide and Size the TabContents. - // TODO(beng): (Cleanup) Show/Size TabContents should be made to actually - // show and size the View. For simplicity sake, for now they're - // just empty. This is currently a bit of a mess and is just a - // band-aid. - virtual void ShowContents() {} - virtual void HideContents(); - virtual void SizeContents(const gfx::Size& size) {} + // Intrinsic tab state ------------------------------------------------------- + // Returns the type of tab this is. See also the As* functions following. TabContentsType type() const { return type_; } // Returns this object as a WebContents if it is one, and NULL otherwise. @@ -123,40 +118,7 @@ class TabContents : public PageNavigator, } // Returns this object as a DOMUIHost if it is one, and NULL otherwise. - virtual DOMUIHost* AsDOMUIHost() { return NULL ; } - - // 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 the url should be displayed within the browser. If false - // is returned, the URL field is blank and grabs focus to invite the user - // to type a new url - 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; - } + virtual DOMUIHost* AsDOMUIHost() { return NULL; } TabContentsDelegate* delegate() const { return delegate_; } void set_delegate(TabContentsDelegate* d) { delegate_ = d; } @@ -183,15 +145,17 @@ class TabContents : public PageNavigator, return controller_ ? controller_->profile() : NULL; } - // For use when switching tabs, these functions allow the tab contents to - // hold the per-tab state of the location bar. The tab contents takes - // ownership of the pointer. - void set_saved_location_bar_state(const AutocompleteEditState* state) { - saved_location_bar_state_.reset(state); - } - const AutocompleteEditState* saved_location_bar_state() const { - return saved_location_bar_state_.get(); - } + // 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 @@ -199,6 +163,38 @@ class TabContents : public PageNavigator, 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; @@ -208,75 +204,72 @@ class TabContents : public PageNavigator, // 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; - // 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(); - - // 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( - ChromeViews::WindowDelegate* window_delegate, - ChromeViews::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); + // Returns a human-readable description the tab's loading state. + virtual std::wstring GetStatusText() const { return std::wstring(); } - // An asynchronous call to trigger the string search in the page. - // It sends an IPC message to the Renderer that handles the string - // search, selecting the matches and setting the caret positions. - // This function also starts the asynchronous scoping effort. - virtual void StartFinding(int request_id, - const std::wstring& string, - bool forward, bool match_case, - bool find_next) { } + const std::wstring& encoding() { return encoding_name_; } + void set_encoding(const std::wstring& encoding_name) { + encoding_name_ = encoding_name; + } - // An asynchronous call to stop the string search in the page. If - // |clear_selection| is true, it will also clear the selection on the - // focused frame. - virtual void StopFinding(bool clear_selection) { } + // Return whether this tab contents is loading a resource. + bool is_loading() const { return is_loading_; } - // Asynchronous calls to change the text zoom level. - virtual void AlterTextSize(text_zoom::TextSize size) { } + // 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_; } - // Asynchronous call to turn on/off encoding auto detector. - virtual void SetEncodingAutoDetector(bool encoding_auto_detector) { } + // Internal state ------------------------------------------------------------ - // Asynchronous call to change page encoding. - virtual void SetPageEncoding(const std::wstring& encoding_name) { } + // For use when switching tabs, these functions allow the tab contents to + // hold the per-tab state of the location bar. The tab contents takes + // ownership of the pointer. + void set_saved_location_bar_state(const AutocompleteEditState* state) { + saved_location_bar_state_.reset(state); + } + const AutocompleteEditState* saved_location_bar_state() const { + return saved_location_bar_state_.get(); + } - // Return whether this tab contents is loading a resource. - bool is_loading() const { return is_loading_; } + // 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; } - // Returns whether this tab contents is waiting for an first-response from - // and external resource. - bool response_started() const { return response_started_; } + // 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. - virtual void SetActive(bool active) { is_active_ = active; } bool is_active() const { return is_active_; } + void set_is_active(bool active) { is_active_ = active; } + + // 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, + 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 @@ -294,21 +287,57 @@ class TabContents : public PageNavigator, // Stop any pending navigation. virtual void Stop() {} - // Convenience method for notifying the delegate of a navigation state - // change. See TabContentsDelegate. - void NotifyNavigationStateChanged(unsigned changed_flags); + // An asynchronous call to trigger the string search in the page. + // It sends an IPC message to the Renderer that handles the string + // search, selecting the matches and setting the caret positions. + // This function also starts the asynchronous scoping effort. + virtual void StartFinding(int request_id, + const std::wstring& string, + bool forward, bool match_case, + bool find_next) { } - // Invoked when the tab contents becomes selected. If you override, be sure - // and invoke super's implementation. - virtual void DidBecomeSelected(); + // An asynchronous call to stop the string search in the page. If + // |clear_selection| is true, it will also clear the selection on the + // focused frame. + virtual void StopFinding(bool clear_selection) { } - // Invoked when the tab contents becomes hidden. - // NOTE: If you override this, call the superclass version too! - virtual void WasHidden(); + // 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() { } - // Activates this contents within its containing window, bringing that window - // to the foreground if necessary. - virtual void Activate(); + // 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( + ChromeViews::WindowDelegate* window_delegate, + ChromeViews::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 @@ -316,41 +345,34 @@ class TabContents : public PageNavigator, // of unwanted popups. void CloseAllSuppressedPopups(); - // Displays the download shelf and animation when a download occurs. - void OnStartDownload(DownloadItem* download); + // Show, Hide and Size the TabContents. + // TODO(beng): (Cleanup) Show/Size TabContents should be made to actually + // show and size the View. For simplicity sake, for now they're + // just empty. This is currently a bit of a mess and is just a + // band-aid. + virtual void ShowContents() {} + virtual void HideContents(); + virtual void SizeContents(const gfx::Size& size) {} - // ConstrainedTabContentsDelegate methods: - virtual void AddNewContents(ConstrainedWindow* window, - TabContents* contents, - WindowOpenDisposition disposition, - const gfx::Rect& initial_pos, - bool user_gesture); - virtual void OpenURL(ConstrainedWindow* window, - const GURL& url, - WindowOpenDisposition disposition, - PageTransition::Type transition); - virtual void WillClose(ConstrainedWindow* window); - virtual void DetachContents(ConstrainedWindow* window, - TabContents* contents, - const gfx::Rect& contents_bounds, - const gfx::Point& mouse_pt, - int frame_component); - virtual void DidMoveOrResize(ConstrainedWindow* window); + // Views and focus ----------------------------------------------------------- // Returns the actual window that is focused when this TabContents is shown. virtual HWND GetContentHWND() { return GetContainerHWND(); } - // PageNavigator methods: - virtual void OpenURL(const GURL& url, - WindowOpenDisposition disposition, - PageTransition::Type transition); + // 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(HWND parent_hwnd, const gfx::Rect& initial_bounds) {} - // NotificationObserver implementation. - virtual void Observe(NotificationType type, - const NotificationSource& source, - const NotificationDetails& details) { } + // 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(); @@ -362,20 +384,16 @@ class TabContents : public PageNavigator, // invoked, SetInitialFocus is invoked. virtual void RestoreFocus(); - // 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; - } - - // Returns the View to display at the top of the tab. - virtual InfoBarView* GetInfoBarView() { return NULL; } - - // Returns whether the info bar is visible. - // If the visibility dynamically changes, invoke ToolbarSizeChanged - // on the delegate. Which forces the frame to layout if size has changed. - virtual bool IsInfoBarVisible() { return false; } + // 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 @@ -388,54 +406,18 @@ class TabContents : public PageNavigator, // the focus is passed to the RootView. virtual ChromeViews::RootView* GetContentsRootView() { return NULL; } - // Invoked the first time this tab is getting the focus through TAB traversal. - virtual void SetInitialFocus(bool reverse) { } - + // Toolbars and such --------------------------------------------------------- + // Returns whether the bookmark bar should be visible. virtual bool IsBookmarkBarAlwaysVisible() { return false; } - // Called before and after capturing an image of this tab contents. The tab - // contents may be temporarily re-parented after WillCaptureContents. - virtual void WillCaptureContents() {} - virtual void DidCaptureContents() {} - - // Returns true if the tab is currently loading a resource. - virtual bool IsLoading() const { return is_loading_; } - - // Returns a human-readable description the tab's loading state. - virtual std::wstring GetStatusText() const { return std::wstring(); } - - const std::wstring& GetEncoding() { return encoding_name_; } - void SetEncoding(const std::wstring& encoding_name) { - encoding_name_ = encoding_name; - } - - // Changes the IsCrashed state and notifies the delegate as needed. - void SetIsCrashed(bool state); - - // Return whether this tab should be considered crashed. - bool IsCrashed() const; - - // 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); + // Returns the View to display at the top of the tab. + virtual InfoBarView* GetInfoBarView() { return NULL; } - // 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() { } + // Returns whether the info bar is visible. + // If the visibility dynamically changes, invoke ToolbarSizeChanged + // on the delegate. Which forces the frame to layout if size has changed. + virtual bool IsInfoBarVisible() { return false; } // Whether or not the shelf view is visible. virtual void SetDownloadShelfVisible(bool visible); @@ -444,6 +426,9 @@ class TabContents : public PageNavigator, // 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(); @@ -457,13 +442,36 @@ class TabContents : public PageNavigator, // want to generalize this if we need to migrate some other state. static void MigrateShelfView(TabContents* from, TabContents* to); - static void RegisterUserPrefs(PrefService* prefs); + // ConstrainedTabContentsDelegate -------------------------------------------- + + virtual void AddNewContents(ConstrainedWindow* window, + TabContents* contents, + WindowOpenDisposition disposition, + const gfx::Rect& initial_pos, + bool user_gesture); + virtual void OpenURL(ConstrainedWindow* window, + const GURL& url, + WindowOpenDisposition disposition, + PageTransition::Type transition); + virtual void WillClose(ConstrainedWindow* window); + virtual void DetachContents(ConstrainedWindow* window, + TabContents* contents, + const gfx::Rect& contents_bounds, + const gfx::Point& mouse_pt, + int frame_component); + virtual void DidMoveOrResize(ConstrainedWindow* window); protected: 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 @@ -472,14 +480,16 @@ class TabContents : public PageNavigator, // Protected so that others don't try to delete this directly. virtual ~TabContents(); - // Set focus on the initial component. This is invoked from - // RestoreFocus if SetLastFocusOwner has not yet been invoked. + // 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) - void SetIsLoading(bool is_loading, LoadNotificationDetails* details); + // (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 @@ -491,26 +501,33 @@ class TabContents : public PageNavigator, // invoke TabContents::ReleaseDownloadShelfView(). virtual void ReleaseDownloadShelfView(); - bool is_loading_; // true if currently loading a resource. - bool response_started_; // true if waiting for a response. - bool is_active_; - bool is_crashed_; // true if the tab is considered crashed. + // 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<ConstrainedWindow*> ConstrainedWindowList; ConstrainedWindowList child_windows_; - TabContentsType type_; - private: - ConstrainedWindowList child_windows() const { return child_windows_; } + // Data ---------------------------------------------------------------------- - // Clear the last focus view and unregister the notification associated with - // it. - void ClearLastFocusedView(); + TabContentsType type_; TabContentsDelegate* delegate_; NavigationController* controller_; + // 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_; + scoped_ptr<const AutocompleteEditState> saved_location_bar_state_; // The download shelf view (view at the bottom of the page). @@ -528,7 +545,11 @@ class TabContents : public PageNavigator, int last_focused_view_storage_id_; std::wstring encoding_name_; + + // See capturing_contents() above. + bool capturing_contents_; + + DISALLOW_COPY_AND_ASSIGN(TabContents); }; #endif // CHROME_BROWSER_TAB_CONTENTS_H_ - diff --git a/chrome/browser/view_source_contents.cc b/chrome/browser/view_source_contents.cc index 8e0c052..6ba3fc7 100644 --- a/chrome/browser/view_source_contents.cc +++ b/chrome/browser/view_source_contents.cc @@ -9,7 +9,7 @@ ViewSourceContents::ViewSourceContents(Profile* profile, SiteInstance* instance) : WebContents(profile, instance, NULL, MSG_ROUTING_NONE, NULL) { - type_ = TAB_CONTENTS_VIEW_SOURCE; + set_type(TAB_CONTENTS_VIEW_SOURCE); } void ViewSourceContents::RendererCreated(RenderViewHost* host) { diff --git a/chrome/browser/views/tab_contents_container_view.cc b/chrome/browser/views/tab_contents_container_view.cc index 582726a..d6881652 100644 --- a/chrome/browser/views/tab_contents_container_view.cc +++ b/chrome/browser/views/tab_contents_container_view.cc @@ -170,7 +170,7 @@ bool TabContentsContainerView::GetAccessibleRole(VARIANT* role) { bool TabContentsContainerView::ShouldLookupAccelerators( const ChromeViews::KeyEvent& e) { - if (tab_contents_ && !tab_contents_->IsCrashed() && + if (tab_contents_ && !tab_contents_->is_crashed() && tab_contents_->AsWebContents()) return false; return true; diff --git a/chrome/browser/views/tabs/dragged_tab_controller.cc b/chrome/browser/views/tabs/dragged_tab_controller.cc index 82c002e..cd8bd69 100644 --- a/chrome/browser/views/tabs/dragged_tab_controller.cc +++ b/chrome/browser/views/tabs/dragged_tab_controller.cc @@ -463,7 +463,7 @@ void DraggedTabController::Attach(TabStrip* attached_tabstrip, original_delegate_ = NULL; // Return the TabContents' to normalcy. - dragged_contents_->DidCaptureContents(); + dragged_contents_->set_capturing_contents(false); // We need to ask the TabStrip we're attached to to ensure that the ideal // bounds for all its tabs are correctly generated, because the calculation @@ -497,7 +497,7 @@ void DraggedTabController::Attach(TabStrip* attached_tabstrip, void DraggedTabController::Detach() { // Prevent the TabContents' HWND from being hidden by any of the model // operations performed during the drag. - dragged_contents_->WillCaptureContents(); + dragged_contents_->set_capturing_contents(true); // Update the Model. TabStripModel* attached_model = attached_tabstrip_->model(); diff --git a/chrome/browser/views/tabs/tab_renderer.cc b/chrome/browser/views/tabs/tab_renderer.cc index 2dd430d..e4505a3 100644 --- a/chrome/browser/views/tabs/tab_renderer.cc +++ b/chrome/browser/views/tabs/tab_renderer.cc @@ -270,7 +270,7 @@ void TabRenderer::UpdateData(TabContents* contents) { data_.off_the_record = contents->profile()->IsOffTheRecord(); data_.show_icon = contents->ShouldDisplayFavIcon(); data_.show_download_icon = contents->IsDownloadShelfVisible(); - data_.crashed = contents->IsCrashed(); + data_.crashed = contents->is_crashed(); } void TabRenderer::UpdateFromModel() { diff --git a/chrome/browser/views/tabs/tab_strip.cc b/chrome/browser/views/tabs/tab_strip.cc index 768604c..ec1a705 100644 --- a/chrome/browser/views/tabs/tab_strip.cc +++ b/chrome/browser/views/tabs/tab_strip.cc @@ -1277,7 +1277,7 @@ void TabStrip::LoadingAnimationCallback() { TabContents* contents = model_->GetTabContentsAt(index); if (!contents || !contents->is_loading()) { current_tab->ValidateLoadingAnimation(Tab::ANIMATION_NONE); - } else if (contents->response_started()) { + } else if (contents->waiting_for_response()) { current_tab->ValidateLoadingAnimation(Tab::ANIMATION_WAITING); } else { current_tab->ValidateLoadingAnimation(Tab::ANIMATION_LOADING); diff --git a/chrome/browser/web_contents.cc b/chrome/browser/web_contents.cc index 9549f4b..782df56 100644 --- a/chrome/browser/web_contents.cc +++ b/chrome/browser/web_contents.cc @@ -5,6 +5,7 @@ #include "chrome/browser/web_contents.h" #include "base/command_line.h" +#include "base/compiler_specific.h" #include "base/file_version_info.h" #include "chrome/app/locales/locale_settings.h" #include "chrome/browser/bookmarks/bookmark_model.h" @@ -50,6 +51,45 @@ #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. + namespace { // Amount of time we wait between when a key event is received and the renderer @@ -104,10 +144,13 @@ void InitWebContentsClass() { } } -} // namespace +// 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); +} -/////////////////////////////////////////////////////////////////////////////// -// WebContents +} // namespace class WebContents::GearsCreateShortcutCallbackFunctor { public: @@ -127,6 +170,53 @@ class WebContents::GearsCreateShortcutCallbackFunctor { WebContents* contents_; }; +WebContents::WebContents(Profile* profile, + SiteInstance* site_instance, + RenderViewHostFactory* render_view_factory, + int routing_id, + HANDLE modal_dialog_event) + : TabContents(TAB_CONTENTS_WEB), + ALLOW_THIS_IN_INITIALIZER_LIST( + render_manager_(render_view_factory, this, this)), + render_view_factory_(render_view_factory), + has_page_title_(false), + info_bar_visible_(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)), + crashed_plugin_info_bar_(NULL), + 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()); +} + +WebContents::~WebContents() { + if (web_app_.get()) + web_app_->RemoveObserver(this); + if (pending_install_.callback_functor) + pending_install_.callback_functor->Cancel(); +} + // static void WebContents::RegisterUserPrefs(PrefService* prefs) { prefs->RegisterBooleanPref(prefs::kAlternateErrorPagesEnabled, true); @@ -181,104 +271,16 @@ void WebContents::RegisterUserPrefs(PrefService* prefs) { IDS_STATIC_ENCODING_LIST); } -WebContents::WebContents(Profile* profile, - SiteInstance* site_instance, - RenderViewHostFactory* render_view_factory, - int routing_id, - HANDLE modal_dialog_event) - : TabContents(TAB_CONTENTS_WEB), -#pragma warning(suppress: 4355) // Okay to pass "this" here. - render_manager_(render_view_factory, this, this), - render_view_factory_(render_view_factory), - has_page_title_(false), - info_bar_visible_(false), - is_starred_(false), - printing_(*this), - notify_disconnection_(false), - message_box_active_(CreateEvent(NULL, TRUE, FALSE, NULL)), - capturing_contents_(false), -#pragma warning(suppress: 4355) // Okay to pass "this" here. - fav_icon_helper_(this), - crashed_plugin_info_bar_(NULL), - 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()); -} - -WebContents::~WebContents() { - if (web_app_.get()) - web_app_->RemoveObserver(this); - if (pending_install_.callback_functor) - pending_install_.callback_functor->Cancel(); -} - -void WebContents::CreateView(HWND parent_hwnd, - const gfx::Rect& initial_bounds) { - set_delete_on_destroy(false); - HWNDViewContainer::Init(parent_hwnd, initial_bounds, false); - - // Remove the root view drop target so we can register our own. - RevokeDragDrop(GetHWND()); - drop_target_ = new WebDropTarget(GetHWND(), this); -} - -void WebContents::GetContainerBounds(gfx::Rect *out) const { - CRect r; - GetBounds(&r, false); - *out = r; -} - -void WebContents::ShowContents() { - if (view()) - view()->DidBecomeSelected(); - - // Loop through children and send DidBecomeSelected to them, too. - int count = static_cast<int>(child_windows_.size()); - for (int i = count - 1; i >= 0; --i) { - ConstrainedWindow* window = child_windows_.at(i); - window->DidBecomeSelected(); - } - - // If we have a FindInPage dialog, notify it that its tab was selected. - if (find_in_page_controller_.get()) - find_in_page_controller_->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(); +PasswordManager* WebContents::GetPasswordManager() { + if (password_manager_.get() == NULL) + password_manager_.reset(new PasswordManager(this)); + return password_manager_.get(); } -void WebContents::SizeContents(const gfx::Size& size) { - if (view()) - view()->SetSize(size); - if (find_in_page_controller_.get()) - find_in_page_controller_->RespondToResize(size); - RepositionSupressedPopupsToFit(size); +PluginInstaller* WebContents::GetPluginInstaller() { + if (plugin_installer_.get() == NULL) + plugin_installer_.reset(new PluginInstaller(this)); + return plugin_installer_.get(); } void WebContents::Destroy() { @@ -316,290 +318,43 @@ void WebContents::Destroy() { TabContents::Destroy(); } -/////////////////////////////////////////////////////////////////////////////// -// Event Handlers - -void WebContents::OnDestroy() { - if (drop_target_.get()) { - RevokeDragDrop(GetHWND()); - drop_target_ = NULL; - } -} - -void WebContents::OnWindowPosChanged(WINDOWPOS* window_pos) { - if (window_pos->flags & SWP_HIDEWINDOW) { - HideContents(); - } 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) - ShowContents(); - // 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)) { - gfx::Size size(window_pos->cx, window_pos->cy); - SizeContents(size); - } - - // If we have a FindInPage dialog, notify it that the window changed. - if (find_in_page_controller_.get() && find_in_page_controller_->IsVisible()) - find_in_page_controller_->MoveWindowIfNecessary(gfx::Rect()); - } -} - -void WebContents::OnPaint(HDC junk_dc) { - if (render_view_host() && !render_view_host()->IsRenderViewLive()) { - if (!sad_tab_.get()) - sad_tab_.reset(new SadTabView); - CRect cr; - GetClientRect(&cr); - sad_tab_->SetBounds(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); -} - -LRESULT WebContents::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 (delegate()) - delegate()->ActivateContents(this); - break; - case WM_MOUSEMOVE: - // Let our delegate know that the mouse moved (useful for resetting status - // bubble state). - if (delegate()) - delegate()->ContentsMouseEvent(this, WM_MOUSEMOVE); - break; - default: - break; - } - - return 0; +SiteInstance* WebContents::GetSiteInstance() const { + return render_manager_.current_host()->site_instance(); } -void WebContents::OnMouseLeave() { - // Let our delegate know that the mouse moved (useful for resetting status - // bubble state). - if (delegate()) - delegate()->ContentsMouseEvent(this, WM_MOUSELEAVE); - 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 WebContents::OnReflectedMessage(UINT msg, WPARAM w_param, - LPARAM l_param) { - MSG* message = reinterpret_cast<MSG*>(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 WebContents::OnSize(UINT param, const CSize& size) { - HWNDViewContainer::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.nTrackPos = 50; - - ::SetScrollInfo(GetHWND(), SB_HORZ, &si, FALSE); - ::SetScrollInfo(GetHWND(), SB_VERT, &si, FALSE); -} - -LRESULT WebContents::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 WebContents::OnNCPaint(HRGN rgn) { - // Suppress default WM_NCPAINT handling. We don't need to do anything - // here since the view will draw everything correctly. -} - -void WebContents::OnHScroll(int scroll_type, short position, HWND scrollbar) { - ScrollCommon(WM_HSCROLL, scroll_type, position, scrollbar); -} - -void WebContents::OnVScroll(int scroll_type, short position, HWND scrollbar) { - ScrollCommon(WM_VSCROLL, scroll_type, position, scrollbar); -} - -void WebContents::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); - } -} - -bool WebContents::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 WebContents::WheelZoom(int distance) { - if (delegate()) { - bool zoom_in = distance > 0; - delegate()->ContentsZoomChange(zoom_in); +SkBitmap WebContents::GetFavIcon() { + if (web_app_.get() && IsWebApplicationActive()) { + SkBitmap app_icon = web_app_->GetFavIcon(); + if (!app_icon.isNull()) + return app_icon; } + return TabContents::GetFavIcon(); } -void WebContents::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 (view()) { - HWND inner_hwnd = view()->GetPluginHWND(); - if (::IsWindow(inner_hwnd)) - ::SetFocus(inner_hwnd); - } -} +std::wstring WebContents::GetStatusText() const { + if (!is_loading() || load_state_ == net::LOAD_STATE_IDLE) + return std::wstring(); -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; + 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 } - // 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)) - 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(); + return std::wstring(); } -/////////////////////////////////////////////////////////////////////////////// - -// 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. - bool WebContents::NavigateToPendingEntry(bool reload) { NavigationEntry* entry = controller()->GetPendingEntry(); RenderViewHost* dest_render_view_host = render_manager_.Navigate(*entry); @@ -637,6 +392,31 @@ void WebContents::Stop() { printing_.Stop(); } +void WebContents::StartFinding(int request_id, + const std::wstring& search_string, + bool forward, + bool match_case, + bool find_next) { + render_view_host()->StartFinding(request_id, search_string, forward, + match_case, find_next); +} + +void WebContents::StopFinding(bool clear_selection) { + render_view_host()->StopFinding(clear_selection); +} + +void WebContents::Cut() { + render_view_host()->Cut(); +} + +void WebContents::Copy() { + render_view_host()->Copy(); +} + +void WebContents::Paste() { + render_view_host()->Paste(); +} + void WebContents::DidBecomeSelected() { TabContents::DidBecomeSelected(); @@ -647,7 +427,7 @@ void WebContents::DidBecomeSelected() { } void WebContents::WasHidden() { - if (!capturing_contents_) { + 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 @@ -671,17 +451,78 @@ void WebContents::WasHidden() { TabContents::WasHidden(); } -void WebContents::StartFinding(int request_id, - const std::wstring& search_string, - bool forward, - bool match_case, - bool find_next) { - render_view_host()->StartFinding(request_id, search_string, forward, - match_case, find_next); +void WebContents::ShowContents() { + if (view()) + view()->DidBecomeSelected(); + + // Loop through children and send DidBecomeSelected to them, too. + int count = static_cast<int>(child_windows_.size()); + for (int i = count - 1; i >= 0; --i) { + ConstrainedWindow* window = child_windows_.at(i); + window->DidBecomeSelected(); + } + + // If we have a FindInPage dialog, notify it that its tab was selected. + if (find_in_page_controller_.get()) + find_in_page_controller_->DidBecomeSelected(); } -void WebContents::StopFinding(bool clear_selection) { - render_view_host()->StopFinding(clear_selection); +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::SizeContents(const gfx::Size& size) { + if (view()) + view()->SetSize(size); + if (find_in_page_controller_.get()) + find_in_page_controller_->RespondToResize(size); + RepositionSupressedPopupsToFit(size); +} + +HWND WebContents::GetContentHWND() { + if (!view()) + return NULL; + return view()->GetPluginHWND(); +} + +void WebContents::CreateView(HWND parent_hwnd, + const gfx::Rect& initial_bounds) { + set_delete_on_destroy(false); + HWNDViewContainer::Init(parent_hwnd, initial_bounds, false); + + // Remove the root view drop target so we can register our own. + RevokeDragDrop(GetHWND()); + drop_target_ = new WebDropTarget(GetHWND(), this); +} + +void WebContents::GetContainerBounds(gfx::Rect *out) const { + CRect r; + GetBounds(&r, false); + *out = r; +} + +InfoBarView* WebContents::GetInfoBarView() { + if (info_bar_view_.get() == NULL) { + info_bar_view_.reset(new InfoBarView(this)); + // The WebContents owns the info-bar. + info_bar_view_->SetParentOwned(false); + } + return info_bar_view_.get(); +} + +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::OpenFindInPageWindow(const Browser& browser) { @@ -736,146 +577,6 @@ bool WebContents::GetFindInPageWindowLocation(int* x, int* y) { return false; } -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); -} - -// Generic NotificationObserver callback. -void WebContents::Observe(NotificationType type, - const NotificationSource& source, - const NotificationDetails& details) { - TabContents::Observe(type, source, 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<Profile>(source).ptr(); - if (!source_profile->IsSameProfile(profile())) - return; - - UpdateStarredStateForCurrentURL(); - break; - } - case NOTIFY_PREF_CHANGED: { - std::wstring* pref_name_in = Details<std::wstring>(details).ptr(); - DCHECK(Source<PrefService>(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; - } - default: { - NOTREACHED(); - break; - } - } -} - -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<WebContents>(this), - NotificationService::NoDetails()); -} - -void WebContents::NotifyConnected() { - notify_disconnection_ = true; - NotificationService::current()-> - Notify(NOTIFY_WEB_CONTENTS_CONNECTED, - Source<WebContents>(this), - NotificationService::NoDetails()); -} - -void WebContents::NotifyDisconnected() { - if (!notify_disconnection_) - return; - - notify_disconnection_ = false; - NotificationService::current()-> - Notify(NOTIFY_WEB_CONTENTS_DISCONNECTED, - Source<WebContents>(this), - NotificationService::NoDetails()); -} - -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<GURL> 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); - } - } -} - -void WebContents::MaybeCloseChildWindows( - const ViewHostMsg_FrameNavigate_Params& params) { - if (net::RegistryControlledDomainService::SameDomainOrHost( - last_url_, params.url)) - return; - last_url_ = params.url; - - // 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<int>(child_windows_.size()); - for (int i = size - 1; i >= 0; --i) { - ConstrainedWindow* window = child_windows_[i]; - if (window) - window->CloseConstrainedWindow(); - } -} - -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::SetInfoBarVisible(bool visible) { - if (info_bar_visible_ != visible) { - info_bar_visible_ = visible; - if (info_bar_visible_) { - // Invoke GetInfoBarView to force the info bar to be created. - GetInfoBarView(); - } - ToolbarSizeChanged(false); - } -} void WebContents::SetFindInPageVisible(bool visible) { if (find_in_page_controller_.get()) { @@ -886,15 +587,6 @@ void WebContents::SetFindInPageVisible(bool visible) { } } -InfoBarView* WebContents::GetInfoBarView() { - if (info_bar_view_.get() == NULL) { - info_bar_view_.reset(new InfoBarView(this)); - // The WebContents owns the info-bar. - info_bar_view_->SetParentOwned(false); - } - return info_bar_view_.get(); -} - void WebContents::SetWebApp(WebApp* web_app) { if (web_app_.get()) { web_app_->RemoveObserver(this); @@ -936,16 +628,83 @@ void WebContents::CreateShortcut() { render_view_host()->GetApplicationInfo(pending_install_.page_id); } -PasswordManager* WebContents::GetPasswordManager() { - if (password_manager_.get() == NULL) - password_manager_.reset(new PasswordManager(this)); - return password_manager_.get(); +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); } -PluginInstaller* WebContents::GetPluginInstaller() { - if (plugin_installer_.get() == NULL) - plugin_installer_.reset(new PluginInstaller(this)); - return plugin_installer_.get(); +void WebContents::SetInfoBarVisible(bool visible) { + if (info_bar_visible_ != visible) { + info_bar_visible_ = visible; + if (info_bar_visible_) { + // Invoke GetInfoBarView to force the info bar to be created. + GetInfoBarView(); + } + ToolbarSizeChanged(false); + } +} + +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)) + 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 (render_manager_.showing_interstitial_page()) + return; + + // If we have a FindInPage dialog, notify it that its tab was hidden. + if (find_in_page_controller_.get()) + find_in_page_controller_->DidBecomeUnselected(); + + // 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 (render_manager_.showing_interstitial_page()) + return false; + + // If we have a FindInPage dialog, notify it that its tab was hidden. + if (find_in_page_controller_.get()) + find_in_page_controller_->DidBecomeUnselected(); + + return printing_.PrintNow(); } bool WebContents::IsActiveEntry(int32 page_id) { @@ -955,8 +714,22 @@ bool WebContents::IsActiveEntry(int32 page_id) { active_entry->page_id() == page_id); } -/////////////////////////////////////////////////////////////////////////////// -// RenderViewHostDelegate implementation: +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::FindInPage* WebContents::GetFindInPageDelegate() const { // The find in page controller implements this interface for us. Our return @@ -1122,7 +895,7 @@ void WebContents::DidNavigate(RenderViewHost* rvh, return; // We can't do anything about navigations when we're inactive. - if (!controller() || !is_active_) + if (!controller() || !is_active()) return; // Update the site of the SiteInstance if it doesn't have one yet, unless we @@ -1154,144 +927,6 @@ void WebContents::DidNavigate(RenderViewHost* rvh, DidNavigateAnyFramePostCommit(rvh, details, params); } -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); - - // We no longer know the title after this navigation. - has_page_title_ = false; - - // Update contents MIME type of the main webframe. - contents_mime_type_ = params.contents_mime_type; - - // 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(params); - - // We hide the FindInPage window when the user navigates away, except on - // reload. - if (PageTransition::StripQualifier(params.transition) != - PageTransition::RELOAD) - SetFindInPageVisible(false); - - // 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); -} - -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::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()); -} - -void WebContents::UpdateRenderViewSize() { - // Using same technique as OnPaint, which sets size of SadTab. - CRect cr; - GetClientRect(&cr); - gfx::Size new_size(cr.Width(), cr.Height()); - SizeContents(new_size); -} - void WebContents::UpdateState(RenderViewHost* rvh, int32 page_id, const GURL& url, @@ -1375,7 +1010,7 @@ void WebContents::UpdateTitle(RenderViewHost* rvh, // If we have a title, that's a pretty good indication that we've started // getting useful data. - response_started_ = false; + SetNotWaitingForResponse(); NavigationEntry* entry; if (render_manager_.showing_interstitial_page() && @@ -1418,7 +1053,7 @@ void WebContents::UpdateTitle(RenderViewHost* rvh, void WebContents::UpdateEncoding(RenderViewHost* render_view_host, const std::wstring& encoding_name) { - SetEncoding(encoding_name); + set_encoding(encoding_name); } void WebContents::UpdateTargetURL(int32 page_id, const GURL& url) { @@ -1769,6 +1404,121 @@ void WebContents::TakeFocus(bool reverse) { } } +// 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(GetHWND(), 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<WebContents>(this), + Details<int>(&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); +} + +// The renderer sends back to the browser the key events it did not process. +void WebContents::HandleKeyboardEvent(const WebKeyboardEvent& event) { + // 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) { + ChromeViews::FocusManager* focus_manager = + ChromeViews::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) { + ChromeViews::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)) + 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); +} + GURL WebContents::GetAlternateErrorPageURL() const { GURL url; PrefService* prefs = profile()->GetPrefs(); @@ -1899,78 +1649,27 @@ void WebContents::OnJSOutOfMemory() { } } -// Returns true if the entry's transition type is FORM_SUBMIT. -static bool IsFormSubmit(const NavigationEntry* entry) { - DCHECK(entry); - return (PageTransition::StripQualifier(entry->transition_type()) == - PageTransition::FORM_SUBMIT); +bool WebContents::CanBlur() const { + return delegate() ? delegate()->CanBlur() : true; } -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; - } +void WebContents::RendererUnresponsive(RenderViewHost* rvh) { + if (render_view_host() && render_view_host()->IsRenderViewLive()) + HungRendererWarning::ShowForWebContents(this); +} - // 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; - } +void WebContents::RendererResponsive(RenderViewHost* render_view_host) { + HungRendererWarning::HideForWebContents(this); +} - // 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(GetHWND(), GA_ROOT), - autodetected); +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( @@ -1987,6 +1686,433 @@ void WebContents::OnDidGetApplicationInfo( &GearsCreateShortcutCallbackFunctor::Run)); } +void WebContents::FileSelected(const std::wstring& path, void* params) { + render_view_host()->FileSelected(path); +} + +void WebContents::FileSelectionCanceled(void* params) { + // If the user cancels choosing a file to upload we need to pass back the + // empty string. + render_view_host()->FileSelected(std::wstring()); +} + +void WebContents::BeforeUnloadFiredFromRenderManager( + bool proceed, + bool* proceed_to_fire_unload) { + delegate()->BeforeUnloadFired(this, proceed, proceed_to_fire_unload); +} + +void WebContents::UpdateRenderViewSizeForRenderManager() { + // Using same technique as OnPaint, which sets size of SadTab. + CRect cr; + GetClientRect(&cr); + gfx::Size new_size(cr.Width(), cr.Height()); + SizeContents(new_size); +} + +bool WebContents::CreateRenderViewForRenderManager( + RenderViewHost* render_view_host) { + RenderWidgetHostHWND* view = CreatePageView(render_view_host); + + bool ok = render_view_host->CreateRenderView(); + if (ok) { + CRect client_rect; + ::GetClientRect(GetHWND(), &client_rect); + view->SetSize(gfx::Size(client_rect.Width(), client_rect.Height())); + 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<Profile>(source).ptr(); + if (!source_profile->IsSameProfile(profile())) + return; + + UpdateStarredStateForCurrentURL(); + break; + } + case NOTIFY_PREF_CHANGED: { + std::wstring* pref_name_in = Details<std::wstring>(details).ptr(); + DCHECK(Source<PrefService>(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; + } + default: { + NOTREACHED(); + break; + } + } +} + +void WebContents::OnDestroy() { + if (drop_target_.get()) { + RevokeDragDrop(GetHWND()); + drop_target_ = NULL; + } +} + +void WebContents::OnHScroll(int scroll_type, short position, HWND scrollbar) { + ScrollCommon(WM_HSCROLL, scroll_type, position, scrollbar); +} + +void WebContents::OnMouseLeave() { + // Let our delegate know that the mouse moved (useful for resetting status + // bubble state). + if (delegate()) + delegate()->ContentsMouseEvent(this, WM_MOUSELEAVE); + SetMsgHandled(FALSE); +} + +LRESULT WebContents::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 (delegate()) + delegate()->ActivateContents(this); + break; + case WM_MOUSEMOVE: + // Let our delegate know that the mouse moved (useful for resetting status + // bubble state). + if (delegate()) + delegate()->ContentsMouseEvent(this, WM_MOUSEMOVE); + break; + default: + break; + } + + return 0; +} + +void WebContents::OnPaint(HDC junk_dc) { + if (render_view_host() && !render_view_host()->IsRenderViewLive()) { + if (!sad_tab_.get()) + sad_tab_.reset(new SadTabView); + CRect cr; + GetClientRect(&cr); + sad_tab_->SetBounds(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 WebContents::OnReflectedMessage(UINT msg, WPARAM w_param, + LPARAM l_param) { + MSG* message = reinterpret_cast<MSG*>(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 WebContents::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 (view()) { + HWND inner_hwnd = view()->GetPluginHWND(); + if (::IsWindow(inner_hwnd)) + ::SetFocus(inner_hwnd); + } +} + +void WebContents::OnVScroll(int scroll_type, short position, HWND scrollbar) { + ScrollCommon(WM_VSCROLL, scroll_type, position, scrollbar); +} + +void WebContents::OnWindowPosChanged(WINDOWPOS* window_pos) { + if (window_pos->flags & SWP_HIDEWINDOW) { + HideContents(); + } 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) + ShowContents(); + // 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)) { + gfx::Size size(window_pos->cx, window_pos->cy); + SizeContents(size); + } + + // If we have a FindInPage dialog, notify it that the window changed. + if (find_in_page_controller_.get() && find_in_page_controller_->IsVisible()) + find_in_page_controller_->MoveWindowIfNecessary(gfx::Rect()); + } +} + +void WebContents::OnSize(UINT param, const CSize& size) { + HWNDViewContainer::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.nTrackPos = 50; + + ::SetScrollInfo(GetHWND(), SB_HORZ, &si, FALSE); + ::SetScrollInfo(GetHWND(), SB_VERT, &si, FALSE); +} + +LRESULT WebContents::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 WebContents::OnNCPaint(HRGN rgn) { + // Suppress default WM_NCPAINT handling. We don't need to do anything + // here since the view will draw everything correctly. +} + +void WebContents::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); + } +} + +bool WebContents::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 WebContents::WheelZoom(int distance) { + if (delegate()) { + bool zoom_in = distance > 0; + delegate()->ContentsZoomChange(zoom_in); + } +} + +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); + + // We no longer know the title after this navigation. + has_page_title_ = false; + + // Update contents MIME type of the main webframe. + contents_mime_type_ = params.contents_mime_type; + + // 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(params); + + // We hide the FindInPage window when the user navigates away, except on + // reload. + if (PageTransition::StripQualifier(params.transition) != + PageTransition::RELOAD) + SetFindInPageVisible(false); + + // 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 ViewHostMsg_FrameNavigate_Params& params) { + if (net::RegistryControlledDomainService::SameDomainOrHost( + last_url_, params.url)) + return; + last_url_ = params.url; + + // 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<int>(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(); @@ -2031,77 +2157,86 @@ void WebContents::UpdateMaxPageIDIfNecessary(SiteInstance* site_instance, } } -void WebContents::BeforeUnloadFiredFromRenderManager( - bool proceed, - bool* proceed_to_fire_unload) { - delegate()->BeforeUnloadFired(this, proceed, proceed_to_fire_unload); -} - - -HWND WebContents::GetContentHWND() { - if (!view()) - return NULL; - return view()->GetPluginHWND(); -} - -bool WebContents::CanDisplayFile(const std::wstring& full_path) { - bool allow_wildcard = false; - std::string mime_type; - net::GetMimeTypeFromFile(full_path, &mime_type); - if (net::IsSupportedMimeType(mime_type) || - (PluginService::GetInstance() && - PluginService::GetInstance()->HavePluginFor(mime_type, allow_wildcard))) - return true; - return false; -} - -void WebContents::PrintPreview() { - // We can't print interstitial page for now. - if (render_manager_.showing_interstitial_page()) +void WebContents::UpdateHistoryForNavigation(const GURL& display_url, + const ViewHostMsg_FrameNavigate_Params& params) { + if (profile()->IsOffTheRecord()) return; - // If we have a FindInPage dialog, notify it that its tab was hidden. - if (find_in_page_controller_.get()) - find_in_page_controller_->DidBecomeUnselected(); - - // We don't show the print preview for the beta, only the print dialog. - printing_.ShowPrintDialog(); + // 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<GURL> 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::PrintNow() { - // We can't print interstitial page for now. - if (render_manager_.showing_interstitial_page()) - return false; - - // If we have a FindInPage dialog, notify it that its tab was hidden. - if (find_in_page_controller_.get()) - find_in_page_controller_->DidBecomeUnselected(); - - return printing_.PrintNow(); +RenderWidgetHostHWND* WebContents::CreatePageView( + RenderViewHost* render_view_host) { + // Create the View as well. Its lifetime matches the child process'. + DCHECK(!render_view_host->view()); + RenderWidgetHostHWND* view = new RenderWidgetHostHWND(render_view_host); + render_view_host->set_view(view); + view->Create(GetHWND()); + view->ShowWindow(SW_SHOW); + return view; } -void WebContents::WillCaptureContents() { - capturing_contents_ = true; +void WebContents::DetachPluginWindows() { + EnumChildWindows(GetHWND(), WebContents::EnumPluginWindowsCallback, NULL); } -void WebContents::DidCaptureContents() { - capturing_contents_ = false; -} +BOOL WebContents::EnumPluginWindowsCallback(HWND window, LPARAM) { + if (WebPluginDelegateImpl::IsPluginDelegateWindow(window)) { + ::ShowWindow(window, SW_HIDE); + SetParent(window, NULL); + } -void WebContents::Cut() { - render_view_host()->Cut(); + return TRUE; } -void WebContents::Copy() { - render_view_host()->Copy(); +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<WebContents>(this), + NotificationService::NoDetails()); } -void WebContents::Paste() { - render_view_host()->Paste(); +void WebContents::NotifyConnected() { + notify_disconnection_ = true; + NotificationService::current()-> + Notify(NOTIFY_WEB_CONTENTS_CONNECTED, + Source<WebContents>(this), + NotificationService::NoDetails()); } -void WebContents::SetInitialFocus(bool reverse) { - render_view_host()->SetInitialFocus(reverse); +void WebContents::NotifyDisconnected() { + if (!notify_disconnection_) + return; + + notify_disconnection_ = false; + NotificationService::current()-> + Notify(NOTIFY_WEB_CONTENTS_DISCONNECTED, + Source<WebContents>(this), + NotificationService::NoDetails()); } void WebContents::GenerateKeywordIfNecessary( @@ -2178,167 +2313,3 @@ void WebContents::GenerateKeywordIfNecessary( new_url->set_safe_for_autoreplace(true); url_model->Add(new_url); } - -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<WebContents>(this), - Details<int>(&num_resources)); -} - -// The renderer sends back to the browser the key events it did not process. -void WebContents::HandleKeyboardEvent(const WebKeyboardEvent& event) { - // 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) { - ChromeViews::FocusManager* focus_manager = - ChromeViews::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) { - ChromeViews::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)) - 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); -} - -bool WebContents::CreateRenderViewForRenderManager( - RenderViewHost* render_view_host) { - RenderWidgetHostHWND* view = CreatePageView(render_view_host); - - bool ok = render_view_host->CreateRenderView(); - if (ok) { - CRect client_rect; - ::GetClientRect(GetHWND(), &client_rect); - view->SetSize(gfx::Size(client_rect.Width(), client_rect.Height())); - UpdateMaxPageIDIfNecessary(render_view_host->site_instance(), - render_view_host); - } - return ok; -} - -RenderWidgetHostHWND* WebContents::CreatePageView( - RenderViewHost* render_view_host) { - // Create the View as well. Its lifetime matches the child process'. - DCHECK(!render_view_host->view()); - RenderWidgetHostHWND* view = new RenderWidgetHostHWND(render_view_host); - render_view_host->set_view(view); - view->Create(GetHWND()); - view->ShowWindow(SW_SHOW); - return view; -} - -void WebContents::DidGetPrintedPagesCount(int cookie, int number_pages) { - printing_.DidGetPrintedPagesCount(cookie, number_pages); -} - -void WebContents::DidPrintPage(const ViewHostMsg_DidPrintPage_Params& params) { - printing_.DidPrintPage(params); -} - -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); -} - -void WebContents::FileSelected(const std::wstring& path, void* params) { - render_view_host()->FileSelected(path); -} - -void WebContents::FileSelectionCanceled(void* params) { - // If the user cancels choosing a file to upload we need to pass back the - // empty string. - render_view_host()->FileSelected(std::wstring()); -} - -/////////////////////////////////////////////////////////////////////////////// - -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::CanBlur() const { - return delegate() ? delegate()->CanBlur() : true; -} - -void WebContents::RendererUnresponsive(RenderViewHost* rvh) { - 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) - response_started_ = false; - if (is_loading()) - NotifyNavigationStateChanged(INVALIDATE_LOAD); -} - -void WebContents::DetachPluginWindows() { - EnumChildWindows(GetHWND(), WebContents::EnumPluginWindowsCallback, NULL); -} - -BOOL WebContents::EnumPluginWindowsCallback(HWND window, LPARAM) { - if (WebPluginDelegateImpl::IsPluginDelegateWindow(window)) { - ::ShowWindow(window, SW_HIDE); - SetParent(window, NULL); - } - - return TRUE; -} diff --git a/chrome/browser/web_contents.h b/chrome/browser/web_contents.h index 1e23645..780b34a 100644 --- a/chrome/browser/web_contents.h +++ b/chrome/browser/web_contents.h @@ -28,11 +28,14 @@ class SadTabView; struct WebDropData; class WebDropTarget; +// 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 ChromeViews::HWNDViewContainer, public SelectFileDialog::Listener, + public NotificationObserver, public WebApp::Observer { public: // If instance is NULL, then creates a new process for this view. Otherwise @@ -48,82 +51,78 @@ class WebContents : public TabContents, static void RegisterUserPrefs(PrefService* prefs); - virtual void CreateView(HWND parent_hwnd, const gfx::Rect& initial_bounds); - virtual HWND GetContainerHWND() const { return GetHWND(); } - virtual void GetContainerBounds(gfx::Rect *out) const; - virtual void ShowContents(); - virtual void HideContents(); - virtual void SizeContents(const gfx::Size& size); + // Getters ------------------------------------------------------------------- - // TabContents - virtual WebContents* AsWebContents() { return this; } - virtual SiteInstance* GetSiteInstance() const { - return render_manager_.current_host()->site_instance(); + // 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, RenderViewHost, and + // SiteInstance, respectively. Each of these may change over time. Callers + // should be aware that the SiteInstance could be deleted if its ref count + // drops to zero (i.e., if all RenderViewHosts and NavigationEntries that + // use it are deleted). + RenderProcessHost* process() const { + return render_manager_.current_host()->process(); } - virtual bool NavigateToPendingEntry(bool reload); - virtual void Stop(); - virtual void DidBecomeSelected(); - virtual void WasHidden(); + RenderViewHost* render_view_host() const { + return render_manager_.current_host(); + } + RenderWidgetHostView* view() const { + return render_manager_.current_view(); + } + + bool is_starred() const { return is_starred_; } + + // TabContents (public overrides) -------------------------------------------- + virtual void Destroy(); + virtual WebContents* AsWebContents() { return this; } + virtual SiteInstance* GetSiteInstance() const; virtual SkBitmap GetFavIcon(); virtual std::wstring GetStatusText() const; - - // Find functions + virtual bool NavigateToPendingEntry(bool reload); + virtual void Stop(); virtual void StartFinding(int request_id, const std::wstring& search_string, bool forward, bool match_case, bool find_next); virtual void StopFinding(bool clear_selection); - virtual void OpenFindInPageWindow(const Browser& browser); - virtual void ReparentFindWindow(HWND new_parent); - virtual bool AdvanceFindSelection(bool forward_direction); - virtual bool IsFindWindowFullyVisible(); - virtual bool GetFindInPageWindowLocation(int* x, int* y); - - bool is_starred() const { return is_starred_; } - - // 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; - } - - // Various other systems need to know about our interstitials. - bool showing_interstitial_page() const { - return render_manager_.showing_interstitial_page(); - } - bool showing_repost_interstitial() const { - return render_manager_.showing_repost_interstitial(); - } - - // Overridden from TabContents to remember at what time the download bar was - // shown. - void SetDownloadShelfVisible(bool visible); - - // Returns the SavePackage which manages the page saving job. May be NULL. - SavePackage* save_package() const { return save_package_.get(); } - - // Whether or not the info bar is visible. This delegates to - // the ChromeFrame method InfoBarVisibilityChanged. - void SetInfoBarVisible(bool visible); - virtual bool IsInfoBarVisible() { return info_bar_visible_; } - - // Whether or not the FindInPage bar is visible. - void SetFindInPageVisible(bool visible); - + virtual void Cut(); + virtual void Copy(); + virtual void Paste(); + virtual void DidBecomeSelected(); + virtual void WasHidden(); + virtual void ShowContents(); + virtual void HideContents(); + virtual void SizeContents(const gfx::Size& size); + virtual HWND GetContentHWND(); + virtual void CreateView(HWND parent_hwnd, const gfx::Rect& initial_bounds); + virtual HWND GetContainerHWND() const { return GetHWND(); } + virtual void GetContainerBounds(gfx::Rect *out) const; // Create the InfoBarView and returns it if none has been created. // Just returns existing InfoBarView if it is already created. virtual InfoBarView* GetInfoBarView(); + virtual bool IsInfoBarVisible() { return info_bar_visible_; } + virtual void SetDownloadShelfVisible(bool visible); - // Prepare for saving page. - void OnSavePage(); + // Find in page -------------------------------------------------------------- - // 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); + // TODO(brettw) these should be commented. + void OpenFindInPageWindow(const Browser& browser); + void ReparentFindWindow(HWND new_parent); + bool AdvanceFindSelection(bool forward_direction); + bool IsFindWindowFullyVisible(); + bool GetFindInPageWindowLocation(int* x, int* y); + void SetFindInPageVisible(bool visible); + + // Web apps ------------------------------------------------------------------ // Sets the WebApp for this WebContents. void SetWebApp(WebApp* web_app); @@ -135,57 +134,16 @@ class WebContents : public TabContents, // Tell Gears to create a shortcut for the current page. void CreateShortcut(); - // JavascriptMessageBoxHandler calls this when the dialog is closed. - void OnJavaScriptMessageBoxClosed(IPC::Message* reply_msg, bool success, - const std::wstring& prompt); + // Interstitials ------------------------------------------------------------- - // Returns the PasswordManager, creating it if necessary. - PasswordManager* GetPasswordManager(); - - // Returns the PluginInstaller, creating it if necessary. - PluginInstaller* GetPluginInstaller(); - - // Return the currently active RenderProcessHost, RenderViewHost, and - // SiteInstance, respectively. Each of these may change over time. Callers - // should be aware that the SiteInstance could be deleted if its ref count - // drops to zero (i.e., if all RenderViewHosts and NavigationEntries that - // use it are deleted). - RenderProcessHost* process() const { - return render_manager_.current_host()->process(); - } - RenderViewHost* render_view_host() const { - return render_manager_.current_host(); + // Various other systems need to know about our interstitials. + bool showing_interstitial_page() const { + return render_manager_.showing_interstitial_page(); } - RenderWidgetHostView* view() const { - return render_manager_.current_view(); + bool showing_repost_interstitial() const { + return render_manager_.showing_repost_interstitial(); } - // Overridden from TabContents to return the window of the - // RenderWidgetHostView. - virtual HWND GetContentHWND(); - - // Handling the drag and drop of files into the content area. - virtual bool CanDisplayFile(const std::wstring& full_path); - - // 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(); - - virtual void WillCaptureContents(); - virtual void DidCaptureContents(); - - virtual void Cut(); - virtual void Copy(); - virtual void Paste(); - // The rest of the system wants to interact with the delegate our render view // host manager has. See those setters for more. InterstitialPageDelegate* interstitial_page_delegate() const { @@ -215,15 +173,45 @@ class WebContents : public TabContents, render_manager_.HideInterstitialPage(wait_for_navigation, 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); + // 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); + + // Whether or not the info bar is visible. This delegates to + // the ChromeFrame method InfoBarVisibilityChanged. See also IsInfoBarVisible + // (a TabContents override). + void SetInfoBarVisible(bool visible); + + // 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); @@ -235,17 +223,19 @@ class WebContents : public TabContents, bool notify_disconnection() const { return notify_disconnection_; } protected: - FRIEND_TEST(WebContentsTest, UpdateTitle); - // Should be deleted via CloseContents. virtual ~WebContents(); - // RenderViewHostDelegate + // TabContents (private overrides) ------------------------------------------- + + virtual void SetInitialFocus(bool reverse); + virtual void SetIsLoading(bool is_loading, LoadNotificationDetails* details); + + // RenderViewHostDelegate ---------------------------------------------------- + virtual RenderViewHostDelegate::FindInPage* GetFindInPageDelegate() const; virtual RenderViewHostDelegate::Save* GetSaveDelegate() const; - virtual Profile* GetProfile() const; - virtual void CreateView(int route_id, HANDLE modal_dialog_event); virtual void CreateWidget(int route_id); virtual void ShowView(int route_id, @@ -257,7 +247,6 @@ class WebContents : public TabContents, virtual void RendererGone(RenderViewHost* render_view_host); virtual void DidNavigate(RenderViewHost* render_view_host, const ViewHostMsg_FrameNavigate_Params& params); - virtual void UpdateRenderViewSize(); virtual void UpdateState(RenderViewHost* render_view_host, int32 page_id, const GURL& url, @@ -321,8 +310,12 @@ class WebContents : public TabContents, IPC::Message* reply_msg); virtual void PasswordFormsSeen(const std::vector<PasswordForm>& forms); virtual void TakeFocus(bool reverse); + 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 void HandleKeyboardEvent(const WebKeyboardEvent& event); virtual GURL GetAlternateErrorPageURL() const; virtual WebPreferences GetWebkitPrefs(); virtual void OnMissingPluginStatus(int status); @@ -331,41 +324,47 @@ class WebContents : public TabContents, 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); virtual void RendererResponsive(RenderViewHost* render_view_host); virtual void LoadStateChanged(const GURL& url, net::LoadState load_state); - - // Notification that a page has an OpenSearch description document available - // at url. This 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. - virtual void PageHasOSDD(RenderViewHost* render_view_host, - int32 page_id, const GURL& url, bool autodetected); - virtual void OnDidGetApplicationInfo( int32 page_id, const webkit_glue::WebApplicationInfo& info); - // Overridden from TabContents. - virtual void SetInitialFocus(bool reverse); - - // Handle reply from inspect element request - virtual void InspectElementReply(int num_resources); - - // Handle keyboard events not processed by the renderer. - virtual void HandleKeyboardEvent(const WebKeyboardEvent& event); - - // Notifies the RenderWidgetHost instance about the fact that the - // page is loading, or done loading and calls the base implementation. - void SetIsLoading(bool is_loading, LoadNotificationDetails* details); + // SelectFileDialog::Listener ------------------------------------------------ - // Overridden from SelectFileDialog::Listener: virtual void FileSelected(const std::wstring& path, void* params); virtual void FileSelectionCanceled(void* params); - // Another part of RenderViewHostManager::Delegate. - // + // 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 @@ -382,6 +381,7 @@ class WebContents : public TabContents, RenderViewHost* render_view_host); private: + FRIEND_TEST(WebContentsTest, UpdateTitle); friend class TestWebContents; // When CreateShortcut is invoked RenderViewHost::GetApplicationInfo is @@ -400,17 +400,14 @@ class WebContents : public TabContents, GearsCreateShortcutCallbackFunctor* callback_functor; }; - void ScrollCommon(UINT message, int scroll_type, short position, - HWND scrollbar); - bool ScrollZoom(int scroll_type); - void WheelZoom(int distance); + // NotificationObserver ------------------------------------------------------ - // Backend for LoadURL that optionally creates a history entry. The - // transition type will be ignored if a history entry is not created. - void LoadURL(const std::wstring& url, bool create_history_entry, - PageTransition::Type transition); + virtual void Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details); + + // Windows events ------------------------------------------------------------ - // Windows Event handlers virtual void OnDestroy(); virtual void OnHScroll(int scroll_type, short position, HWND scrollbar); virtual void OnMouseLeave(); @@ -424,33 +421,14 @@ class WebContents : public TabContents, virtual LRESULT OnNCCalcSize(BOOL w_param, LPARAM l_param); virtual void OnNCPaint(HRGN rgn); - // Callback from HistoryService for our request for a favicon. - void OnFavIconData(HistoryService::Handle handle, - bool know_favicon, - scoped_refptr<RefCountedBytes> data, - bool expired); - - // NotificationObserver implementation. - virtual void Observe(NotificationType type, - const NotificationSource& source, - const NotificationDetails& details); - - // Helper functions for sending notifications. - void NotifySwapped(); - void NotifyConnected(); - void NotifyDisconnected(); - - // Called by OnMsgNavigate to update history state. - virtual void UpdateHistoryForNavigation(const GURL& display_url, - const ViewHostMsg_FrameNavigate_Params& params); - - // If params has a searchable form, this tries to create a new keyword. - void GenerateKeywordIfNecessary( - const ViewHostMsg_FrameNavigate_Params& params); + // Backend for all scroll messages, the |message| parameter indicates which + // one it is. + void ScrollCommon(UINT message, int scroll_type, short position, + HWND scrollbar); - // Sets up the View that holds the rendered web page, receives messages for - // it and contains page plugins. - RenderWidgetHostHWND* CreatePageView(RenderViewHost* render_view_host); + // TODO(brettw) comment these. They're confusing. + bool ScrollZoom(int scroll_type); + void WheelZoom(int distance); // Navigation helpers -------------------------------------------------------- // @@ -505,35 +483,33 @@ class WebContents : public TabContents, void UpdateMaxPageIDIfNecessary(SiteInstance* site_instance, RenderViewHost* rvh); - // RenderViewHostManager::Delegate pass-throughs ----------------------------- + // 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); - 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() { - UpdateRenderViewSize(); - } - virtual void NotifySwappedFromRenderManager() { - NotifySwapped(); - } - virtual NavigationController* GetControllerForRenderManager() { - return controller(); - } + // Misc view stuff ----------------------------------------------------------- - // --------------------------------------------------------------------------- + // Sets up the View that holds the rendered web page, receives messages for + // it and contains page plugins. + RenderWidgetHostHWND* CreatePageView(RenderViewHost* render_view_host); // Enumerate and 'un-parent' any plugin windows that are children // of this web contents. void DetachPluginWindows(); static BOOL CALLBACK EnumPluginWindowsCallback(HWND window, LPARAM param); + // 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 ---------------------------------------------------------------------- // Manages creation and swapping of render views. @@ -603,9 +579,6 @@ class WebContents : public TabContents, // The SadTab renderer. scoped_ptr<SadTabView> sad_tab_; - // This flag is true while we are in the photo-booth. See dragged_tab.cc. - bool capturing_contents_; - // Handles downloading favicons. FavIconHelper fav_icon_helper_; |