diff options
author | brettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-04-24 03:28:54 +0000 |
---|---|---|
committer | brettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-04-24 03:28:54 +0000 |
commit | 96d185dff2231e09dfcf4b08c9ed878a4a9f7acf (patch) | |
tree | 0da07853d5023694ff329398bd9c7f05ed04e05c /chrome/browser/tab_contents/tab_contents.cc | |
parent | 695e0fe18af42a8ce29519ed17264d412146de04 (diff) | |
download | chromium_src-96d185dff2231e09dfcf4b08c9ed878a4a9f7acf.zip chromium_src-96d185dff2231e09dfcf4b08c9ed878a4a9f7acf.tar.gz chromium_src-96d185dff2231e09dfcf4b08c9ed878a4a9f7acf.tar.bz2 |
Move another batch of functions for WebContents to TabContents. This also
updates the Dev tools manager to take a TabContents (a pointer was being
passed from the TabContents which made it break).
Review URL: http://codereview.chromium.org/92101
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@14412 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/tab_contents/tab_contents.cc')
-rw-r--r-- | chrome/browser/tab_contents/tab_contents.cc | 373 |
1 files changed, 369 insertions, 4 deletions
diff --git a/chrome/browser/tab_contents/tab_contents.cc b/chrome/browser/tab_contents/tab_contents.cc index fcf7bdd..a550414 100644 --- a/chrome/browser/tab_contents/tab_contents.cc +++ b/chrome/browser/tab_contents/tab_contents.cc @@ -4,12 +4,20 @@ #include "chrome/browser/tab_contents/tab_contents.h" +#include "base/string16.h" +#include "base/time.h" #include "chrome/browser/autofill_manager.h" +#include "chrome/browser/browser_process.h" #include "chrome/browser/cert_store.h" +#include "chrome/browser/debugger/devtools_manager.h" +#include "chrome/browser/dom_ui/dom_ui.h" +#include "chrome/browser/dom_ui/dom_ui_factory.h" #include "chrome/browser/download/download_item_model.h" #include "chrome/browser/download/download_shelf.h" #include "chrome/browser/password_manager/password_manager.h" #include "chrome/browser/plugin_installer.h" +#include "chrome/browser/renderer_host/render_widget_host_view.h" +#include "chrome/browser/renderer_host/web_cache_manager.h" #include "chrome/browser/tab_contents/navigation_entry.h" #include "chrome/browser/tab_contents/tab_contents_delegate.h" #include "chrome/browser/tab_contents/tab_contents_view.h" @@ -18,6 +26,7 @@ #include "chrome/common/notification_service.h" #include "chrome/common/pref_names.h" #include "chrome/common/pref_service.h" +#include "chrome/common/url_constants.h" #include "grit/generated_resources.h" #if defined(OS_WIN) @@ -123,6 +132,38 @@ const GURL& TabContents::GetURL() const { return entry ? entry->display_url() : GURL::EmptyGURL(); } +const string16& TabContents::GetTitle() const { + DOMUI* our_dom_ui = render_manager_.pending_dom_ui() ? + render_manager_.pending_dom_ui() : render_manager_.dom_ui(); + if (our_dom_ui) { + // Don't override the title in view source mode. + NavigationEntry* entry = controller_.GetActiveEntry(); + if (!(entry && entry->IsViewSourceMode())) { + // Give the DOM UI the chance to override our title. + const string16& title = our_dom_ui->overridden_title(); + if (!title.empty()) + return title; + } + } + + // We use the title for the last committed entry rather than a pending + // navigation entry. For example, when the user types in a URL, we want to + // keep the old page's title until the new load has committed and we get a new + // title. + // The exception is with transient pages, for which we really want to use + // their title, as they are not committed. + NavigationEntry* entry = controller_.GetTransientEntry(); + if (entry) + return entry->GetTitleForDisplay(&controller_); + + entry = controller_.GetLastCommittedEntry(); + if (entry) + return entry->GetTitleForDisplay(&controller_); + else if (controller_.LoadingURLLazily()) + return controller_.GetLazyTitle(); + return EmptyString16(); +} + int32 TabContents::GetMaxPageID() { if (GetSiteInstance()) return GetSiteInstance()->max_page_id(); @@ -143,10 +184,25 @@ void TabContents::UpdateMaxPageID(int32 page_id) { max_page_id_ = std::max(max_page_id_, page_id); } +SiteInstance* TabContents::GetSiteInstance() const { + return render_manager_.current_host()->site_instance(); +} + const std::wstring TabContents::GetDefaultTitle() const { return l10n_util::GetString(IDS_DEFAULT_TAB_TITLE); } +bool TabContents::ShouldDisplayURL() { + // Don't hide the url in view source mode. + NavigationEntry* entry = controller_.GetActiveEntry(); + if (entry && entry->IsViewSourceMode()) + return true; + DOMUI* dom_ui = GetDOMUIForCurrentState(); + if (dom_ui) + return !dom_ui->should_hide_url(); + return true; +} + SkBitmap TabContents::GetFavIcon() const { // Like GetTitle(), we also want to use the favicon for the last committed // entry rather than a pending navigation entry. @@ -162,6 +218,17 @@ SkBitmap TabContents::GetFavIcon() const { return SkBitmap(); } +bool TabContents::ShouldDisplayFavIcon() { + // Always display a throbber during pending loads. + if (controller_.GetLastCommittedEntry() && controller_.pending_entry()) + return true; + + DOMUI* dom_ui = GetDOMUIForCurrentState(); + if (dom_ui) + return !dom_ui->hide_favicon(); + return true; +} + #if defined(OS_WIN) SecurityStyle TabContents::GetSecurityStyle() const { // We may not have a navigation entry yet. @@ -192,6 +259,33 @@ bool TabContents::GetSSLEVText(std::wstring* ev_text, } #endif +std::wstring TabContents::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 + case net::LOAD_STATE_IDLE: + case net::LOAD_STATE_READING_RESPONSE: + break; + } + + return std::wstring(); +} + void TabContents::SetIsCrashed(bool state) { if (state == is_crashed_) return; @@ -206,11 +300,69 @@ void TabContents::NotifyNavigationStateChanged(unsigned changed_flags) { delegate_->NavigationStateChanged(this, changed_flags); } +void TabContents::DidBecomeSelected() { + controller_.SetActive(true); + + if (render_widget_host_view()) + render_widget_host_view()->DidBecomeSelected(); + + // If pid() is -1, that means the RenderProcessHost still hasn't been + // initialized. It'll register with CacheManagerHost when it is. + if (process()->pid() != -1) + WebCacheManager::GetInstance()->ObserveActivity(process()->pid()); +} + +void TabContents::WasHidden() { + if (!capturing_contents()) { + // |render_view_host()| can be NULL if the user middle clicks a link to open + // a tab in then background, then closes the tab before selecting it. This + // is because closing the tab calls TabContents::Destroy(), which removes + // the |render_view_host()|; then when we actually destroy the window, + // OnWindowPosChanged() notices and calls HideContents() (which calls us). + if (render_widget_host_view()) + render_widget_host_view()->WasHidden(); + + // Loop through children and send WasHidden 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->WasHidden(); + } + } + + NotificationService::current()->Notify( + NotificationType::TAB_CONTENTS_HIDDEN, + Source<TabContents>(this), + NotificationService::NoDetails()); +} + void TabContents::Activate() { if (delegate_) delegate_->ActivateContents(this); } +void TabContents::ShowContents() { + if (render_widget_host_view()) + render_widget_host_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(); + } +} + +void TabContents::HideContents() { + // TODO(pkasting): http://b/1239839 Right now we purposefully don't call + // our superclass HideContents(), because some callers want to be very picky + // about the order in which these get called. In addition to making the code + // here practically impossible to understand, this also means we end up + // calling TabContents::WasHidden() twice if callers call both versions of + // HideContents() on a WebContents. + WasHidden(); +} + void TabContents::OpenURL(const GURL& url, const GURL& referrer, WindowOpenDisposition disposition, PageTransition::Type transition) { @@ -219,13 +371,80 @@ void TabContents::OpenURL(const GURL& url, const GURL& referrer, } bool TabContents::NavigateToPendingEntry(bool reload) { - // Our benavior is just to report that the entry was committed. - string16 default_title = WideToUTF16Hack(GetDefaultTitle()); - controller_.pending_entry()->set_title(default_title); - controller_.CommitPendingEntry(); + const NavigationEntry& entry = *controller_.pending_entry(); + + RenderViewHost* dest_render_view_host = render_manager_.Navigate(entry); + if (!dest_render_view_host) + return false; // Unable to create the desired render view host. + + // Tell DevTools agent that it is attached prior to the navigation. + DevToolsManager* dev_tools_manager = g_browser_process->devtools_manager(); + if (dev_tools_manager) // NULL in unit tests. + dev_tools_manager->SendAttachToAgent(*this, dest_render_view_host); + + // Used for page load time metrics. + current_load_start_ = base::TimeTicks::Now(); + + // Navigate in the desired RenderViewHost. + dest_render_view_host->NavigateToEntry(entry, reload); + + if (entry.page_id() == -1) { + // HACK!! This code suppresses javascript: URLs from being added to + // session history, which is what we want to do for javascript: URLs that + // do not generate content. What we really need is a message from the + // renderer telling us that a new page was not created. The same message + // could be used for mailto: URLs and the like. + if (entry.url().SchemeIs(chrome::kJavaScriptScheme)) + return false; + } + + // Clear any provisional password saves - this stops password infobars + // showing up on pages the user navigates to while the right page is + // loading. + GetPasswordManager()->ClearProvisionalSave(); + + if (reload && !profile()->IsOffTheRecord()) { + HistoryService* history = + profile()->GetHistoryService(Profile::IMPLICIT_ACCESS); + if (history) + history->SetFavIconOutOfDateForPage(entry.url()); + } + return true; } +void TabContents::Stop() { + render_manager_.Stop(); + printing_.Stop(); +} + +void TabContents::Cut() { + render_view_host()->Cut(); +} + +void TabContents::Copy() { + render_view_host()->Copy(); +} + +void TabContents::Paste() { + render_view_host()->Paste(); +} + +void TabContents::DisassociateFromPopupCount() { + render_view_host()->DisassociateFromPopupCount(); +} + +TabContents* TabContents::Clone() { + // We create a new SiteInstance so that the new tab won't share processes + // with the old one. This can be changed in the future if we need it to share + // processes for some reason. + TabContents* tc = new WebContents(profile(), + SiteInstance::CreateSiteInstance(profile()), + MSG_ROUTING_NONE, NULL); + tc->controller().CopyStateFrom(controller_); + return tc; +} + #if defined(OS_WIN) ConstrainedWindow* TabContents::CreateConstrainedDialog( views::WindowDelegate* window_delegate, @@ -294,6 +513,37 @@ void TabContents::CloseAllSuppressedPopups() { } #endif +void TabContents::PopupNotificationVisibilityChanged(bool visible) { + render_view_host()->PopupNotificationVisibilityChanged(visible); +} + +gfx::NativeView TabContents::GetContentNativeView() { + return view_->GetContentNativeView(); +} + +gfx::NativeView TabContents::GetNativeView() const { + return view_->GetNativeView(); +} + +void TabContents::GetContainerBounds(gfx::Rect *out) const { + view_->GetContainerBounds(out); +} + +void TabContents::Focus() { + view_->Focus(); +} + +void TabContents::SetInitialFocus(bool reverse) { + render_view_host()->SetInitialFocus(reverse); +} + +bool TabContents::FocusLocationBarByDefault() { + DOMUI* dom_ui = GetDOMUIForCurrentState(); + if (dom_ui) + return dom_ui->focus_location_bar_by_default(); + return false; +} + void TabContents::AddInfoBar(InfoBarDelegate* delegate) { // Look through the existing InfoBarDelegates we have for a match. If we've // already got one that matches, then we don't add the new one. @@ -336,6 +586,51 @@ void TabContents::RemoveInfoBar(InfoBarDelegate* delegate) { } } +bool TabContents::IsBookmarkBarAlwaysVisible() { + // See GetDOMUIForCurrentState() comment for more info. This case is very + // similar, but for non-first loads, we want to use the committed entry. This + // is so the bookmarks bar disappears at the same time the page does. + if (controller_.GetLastCommittedEntry()) { + // Not the first load, always use the committed DOM UI. + if (render_manager_.dom_ui()) + return render_manager_.dom_ui()->force_bookmark_bar_visible(); + return false; // Default. + } + + // When it's the first load, we know either the pending one or the committed + // one will have the DOM UI in it (see GetDOMUIForCurrentState), and only one + // of them will be valid, so we can just check both. + if (render_manager_.pending_dom_ui()) + return render_manager_.pending_dom_ui()->force_bookmark_bar_visible(); + if (render_manager_.dom_ui()) + return render_manager_.dom_ui()->force_bookmark_bar_visible(); + return false; // Default. +} + +void TabContents::SetDownloadShelfVisible(bool visible) { + if (shelf_visible_ != visible) { + if (visible) { + // Invoke GetDownloadShelf to force the shelf to be created. + GetDownloadShelf(); + } + shelf_visible_ = visible; + + if (delegate_) + delegate_->ContentsStateChanged(this); + } + + // SetShelfVisible can force-close the shelf, so make sure we lay out + // everything correctly, as if the animation had finished. This doesn't + // matter for showing the shelf, as the show animation will do it. + ToolbarSizeChanged(false); + + 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_ = base::TimeTicks::Now(); + } +} + void TabContents::ToolbarSizeChanged(bool is_animating) { TabContentsDelegate* d = delegate(); if (d) @@ -459,6 +754,36 @@ void TabContents::StopFinding(bool clear_selection) { render_view_host()->StopFinding(clear_selection); } +// Notifies the RenderWidgetHost instance about the fact that the page is +// loading, or done loading and calls the base implementation. +void TabContents::SetIsLoading(bool is_loading, + LoadNotificationDetails* details) { + if (is_loading == is_loading_) + return; + + if (!is_loading) { + load_state_ = net::LOAD_STATE_IDLE; + load_state_host_.clear(); + } + + render_manager_.SetIsLoading(is_loading); + + is_loading_ = is_loading; + waiting_for_response_ = is_loading; + + if (delegate_) + delegate_->LoadingStateChanged(this); + + NotificationType type = is_loading ? NotificationType::LOAD_START : + NotificationType::LOAD_STOP; + NotificationDetails det = NotificationService::NoDetails();; + if (details) + det = Details<LoadNotificationDetails>(details); + NotificationService::current()->Notify(type, + Source<NavigationController>(&controller_), + det); +} + #if defined(OS_WIN) // TODO(brettw) This should be on the TabContentsView. void TabContents::RepositionSupressedPopupsToFit(const gfx::Size& new_size) { @@ -520,3 +845,43 @@ void TabContents::OnGearsCreateShortcutDone( pending_install_.page_id = 0; pending_install_.callback_functor = NULL; } + +DOMUI* TabContents::GetDOMUIForCurrentState() { + // When there is a pending navigation entry, we want to use the pending DOMUI + // that goes along with it to control the basic flags. For example, we want to + // show the pending URL in the URL bar, so we want the display_url flag to + // be from the pending entry. + // + // The confusion comes because there are multiple possibilities for the + // initial load in a tab as a side effect of the way the RenderViewHostManager + // works. + // + // - For the very first tab the load looks "normal". The new tab DOM UI is + // the pending one, and we want it to apply here. + // + // - For subsequent new tabs, they'll get a new SiteInstance which will then + // get switched to the one previously associated with the new tab pages. + // This switching will cause the manager to commit the RVH/DOMUI. So we'll + // have a committed DOM UI in this case. + // + // This condition handles all of these cases: + // + // - First load in first tab: no committed nav entry + pending nav entry + + // pending dom ui: + // -> Use pending DOM UI if any. + // + // - First load in second tab: no committed nav entry + pending nav entry + + // no pending DOM UI: + // -> Use the committed DOM UI if any. + // + // - Second navigation in any tab: committed nav entry + pending nav entry: + // -> Use pending DOM UI if any. + // + // - Normal state with no load: committed nav entry + no pending nav entry: + // -> Use committed DOM UI. + if (controller_.pending_entry() && + (controller_.GetLastCommittedEntry() || + render_manager_.pending_dom_ui())) + return render_manager_.pending_dom_ui(); + return render_manager_.dom_ui(); +} |