summaryrefslogtreecommitdiffstats
path: root/chrome/browser/tab_contents/tab_contents.cc
diff options
context:
space:
mode:
authorbrettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-04-24 03:28:54 +0000
committerbrettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-04-24 03:28:54 +0000
commit96d185dff2231e09dfcf4b08c9ed878a4a9f7acf (patch)
tree0da07853d5023694ff329398bd9c7f05ed04e05c /chrome/browser/tab_contents/tab_contents.cc
parent695e0fe18af42a8ce29519ed17264d412146de04 (diff)
downloadchromium_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.cc373
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();
+}