blob: cff43e55ad4e0b8c09178d2585f99411f75fe37c [file] [log] [blame]
[email protected]61d68ef12011-01-13 14:02:561// Copyright (c) 2011 The Chromium Authors. All rights reserved.
license.botbf09a502008-08-24 00:55:552// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commit09911bf2008-07-26 23:55:294
[email protected]0dd3a0ab2011-02-18 08:17:445#include "content/browser/tab_contents/tab_contents.h"
[email protected]39526562011-02-05 03:41:516
[email protected]b75b8292010-10-01 07:28:257#include <cmath>
8
[email protected]36fb2c7c2011-04-04 15:49:089#include "base/command_line.h"
[email protected]835d7c82010-10-14 04:38:3810#include "base/metrics/histogram.h"
[email protected]724159a2010-12-30 01:11:1811#include "base/metrics/stats_counters.h"
[email protected]96d185d2009-04-24 03:28:5412#include "base/string16.h"
[email protected]996fd702009-09-04 19:12:3713#include "base/string_util.h"
[email protected]96d185d2009-04-24 03:28:5414#include "base/time.h"
[email protected]3c733bde2010-12-21 19:56:3115#include "base/utf_string_conversions.h"
[email protected]96d185d2009-04-24 03:28:5416#include "chrome/browser/debugger/devtools_manager.h"
[email protected]420ae012009-04-24 05:16:3217#include "chrome/browser/load_from_memory_cache_details.h"
[email protected]f364d1392011-04-08 21:03:1018#include "chrome/browser/notifications/desktop_notification_service.h"
[email protected]dcb72d52011-04-13 12:36:5319#include "chrome/browser/notifications/desktop_notification_service_factory.h"
[email protected]8ecad5e2010-12-02 21:18:3320#include "chrome/browser/profiles/profile.h"
[email protected]567812d2011-02-24 17:40:5021#include "content/browser/child_process_security_policy.h"
[email protected]1fd1a502011-03-30 16:55:5622#include "content/browser/content_browser_client.h"
[email protected]567812d2011-02-24 17:40:5023#include "content/browser/host_zoom_map.h"
24#include "content/browser/in_process_webkit/session_storage_namespace.h"
[email protected]35e251d2011-05-24 21:01:0425#include "content/browser/load_notification_details.h"
[email protected]567812d2011-02-24 17:40:5026#include "content/browser/renderer_host/render_process_host.h"
27#include "content/browser/renderer_host/render_view_host.h"
28#include "content/browser/renderer_host/render_widget_host_view.h"
29#include "content/browser/renderer_host/resource_request_details.h"
30#include "content/browser/site_instance.h"
[email protected]0dd3a0ab2011-02-18 08:17:4431#include "content/browser/tab_contents/interstitial_page.h"
[email protected]8286f51a2011-05-31 17:39:1332#include "content/browser/tab_contents/navigation_details.h"
[email protected]0dd3a0ab2011-02-18 08:17:4433#include "content/browser/tab_contents/navigation_entry.h"
34#include "content/browser/tab_contents/provisional_load_details.h"
35#include "content/browser/tab_contents/tab_contents_delegate.h"
36#include "content/browser/tab_contents/tab_contents_observer.h"
37#include "content/browser/tab_contents/tab_contents_view.h"
[email protected]105bb0f2011-05-24 17:12:1438#include "content/browser/tab_contents/title_updated_details.h"
[email protected]afd1e522011-04-27 23:29:5939#include "content/browser/user_metrics.h"
[email protected]1fd1a502011-03-30 16:55:5640#include "content/browser/webui/web_ui_factory.h"
[email protected]9966325b2011-04-18 05:00:1041#include "content/common/bindings_policy.h"
[email protected]1fd1a502011-03-30 16:55:5642#include "content/common/content_client.h"
[email protected]763ec4ca2011-04-29 15:48:1243#include "content/common/content_restriction.h"
[email protected]4dd57932011-03-17 06:06:1244#include "content/common/navigation_types.h"
[email protected]7f070d42011-03-09 20:25:3245#include "content/common/notification_service.h"
[email protected]0f012df82011-05-19 14:15:2946#include "content/common/url_constants.h"
[email protected]2c5569662011-03-22 20:45:0247#include "content/common/view_messages.h"
[email protected]d686e812009-06-03 19:10:2948#include "net/base/net_util.h"
[email protected]420ae012009-04-24 05:16:3249#include "net/base/registry_controlled_domain.h"
[email protected]abe2c032011-03-31 18:49:3450#include "net/url_request/url_request_context_getter.h"
[email protected]8bd0fe62011-01-17 06:44:3751#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
[email protected]42ce29d2011-01-20 23:19:4652#include "ui/base/resource/resource_bundle.h"
[email protected]08397d52011-02-05 01:53:3853#include "ui/gfx/codec/png_codec.h"
[email protected]d5e311b2010-07-20 17:15:0354#include "webkit/glue/password_form.h"
[email protected]3c733bde2010-12-21 19:56:3155#include "webkit/glue/webpreferences.h"
56
57#if defined(OS_MACOSX)
[email protected]b9b751f22011-03-25 14:04:1258#include "ui/gfx/surface/io_surface_support_mac.h"
[email protected]3c733bde2010-12-21 19:56:3159#endif // defined(OS_MACOSX)
[email protected]3e45ba92009-02-20 21:09:0060
[email protected]420ae012009-04-24 05:16:3261// Cross-Site Navigations
62//
63// If a TabContents is told to navigate to a different web site (as determined
64// by SiteInstance), it will replace its current RenderViewHost with a new
65// RenderViewHost dedicated to the new SiteInstance. This works as follows:
66//
67// - Navigate determines whether the destination is cross-site, and if so,
68// it creates a pending_render_view_host_ and moves into the PENDING
69// RendererState.
70// - The pending RVH is "suspended," so that no navigation messages are sent to
71// its renderer until the onbeforeunload JavaScript handler has a chance to
72// run in the current RVH.
73// - The pending RVH tells CrossSiteRequestManager (a thread-safe singleton)
74// that it has a pending cross-site request. ResourceDispatcherHost will
75// check for this when the response arrives.
76// - The current RVH runs its onbeforeunload handler. If it returns false, we
77// cancel all the pending logic and go back to NORMAL. Otherwise we allow
78// the pending RVH to send the navigation request to its renderer.
79// - ResourceDispatcherHost receives a ResourceRequest on the IO thread. It
80// checks CrossSiteRequestManager to see that the RVH responsible has a
81// pending cross-site request, and then installs a CrossSiteEventHandler.
82// - When RDH receives a response, the BufferedEventHandler determines whether
83// it is a download. If so, it sends a message to the new renderer causing
84// it to cancel the request, and the download proceeds in the download
85// thread. For now, we stay in a PENDING state (with a pending RVH) until
[email protected]57c6a652009-05-04 07:58:3486// the next DidNavigate event for this TabContents. This isn't ideal, but it
[email protected]420ae012009-04-24 05:16:3287// doesn't affect any functionality.
88// - After RDH receives a response and determines that it is safe and not a
89// download, it pauses the response to first run the old page's onunload
90// handler. It does this by asynchronously calling the OnCrossSiteResponse
[email protected]992db4c2011-05-12 15:37:1591// method of TabContents on the UI thread, which sends a SwapOut message
[email protected]420ae012009-04-24 05:16:3292// to the current RVH.
[email protected]992db4c2011-05-12 15:37:1593// - Once the onunload handler is finished, a SwapOut_ACK message is sent to
[email protected]420ae012009-04-24 05:16:3294// the ResourceDispatcherHost, who unpauses the response. Data is then sent
95// to the pending RVH.
96// - The pending renderer sends a FrameNavigate message that invokes the
97// DidNavigate method. This replaces the current RVH with the
98// pending RVH and goes back to the NORMAL RendererState.
[email protected]992db4c2011-05-12 15:37:1599// - The previous renderer is kept swapped out in RenderViewHostManager in case
100// the user goes back. The process only stays live if another tab is using
101// it, but if so, the existing frame relationships will be maintained.
[email protected]420ae012009-04-24 05:16:32102
103namespace {
104
105// Amount of time we wait between when a key event is received and the renderer
106// is queried for its state and pushed to the NavigationEntry.
107const int kQueryStateDelay = 5000;
108
[email protected]6ebdc9b2010-09-27 16:55:57109const int kSyncWaitDelay = 40;
110
[email protected]420ae012009-04-24 05:16:32111#if defined(OS_WIN)
112
113BOOL CALLBACK InvalidateWindow(HWND hwnd, LPARAM lparam) {
114 // Note: erase is required to properly paint some widgets borders. This can
115 // be seen with textfields.
116 InvalidateRect(hwnd, NULL, TRUE);
117 return TRUE;
118}
119#endif
120
[email protected]2c5569662011-03-22 20:45:02121ViewMsg_Navigate_Type::Value GetNavigationType(
[email protected]1ccb3568d2010-02-19 10:51:16122 Profile* profile, const NavigationEntry& entry,
123 NavigationController::ReloadType reload_type) {
124 switch (reload_type) {
125 case NavigationController::RELOAD:
[email protected]2c5569662011-03-22 20:45:02126 return ViewMsg_Navigate_Type::RELOAD;
[email protected]1ccb3568d2010-02-19 10:51:16127 case NavigationController::RELOAD_IGNORING_CACHE:
[email protected]2c5569662011-03-22 20:45:02128 return ViewMsg_Navigate_Type::RELOAD_IGNORING_CACHE;
[email protected]1ccb3568d2010-02-19 10:51:16129 case NavigationController::NO_RELOAD:
130 break; // Fall through to rest of function.
131 }
[email protected]5e369672009-11-03 23:48:30132
133 if (entry.restore_type() == NavigationEntry::RESTORE_LAST_SESSION &&
134 profile->DidLastSessionExitCleanly())
[email protected]2c5569662011-03-22 20:45:02135 return ViewMsg_Navigate_Type::RESTORE;
[email protected]5e369672009-11-03 23:48:30136
[email protected]2c5569662011-03-22 20:45:02137 return ViewMsg_Navigate_Type::NORMAL;
[email protected]5e369672009-11-03 23:48:30138}
139
[email protected]876bc832010-09-07 16:29:54140void MakeNavigateParams(const NavigationEntry& entry,
141 const NavigationController& controller,
[email protected]1ccb3568d2010-02-19 10:51:16142 NavigationController::ReloadType reload_type,
143 ViewMsg_Navigate_Params* params) {
[email protected]056de2d2009-06-26 16:41:34144 params->page_id = entry.page_id();
[email protected]876bc832010-09-07 16:29:54145 params->pending_history_list_offset = controller.GetIndexOfEntry(&entry);
[email protected]3cc72b12010-03-18 23:03:00146 params->current_history_list_offset = controller.last_committed_entry_index();
147 params->current_history_list_length = controller.entry_count();
[email protected]056de2d2009-06-26 16:41:34148 params->url = entry.url();
149 params->referrer = entry.referrer();
150 params->transition = entry.transition_type();
151 params->state = entry.content_state();
[email protected]3cc72b12010-03-18 23:03:00152 params->navigation_type =
153 GetNavigationType(controller.profile(), entry, reload_type);
[email protected]056de2d2009-06-26 16:41:34154 params->request_time = base::Time::Now();
155}
156
[email protected]420ae012009-04-24 05:16:32157} // namespace
158
[email protected]f4f50ef2011-01-21 19:01:19159
160// TabContents ----------------------------------------------------------------
[email protected]420ae012009-04-24 05:16:32161
[email protected]420ae012009-04-24 05:16:32162TabContents::TabContents(Profile* profile,
163 SiteInstance* site_instance,
164 int routing_id,
[email protected]6ee12c42010-09-14 09:36:07165 const TabContents* base_tab_contents,
166 SessionStorageNamespace* session_storage_namespace)
[email protected]b680ad22009-04-15 23:19:42167 : delegate_(NULL),
[email protected]6ee12c42010-09-14 09:36:07168 ALLOW_THIS_IN_INITIALIZER_LIST(controller_(
169 this, profile, session_storage_namespace)),
[email protected]66ba4932009-06-04 19:22:13170 ALLOW_THIS_IN_INITIALIZER_LIST(view_(
[email protected]d82ed61e2009-06-16 02:46:22171 TabContentsView::Create(this))),
172 ALLOW_THIS_IN_INITIALIZER_LIST(render_manager_(this, this)),
[email protected]6f821dd2010-02-23 00:54:06173 bookmark_drag_(NULL),
[email protected]d5f942ba2008-09-26 19:30:34174 is_loading_(false),
[email protected]443b80e2010-12-14 00:42:23175 crashed_status_(base::TERMINATION_STATUS_STILL_RUNNING),
176 crashed_error_code_(0),
[email protected]d5f942ba2008-09-26 19:30:34177 waiting_for_response_(false),
[email protected]d5f942ba2008-09-26 19:30:34178 max_page_id_(-1),
[email protected]fdd61c62009-04-22 19:22:57179 load_state_(net::LOAD_STATE_IDLE),
[email protected]094e5b22009-09-25 04:23:56180 upload_size_(0),
181 upload_position_(0),
[email protected]f17a0ee2010-05-17 17:38:47182 displayed_insecure_content_(false),
[email protected]fdd61c62009-04-22 19:22:57183 capturing_contents_(false),
184 is_being_destroyed_(false),
185 notify_disconnection_(false),
[email protected]fdd61c62009-04-22 19:22:57186#if defined(OS_WIN)
187 message_box_active_(CreateEvent(NULL, TRUE, FALSE, NULL)),
188#endif
[email protected]7ab1e7d62009-10-14 23:32:01189 is_showing_before_unload_dialog_(false),
[email protected]1fd1a502011-03-30 16:55:56190 opener_web_ui_type_(WebUI::kNoWebUI),
[email protected]ebf40a72010-07-22 01:46:38191 closed_by_user_gesture_(false),
[email protected]b75b8292010-10-01 07:28:25192 minimum_zoom_percent_(
193 static_cast<int>(WebKit::WebView::minTextSizeMultiplier * 100)),
194 maximum_zoom_percent_(
195 static_cast<int>(WebKit::WebView::maxTextSizeMultiplier * 100)),
[email protected]9e823662010-10-13 23:36:00196 temporary_zoom_settings_(false),
[email protected]4850a7f2011-03-08 23:36:59197 content_restrictions_(0) {
[email protected]7ff431e2010-01-07 18:18:54198
[email protected]12636df2009-09-28 22:32:21199 render_manager_.Init(profile, site_instance, routing_id);
[email protected]420ae012009-04-24 05:16:32200
[email protected]34ac70502009-09-25 17:07:23201 // We have the initial size of the view be based on the size of the passed in
202 // tab contents (normally a tab from the same window).
203 view_->CreateView(base_tab_contents ?
204 base_tab_contents->view()->GetContainerSize() : gfx::Size());
[email protected]420ae012009-04-24 05:16:32205
[email protected]420ae012009-04-24 05:16:32206 registrar_.Add(this, NotificationType::RENDER_WIDGET_HOST_DESTROYED,
207 NotificationService::AllSources());
[email protected]88152052010-10-01 04:05:18208
[email protected]b5a1d11c2011-02-17 03:09:42209 // Can only add observers after render_manager_.Init() is called, since that's
210 // what sets up the render_view_host which TabContentObserver's constructor
211 // uses to get the routing_id.
212 AddObservers();
[email protected]332af7732009-03-11 13:21:35213}
initial.commit09911bf2008-07-26 23:55:29214
215TabContents::~TabContents() {
[email protected]420ae012009-04-24 05:16:32216 is_being_destroyed_ = true;
217
[email protected]bfe4c1582009-10-02 18:11:09218 // We don't want any notifications while we're running our destructor.
[email protected]420ae012009-04-24 05:16:32219 registrar_.RemoveAll();
[email protected]420ae012009-04-24 05:16:32220
[email protected]3ab9cb82011-06-03 18:02:07221 // Clear out any JavaScript state.
222 if (delegate_)
223 delegate_->GetJavaScriptDialogCreator()->ResetJavaScriptState(this);
224
[email protected]420ae012009-04-24 05:16:32225 NotifyDisconnected();
[email protected]420ae012009-04-24 05:16:32226
[email protected]420ae012009-04-24 05:16:32227 // First cleanly close all child windows.
228 // TODO(mpcomplete): handle case if MaybeCloseChildWindows() already asked
229 // some of these to close. CloseWindows is async, so it might get called
230 // twice before it runs.
[email protected]8cc8d492010-02-02 10:40:49231 CloseConstrainedWindows();
[email protected]420ae012009-04-24 05:16:32232
[email protected]420ae012009-04-24 05:16:32233 // Notify any observer that have a reference on this tab contents.
234 NotificationService::current()->Notify(
235 NotificationType::TAB_CONTENTS_DESTROYED,
236 Source<TabContents>(this),
237 NotificationService::NoDetails());
238
239 // TODO(brettw) this should be moved to the view.
240#if defined(OS_WIN)
241 // If we still have a window handle, destroy it. GetNativeView can return
242 // NULL if this contents was part of a window that closed.
[email protected]50bd6452010-11-27 19:39:42243 if (GetNativeView()) {
244 RenderViewHost* host = render_view_host();
[email protected]b9a1fb42011-04-12 23:16:44245 if (host && host->view())
[email protected]50bd6452010-11-27 19:39:42246 host->view()->WillWmDestroy();
[email protected]50bd6452010-11-27 19:39:42247 }
[email protected]420ae012009-04-24 05:16:32248#endif
[email protected]7ab1e7d62009-10-14 23:32:01249
250 // OnCloseStarted isn't called in unit tests.
251 if (!tab_close_start_time_.is_null()) {
252 UMA_HISTOGRAM_TIMES("Tab.Close",
253 base::TimeTicks::Now() - tab_close_start_time_);
254 }
[email protected]b5a1d11c2011-02-17 03:09:42255
[email protected]07d490bc2011-03-07 17:05:26256 FOR_EACH_OBSERVER(TabContentsObserver, observers_, TabContentsDestroyed());
[email protected]232a5812011-03-04 22:42:08257
258 net::NetworkChangeNotifier::RemoveOnlineStateObserver(this);
[email protected]b5a1d11c2011-02-17 03:09:42259}
260
261void TabContents::AddObservers() {
[email protected]232a5812011-03-04 22:42:08262 net::NetworkChangeNotifier::AddOnlineStateObserver(this);
initial.commit09911bf2008-07-26 23:55:29263}
264
[email protected]724159a2010-12-30 01:11:18265bool TabContents::OnMessageReceived(const IPC::Message& message) {
[email protected]f82d57b52011-04-27 19:13:17266 if (web_ui() && web_ui()->OnMessageReceived(message))
267 return true;
268
[email protected]585b30362011-01-28 02:30:17269 ObserverListBase<TabContentsObserver>::Iterator it(observers_);
270 TabContentsObserver* observer;
[email protected]0f180ee2011-01-21 18:23:10271 while ((observer = it.GetNext()) != NULL)
272 if (observer->OnMessageReceived(message))
[email protected]403415a2011-01-10 18:57:53273 return true;
[email protected]403415a2011-01-10 18:57:53274
[email protected]724159a2010-12-30 01:11:18275 bool handled = true;
276 bool message_is_ok = true;
277 IPC_BEGIN_MESSAGE_MAP_EX(TabContents, message, message_is_ok)
278 IPC_MESSAGE_HANDLER(ViewHostMsg_DidStartProvisionalLoadForFrame,
279 OnDidStartProvisionalLoadForFrame)
280 IPC_MESSAGE_HANDLER(ViewHostMsg_DidRedirectProvisionalLoad,
281 OnDidRedirectProvisionalLoad)
282 IPC_MESSAGE_HANDLER(ViewHostMsg_DidFailProvisionalLoadWithError,
283 OnDidFailProvisionalLoadWithError)
284 IPC_MESSAGE_HANDLER(ViewHostMsg_DidLoadResourceFromMemoryCache,
285 OnDidLoadResourceFromMemoryCache)
286 IPC_MESSAGE_HANDLER(ViewHostMsg_DidDisplayInsecureContent,
287 OnDidDisplayInsecureContent)
288 IPC_MESSAGE_HANDLER(ViewHostMsg_DidRunInsecureContent,
289 OnDidRunInsecureContent)
290 IPC_MESSAGE_HANDLER(ViewHostMsg_DocumentLoadedInFrame,
291 OnDocumentLoadedInFrame)
292 IPC_MESSAGE_HANDLER(ViewHostMsg_DidFinishLoad, OnDidFinishLoad)
[email protected]c8f73ab2011-01-22 00:05:17293 IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateContentRestrictions,
294 OnUpdateContentRestrictions)
[email protected]7d472472011-01-22 01:30:25295 IPC_MESSAGE_HANDLER(ViewHostMsg_GoToEntryAtOffset, OnGoToEntryAtOffset)
[email protected]216813952011-05-19 22:21:26296 IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateZoomLimits, OnUpdateZoomLimits)
297 IPC_MESSAGE_HANDLER(ViewHostMsg_FocusedNodeChanged, OnFocusedNodeChanged)
[email protected]724159a2010-12-30 01:11:18298 IPC_MESSAGE_UNHANDLED(handled = false)
299 IPC_END_MESSAGE_MAP_EX()
300
301 if (!message_is_ok) {
302 UserMetrics::RecordAction(UserMetricsAction("BadMessageTerminate_RVD"));
303 GetRenderProcessHost()->ReceivedBadMessage();
304 }
305
306 return handled;
307}
308
[email protected]13367f72009-07-08 16:39:02309// Returns true if contains content rendered by an extension.
310bool TabContents::HostsExtension() const {
311 return GetURL().SchemeIs(chrome::kExtensionScheme);
[email protected]d5f942ba2008-09-26 19:30:34312}
313
[email protected]8cb5d5b2010-02-09 11:36:16314RenderProcessHost* TabContents::GetRenderProcessHost() const {
315 return render_manager_.current_host()->process();
316}
317
[email protected]d5f942ba2008-09-26 19:30:34318const GURL& TabContents::GetURL() const {
319 // We may not have a navigation entry yet
[email protected]ce3fa3c2009-04-20 19:55:57320 NavigationEntry* entry = controller_.GetActiveEntry();
[email protected]ebe89e062009-08-13 23:16:54321 return entry ? entry->virtual_url() : GURL::EmptyGURL();
[email protected]d5f942ba2008-09-26 19:30:34322}
323
[email protected]96d185d2009-04-24 03:28:54324const string16& TabContents::GetTitle() const {
[email protected]4c6092c5b2009-06-06 00:23:55325 // Transient entries take precedence. They are used for interstitial pages
326 // that are shown on top of existing pages.
327 NavigationEntry* entry = controller_.GetTransientEntry();
[email protected]b5cca982011-05-26 04:42:08328 std::string accept_languages =
329 content::GetContentClient()->browser()->GetAcceptLangs(this);
[email protected]45d0ef7f2011-01-05 13:46:23330 if (entry) {
[email protected]b5cca982011-05-26 04:42:08331 return entry->GetTitleForDisplay(accept_languages);
[email protected]45d0ef7f2011-01-05 13:46:23332 }
[email protected]7ade2732011-02-10 00:13:58333 WebUI* our_web_ui = render_manager_.pending_web_ui() ?
334 render_manager_.pending_web_ui() : render_manager_.web_ui();
335 if (our_web_ui) {
[email protected]96d185d2009-04-24 03:28:54336 // Don't override the title in view source mode.
[email protected]4c6092c5b2009-06-06 00:23:55337 entry = controller_.GetActiveEntry();
[email protected]96d185d2009-04-24 03:28:54338 if (!(entry && entry->IsViewSourceMode())) {
[email protected]e0112912011-02-02 22:54:35339 // Give the Web UI the chance to override our title.
[email protected]7ade2732011-02-10 00:13:58340 const string16& title = our_web_ui->overridden_title();
[email protected]96d185d2009-04-24 03:28:54341 if (!title.empty())
342 return title;
343 }
344 }
345
346 // We use the title for the last committed entry rather than a pending
347 // navigation entry. For example, when the user types in a URL, we want to
348 // keep the old page's title until the new load has committed and we get a new
349 // title.
[email protected]96d185d2009-04-24 03:28:54350 entry = controller_.GetLastCommittedEntry();
[email protected]45d0ef7f2011-01-05 13:46:23351 if (entry) {
[email protected]b5cca982011-05-26 04:42:08352 return entry->GetTitleForDisplay(accept_languages);
[email protected]45d0ef7f2011-01-05 13:46:23353 }
[email protected]987fc3a2011-05-26 14:18:09354
355 // |page_title_when_no_navigation_entry_| is finally used
356 // if no title cannot be retrieved.
357 return page_title_when_no_navigation_entry_;
[email protected]96d185d2009-04-24 03:28:54358}
359
[email protected]d5f942ba2008-09-26 19:30:34360int32 TabContents::GetMaxPageID() {
361 if (GetSiteInstance())
362 return GetSiteInstance()->max_page_id();
363 else
364 return max_page_id_;
365}
366
367void TabContents::UpdateMaxPageID(int32 page_id) {
368 // Ensure both the SiteInstance and RenderProcessHost update their max page
[email protected]57c6a652009-05-04 07:58:34369 // IDs in sync. Only TabContents will also have site instances, except during
[email protected]d5f942ba2008-09-26 19:30:34370 // testing.
371 if (GetSiteInstance())
372 GetSiteInstance()->UpdateMaxPageID(page_id);
[email protected]8cb5d5b2010-02-09 11:36:16373 GetRenderProcessHost()->UpdateMaxPageID(page_id);
[email protected]d5f942ba2008-09-26 19:30:34374}
375
[email protected]96d185d2009-04-24 03:28:54376SiteInstance* TabContents::GetSiteInstance() const {
377 return render_manager_.current_host()->site_instance();
378}
379
[email protected]96d185d2009-04-24 03:28:54380bool TabContents::ShouldDisplayURL() {
[email protected]8ab24cc2009-11-13 20:56:15381 // Don't hide the url in view source mode and with interstitials.
[email protected]96d185d2009-04-24 03:28:54382 NavigationEntry* entry = controller_.GetActiveEntry();
[email protected]8ab24cc2009-11-13 20:56:15383 if (entry && (entry->IsViewSourceMode() ||
[email protected]cccd3762010-11-12 18:40:01384 entry->page_type() == INTERSTITIAL_PAGE)) {
[email protected]96d185d2009-04-24 03:28:54385 return true;
[email protected]8ab24cc2009-11-13 20:56:15386 }
[email protected]83e3895b2009-06-11 00:07:16387
[email protected]2b9a06402011-02-16 04:57:10388 // We always display the URL for non-WebUI URLs to prevent spoofing.
[email protected]1fd1a502011-03-30 16:55:56389 if (entry && !content::WebUIFactory::Get()->HasWebUIScheme(entry->url()))
[email protected]2b9a06402011-02-16 04:57:10390 return true;
391
[email protected]d0980792011-02-13 19:41:40392 WebUI* web_ui = GetWebUIForCurrentState();
[email protected]7ade2732011-02-10 00:13:58393 if (web_ui)
394 return !web_ui->should_hide_url();
[email protected]96d185d2009-04-24 03:28:54395 return true;
396}
397
[email protected]585b30362011-01-28 02:30:17398void TabContents::AddObserver(TabContentsObserver* observer) {
399 observers_.AddObserver(observer);
[email protected]3c9e1872010-11-18 16:17:49400}
401
[email protected]585b30362011-01-28 02:30:17402void TabContents::RemoveObserver(TabContentsObserver* observer) {
403 observers_.RemoveObserver(observer);
[email protected]3c9e1872010-11-18 16:17:49404}
405
[email protected]443b80e2010-12-14 00:42:23406void TabContents::SetIsCrashed(base::TerminationStatus status, int error_code) {
407 if (status == crashed_status_)
[email protected]d5f942ba2008-09-26 19:30:34408 return;
409
[email protected]443b80e2010-12-14 00:42:23410 crashed_status_ = status;
411 crashed_error_code_ = error_code;
[email protected]c9cd2222009-05-06 05:16:50412 NotifyNavigationStateChanged(INVALIDATE_TAB);
[email protected]d5f942ba2008-09-26 19:30:34413}
414
415void TabContents::NotifyNavigationStateChanged(unsigned changed_flags) {
416 if (delegate_)
417 delegate_->NavigationStateChanged(this, changed_flags);
418}
419
[email protected]96d185d2009-04-24 03:28:54420void TabContents::DidBecomeSelected() {
421 controller_.SetActive(true);
[email protected]8cb5d5b2010-02-09 11:36:16422 RenderWidgetHostView* rwhv = GetRenderWidgetHostView();
423 if (rwhv) {
424 rwhv->DidBecomeSelected();
[email protected]789e9152009-08-04 21:59:43425#if defined(OS_MACOSX)
[email protected]8cb5d5b2010-02-09 11:36:16426 rwhv->SetActive(true);
[email protected]789e9152009-08-04 21:59:43427#endif
428 }
[email protected]96d185d2009-04-24 03:28:54429
[email protected]5ac20162010-11-24 23:33:11430 last_selected_time_ = base::TimeTicks::Now();
[email protected]3e69bc82011-05-26 23:22:38431
432 FOR_EACH_OBSERVER(TabContentsObserver, observers_, DidBecomeSelected());
[email protected]96d185d2009-04-24 03:28:54433}
434
435void TabContents::WasHidden() {
436 if (!capturing_contents()) {
437 // |render_view_host()| can be NULL if the user middle clicks a link to open
438 // a tab in then background, then closes the tab before selecting it. This
439 // is because closing the tab calls TabContents::Destroy(), which removes
440 // the |render_view_host()|; then when we actually destroy the window,
441 // OnWindowPosChanged() notices and calls HideContents() (which calls us).
[email protected]8cb5d5b2010-02-09 11:36:16442 RenderWidgetHostView* rwhv = GetRenderWidgetHostView();
443 if (rwhv)
444 rwhv->WasHidden();
[email protected]96d185d2009-04-24 03:28:54445 }
446
447 NotificationService::current()->Notify(
448 NotificationType::TAB_CONTENTS_HIDDEN,
449 Source<TabContents>(this),
450 NotificationService::NoDetails());
451}
452
[email protected]d5f942ba2008-09-26 19:30:34453void TabContents::Activate() {
454 if (delegate_)
455 delegate_->ActivateContents(this);
456}
457
[email protected]ea42e7782010-08-23 23:58:12458void TabContents::Deactivate() {
459 if (delegate_)
460 delegate_->DeactivateContents(this);
461}
462
[email protected]96d185d2009-04-24 03:28:54463void TabContents::ShowContents() {
[email protected]8cb5d5b2010-02-09 11:36:16464 RenderWidgetHostView* rwhv = GetRenderWidgetHostView();
465 if (rwhv)
466 rwhv->DidBecomeSelected();
[email protected]96d185d2009-04-24 03:28:54467}
468
469void TabContents::HideContents() {
470 // TODO(pkasting): http://b/1239839 Right now we purposefully don't call
471 // our superclass HideContents(), because some callers want to be very picky
472 // about the order in which these get called. In addition to making the code
473 // here practically impossible to understand, this also means we end up
474 // calling TabContents::WasHidden() twice if callers call both versions of
[email protected]57c6a652009-05-04 07:58:34475 // HideContents() on a TabContents.
[email protected]96d185d2009-04-24 03:28:54476 WasHidden();
477}
478
[email protected]5aab5e22010-12-08 22:13:29479bool TabContents::NeedToFireBeforeUnload() {
480 // TODO(creis): Should we fire even for interstitial pages?
481 return notify_disconnection() &&
482 !showing_interstitial_page() &&
483 !render_view_host()->SuddenTerminationAllowed();
484}
485
[email protected]c0588052008-10-27 23:01:50486void TabContents::OpenURL(const GURL& url, const GURL& referrer,
[email protected]d5f942ba2008-09-26 19:30:34487 WindowOpenDisposition disposition,
488 PageTransition::Type transition) {
[email protected]1c642b52011-04-15 09:05:49489 if (delegate_) {
[email protected]c0588052008-10-27 23:01:50490 delegate_->OpenURLFromTab(this, url, referrer, disposition, transition);
[email protected]1c642b52011-04-15 09:05:49491 // Notify observers.
492 FOR_EACH_OBSERVER(TabContentsObserver, observers_,
493 DidOpenURL(url, referrer, disposition, transition));
494 }
[email protected]d5f942ba2008-09-26 19:30:34495}
496
[email protected]1ccb3568d2010-02-19 10:51:16497bool TabContents::NavigateToPendingEntry(
498 NavigationController::ReloadType reload_type) {
[email protected]876bc832010-09-07 16:29:54499 return NavigateToEntry(*controller_.pending_entry(), reload_type);
500}
[email protected]96d185d2009-04-24 03:28:54501
[email protected]876bc832010-09-07 16:29:54502bool TabContents::NavigateToEntry(
503 const NavigationEntry& entry,
504 NavigationController::ReloadType reload_type) {
[email protected]96d185d2009-04-24 03:28:54505 RenderViewHost* dest_render_view_host = render_manager_.Navigate(entry);
506 if (!dest_render_view_host)
507 return false; // Unable to create the desired render view host.
508
[email protected]770dd8b2010-05-24 18:11:39509 if (delegate_ && delegate_->ShouldEnablePreferredSizeNotifications()) {
[email protected]216813952011-05-19 22:21:26510 dest_render_view_host->Send(new ViewMsg_EnablePreferredSizeChangedMode(
511 dest_render_view_host->routing_id(),
512 kPreferredSizeWidth | kPreferredSizeHeightThisIsSlow));
[email protected]770dd8b2010-05-24 18:11:39513 }
[email protected]9fb325e2010-05-06 18:23:24514
[email protected]80a8fad2011-01-29 04:02:38515 // For security, we should never send non-Web-UI URLs to a Web UI renderer.
[email protected]05fdd492010-11-15 17:52:07516 // Double check that here.
[email protected]54ec6472010-04-09 19:39:58517 int enabled_bindings = dest_render_view_host->enabled_bindings();
[email protected]1fd1a502011-03-30 16:55:56518 bool is_allowed_in_web_ui_renderer = content::GetContentClient()->
519 browser()->GetWebUIFactory()->IsURLAcceptableForWebUI(profile(),
520 entry.url());
[email protected]c09163a2011-02-15 00:05:55521 CHECK(!BindingsPolicy::is_web_ui_enabled(enabled_bindings) ||
522 is_allowed_in_web_ui_renderer);
[email protected]54ec6472010-04-09 19:39:58523
[email protected]96d185d2009-04-24 03:28:54524 // Tell DevTools agent that it is attached prior to the navigation.
[email protected]d9f9b792009-06-24 13:17:12525 DevToolsManager* devtools_manager = DevToolsManager::GetInstance();
[email protected]7e8e6b62009-05-08 11:28:32526 if (devtools_manager) { // NULL in unit tests.
[email protected]3cc72b12010-03-18 23:03:00527 devtools_manager->OnNavigatingToPendingEntry(render_view_host(),
528 dest_render_view_host,
529 entry.url());
[email protected]7e8e6b62009-05-08 11:28:32530 }
[email protected]96d185d2009-04-24 03:28:54531
532 // Used for page load time metrics.
533 current_load_start_ = base::TimeTicks::Now();
534
535 // Navigate in the desired RenderViewHost.
[email protected]056de2d2009-06-26 16:41:34536 ViewMsg_Navigate_Params navigate_params;
[email protected]876bc832010-09-07 16:29:54537 MakeNavigateParams(entry, controller_, reload_type, &navigate_params);
[email protected]52c68652010-12-07 17:47:04538 if (delegate_) {
539 navigate_params.extra_headers =
540 delegate_->GetNavigationHeaders(navigate_params.url);
541 }
[email protected]056de2d2009-06-26 16:41:34542 dest_render_view_host->Navigate(navigate_params);
[email protected]96d185d2009-04-24 03:28:54543
544 if (entry.page_id() == -1) {
545 // HACK!! This code suppresses javascript: URLs from being added to
546 // session history, which is what we want to do for javascript: URLs that
547 // do not generate content. What we really need is a message from the
548 // renderer telling us that a new page was not created. The same message
549 // could be used for mailto: URLs and the like.
550 if (entry.url().SchemeIs(chrome::kJavaScriptScheme))
551 return false;
552 }
553
[email protected]3c9e1872010-11-18 16:17:49554 // Notify observers about navigation.
[email protected]b375c5d2011-05-03 21:15:04555 FOR_EACH_OBSERVER(TabContentsObserver,
556 observers_,
557 NavigateToPendingEntry(entry.url(), reload_type));
[email protected]96d185d2009-04-24 03:28:54558
[email protected]d5f942ba2008-09-26 19:30:34559 return true;
560}
561
[email protected]96d185d2009-04-24 03:28:54562void TabContents::Stop() {
563 render_manager_.Stop();
[email protected]2e3f4572011-03-25 19:24:47564 FOR_EACH_OBSERVER(TabContentsObserver, observers_, StopNavigation());
[email protected]96d185d2009-04-24 03:28:54565}
566
[email protected]96d185d2009-04-24 03:28:54567TabContents* TabContents::Clone() {
568 // We create a new SiteInstance so that the new tab won't share processes
569 // with the old one. This can be changed in the future if we need it to share
570 // processes for some reason.
[email protected]420ae012009-04-24 05:16:32571 TabContents* tc = new TabContents(profile(),
[email protected]96d185d2009-04-24 03:28:54572 SiteInstance::CreateSiteInstance(profile()),
[email protected]6ee12c42010-09-14 09:36:07573 MSG_ROUTING_NONE, this, NULL);
[email protected]96d185d2009-04-24 03:28:54574 tc->controller().CopyStateFrom(controller_);
575 return tc;
576}
577
[email protected]4d677202009-07-19 07:37:12578void TabContents::ShowPageInfo(const GURL& url,
579 const NavigationEntry::SSLStatus& ssl,
580 bool show_history) {
581 if (!delegate_)
582 return;
583
[email protected]bb678332009-07-21 00:15:50584 delegate_->ShowPageInfo(profile(), url, ssl, show_history);
[email protected]4d677202009-07-19 07:37:12585}
586
initial.commit09911bf2008-07-26 23:55:29587ConstrainedWindow* TabContents::CreateConstrainedDialog(
[email protected]e8382172009-06-19 22:16:28588 ConstrainedWindowDelegate* delegate) {
initial.commit09911bf2008-07-26 23:55:29589 ConstrainedWindow* window =
[email protected]e8382172009-06-19 22:16:28590 ConstrainedWindow::CreateConstrainedDialog(this, delegate);
[email protected]aed59602011-02-28 22:57:33591 AddConstrainedDialog(window);
592 return window;
593}
594
595void TabContents::AddConstrainedDialog(ConstrainedWindow* window) {
initial.commit09911bf2008-07-26 23:55:29596 child_windows_.push_back(window);
[email protected]fa1cf0b82010-01-15 21:49:44597
598 if (child_windows_.size() == 1) {
599 window->ShowConstrainedWindow();
600 BlockTabContent(true);
601 }
initial.commit09911bf2008-07-26 23:55:29602}
603
[email protected]fa1cf0b82010-01-15 21:49:44604void TabContents::BlockTabContent(bool blocked) {
[email protected]8dccd7cb2010-02-25 05:19:55605 RenderWidgetHostView* rwhv = GetRenderWidgetHostView();
[email protected]1b072562010-12-13 19:37:45606 // 70% opaque grey.
607 SkColor greyish = SkColorSetARGB(178, 0, 0, 0);
[email protected]8dccd7cb2010-02-25 05:19:55608 if (rwhv)
[email protected]1b072562010-12-13 19:37:45609 rwhv->SetVisuallyDeemphasized(blocked ? &greyish : NULL, false);
[email protected]a7eccac2011-04-15 03:05:19610 // RenderViewHost may be NULL during shutdown.
611 if (render_view_host())
612 render_view_host()->set_ignore_input_events(blocked);
[email protected]fa1cf0b82010-01-15 21:49:44613 if (delegate_)
614 delegate_->SetTabContentBlocked(this, blocked);
615}
616
[email protected]e7cfdbd2011-04-22 14:41:37617void TabContents::AddNewContents(TabContents* new_contents,
618 WindowOpenDisposition disposition,
619 const gfx::Rect& initial_pos,
620 bool user_gesture) {
initial.commit09911bf2008-07-26 23:55:29621 if (!delegate_)
622 return;
623
[email protected]e7cfdbd2011-04-22 14:41:37624 delegate_->AddNewContents(this, new_contents, disposition, initial_pos,
625 user_gesture);
[email protected]96d185d2009-04-24 03:28:54626}
627
[email protected]5c9e97a2009-09-09 23:48:30628gfx::NativeView TabContents::GetContentNativeView() const {
[email protected]96d185d2009-04-24 03:28:54629 return view_->GetContentNativeView();
630}
631
632gfx::NativeView TabContents::GetNativeView() const {
633 return view_->GetNativeView();
634}
635
636void TabContents::GetContainerBounds(gfx::Rect *out) const {
637 view_->GetContainerBounds(out);
638}
639
640void TabContents::Focus() {
641 view_->Focus();
642}
643
[email protected]90daadb42009-06-08 21:27:28644void TabContents::FocusThroughTabTraversal(bool reverse) {
[email protected]7e383692009-06-12 19:14:54645 if (showing_interstitial_page()) {
646 render_manager_.interstitial_page()->FocusThroughTabTraversal(reverse);
647 return;
648 }
[email protected]96d185d2009-04-24 03:28:54649 render_view_host()->SetInitialFocus(reverse);
650}
651
652bool TabContents::FocusLocationBarByDefault() {
[email protected]d0980792011-02-13 19:41:40653 WebUI* web_ui = GetWebUIForCurrentState();
[email protected]7ade2732011-02-10 00:13:58654 if (web_ui)
655 return web_ui->focus_location_bar_by_default();
[email protected]3e3f0eb2009-06-22 18:33:43656 NavigationEntry* entry = controller_.GetActiveEntry();
[email protected]e0d481582009-09-15 21:06:25657 if (entry && entry->url() == GURL(chrome::kAboutBlankURL))
[email protected]3e3f0eb2009-06-22 18:33:43658 return true;
[email protected]96d185d2009-04-24 03:28:54659 return false;
660}
661
[email protected]a26dc362010-04-23 01:48:58662void TabContents::SetFocusToLocationBar(bool select_all) {
[email protected]a11aaf22010-03-30 00:03:38663 if (delegate())
[email protected]a26dc362010-04-23 01:48:58664 delegate()->SetFocusToLocationBar(select_all);
[email protected]a11aaf22010-03-30 00:03:38665}
666
[email protected]d5f942ba2008-09-26 19:30:34667void TabContents::WillClose(ConstrainedWindow* window) {
[email protected]d6219912010-11-17 19:47:37668 ConstrainedWindowList::iterator i(
669 std::find(child_windows_.begin(), child_windows_.end(), window));
670 bool removed_topmost_window = i == child_windows_.begin();
671 if (i != child_windows_.end())
672 child_windows_.erase(i);
673 if (child_windows_.empty()) {
[email protected]fa1cf0b82010-01-15 21:49:44674 BlockTabContent(false);
[email protected]d6219912010-11-17 19:47:37675 } else {
676 if (removed_topmost_window)
677 child_windows_[0]->ShowConstrainedWindow();
678 BlockTabContent(true);
[email protected]fa1cf0b82010-01-15 21:49:44679 }
[email protected]66ba4932009-06-04 19:22:13680}
[email protected]d5f942ba2008-09-26 19:30:34681
[email protected]420ae012009-04-24 05:16:32682bool TabContents::IsActiveEntry(int32 page_id) {
683 NavigationEntry* active_entry = controller_.GetActiveEntry();
684 return (active_entry != NULL &&
685 active_entry->site_instance() == GetSiteInstance() &&
686 active_entry->page_id() == page_id);
687}
688
[email protected]b2fe07d12010-02-09 14:38:08689void TabContents::SetOverrideEncoding(const std::string& encoding) {
[email protected]8cb5d5b2010-02-09 11:36:16690 set_encoding(encoding);
[email protected]216813952011-05-19 22:21:26691 render_view_host()->Send(new ViewMsg_SetPageEncoding(
692 render_view_host()->routing_id(), encoding));
[email protected]8cb5d5b2010-02-09 11:36:16693}
694
[email protected]b2fe07d12010-02-09 14:38:08695void TabContents::ResetOverrideEncoding() {
[email protected]8cb5d5b2010-02-09 11:36:16696 reset_encoding();
[email protected]216813952011-05-19 22:21:26697 render_view_host()->Send(new ViewMsg_ResetPageEncodingToDefault(
698 render_view_host()->routing_id()));
[email protected]8cb5d5b2010-02-09 11:36:16699}
700
[email protected]7ab1e7d62009-10-14 23:32:01701void TabContents::OnCloseStarted() {
702 if (tab_close_start_time_.is_null())
703 tab_close_start_time_ = base::TimeTicks::Now();
704}
705
[email protected]46624bf2010-06-09 16:04:19706bool TabContents::ShouldAcceptDragAndDrop() const {
707#if defined(OS_CHROMEOS)
708 // ChromeOS panels (pop-ups) do not take drag-n-drop.
709 // See http://crosbug.com/2413
[email protected]b35b26b32011-05-05 20:35:14710 if (delegate() && delegate()->IsPopupOrPanel(this))
[email protected]b83af492010-10-09 03:21:20711 return false;
712 return true;
[email protected]46624bf2010-06-09 16:04:19713#else
714 return true;
715#endif
716}
717
[email protected]7813bd72011-02-05 02:19:34718void TabContents::SystemDragEnded() {
719 if (render_view_host())
720 render_view_host()->DragSourceSystemDragEnded();
721 if (delegate())
722 delegate()->DragEnded();
723}
724
[email protected]d0b8d092010-10-25 04:05:17725double TabContents::GetZoomLevel() const {
[email protected]b75b8292010-10-01 07:28:25726 HostZoomMap* zoom_map = profile()->GetHostZoomMap();
727 if (!zoom_map)
[email protected]d0b8d092010-10-25 04:05:17728 return 0;
[email protected]b75b8292010-10-01 07:28:25729
730 double zoom_level;
731 if (temporary_zoom_settings_) {
732 zoom_level = zoom_map->GetTemporaryZoomLevel(
733 GetRenderProcessHost()->id(), render_view_host()->routing_id());
734 } else {
[email protected]13ffa32e2011-05-27 16:37:01735 zoom_level = zoom_map->GetZoomLevel(net::GetHostOrSpecFromURL(GetURL()));
[email protected]b75b8292010-10-01 07:28:25736 }
[email protected]d0b8d092010-10-25 04:05:17737 return zoom_level;
738}
[email protected]b75b8292010-10-01 07:28:25739
[email protected]d0b8d092010-10-25 04:05:17740int TabContents::GetZoomPercent(bool* enable_increment,
741 bool* enable_decrement) {
742 *enable_decrement = *enable_increment = false;
[email protected]b75b8292010-10-01 07:28:25743 int percent = static_cast<int>(
[email protected]d0b8d092010-10-25 04:05:17744 WebKit::WebView::zoomLevelToZoomFactor(GetZoomLevel()) * 100);
[email protected]b75b8292010-10-01 07:28:25745 *enable_decrement = percent > minimum_zoom_percent_;
746 *enable_increment = percent < maximum_zoom_percent_;
747 return percent;
748}
749
[email protected]3c733bde2010-12-21 19:56:31750void TabContents::ViewSource() {
[email protected]1788e772010-12-15 16:40:50751 if (!delegate_)
752 return;
753
754 NavigationEntry* active_entry = controller().GetActiveEntry();
755 if (!active_entry)
756 return;
757
758 delegate_->ViewSourceForTab(this, active_entry->url());
[email protected]77d8d622010-12-15 10:30:12759}
760
[email protected]932b7a12011-03-09 12:50:27761void TabContents::ViewFrameSource(const GURL& url,
762 const std::string& content_state) {
763 if (!delegate_)
764 return;
765
766 delegate_->ViewSourceForFrame(this, url, content_state);
767}
768
[email protected]c40d6232011-03-25 00:16:21769void TabContents::SetContentRestrictions(int restrictions) {
770 content_restrictions_ = restrictions;
771 delegate()->ContentRestrictionsChanged(this);
772}
773
[email protected]724159a2010-12-30 01:11:18774void TabContents::OnDidStartProvisionalLoadForFrame(int64 frame_id,
775 bool is_main_frame,
[email protected]eacb080b2011-05-22 19:40:26776 bool has_opener_set,
[email protected]724159a2010-12-30 01:11:18777 const GURL& url) {
778 bool is_error_page = (url.spec() == chrome::kUnreachableWebDataURL);
779 GURL validated_url(url);
780 render_view_host()->FilterURL(ChildProcessSecurityPolicy::GetInstance(),
781 GetRenderProcessHost()->id(), &validated_url);
782
[email protected]8093a542011-05-13 07:29:32783 RenderViewHost* rvh =
784 render_manager_.pending_render_view_host() ?
785 render_manager_.pending_render_view_host() : render_view_host();
[email protected]0d60f0192011-04-14 12:40:10786 // Notify observers about the start of the provisional load.
787 FOR_EACH_OBSERVER(TabContentsObserver, observers_,
788 DidStartProvisionalLoadForFrame(frame_id, is_main_frame,
[email protected]8093a542011-05-13 07:29:32789 validated_url, is_error_page, rvh));
[email protected]0d60f0192011-04-14 12:40:10790
[email protected]724159a2010-12-30 01:11:18791 if (is_main_frame) {
[email protected]4850a7f2011-03-08 23:36:59792 // Notify observers about the provisional change in the main frame URL.
793 FOR_EACH_OBSERVER(TabContentsObserver, observers_,
[email protected]eacb080b2011-05-22 19:40:26794 ProvisionalChangeToMainFrameUrl(url, has_opener_set));
[email protected]724159a2010-12-30 01:11:18795 }
796}
797
798void TabContents::OnDidRedirectProvisionalLoad(int32 page_id,
[email protected]eacb080b2011-05-22 19:40:26799 bool has_opener_set,
[email protected]724159a2010-12-30 01:11:18800 const GURL& source_url,
801 const GURL& target_url) {
[email protected]18ba2b12011-04-06 16:35:49802 // TODO(creis): Remove this method and have the pre-rendering code listen to
803 // the ResourceDispatcherHost's RESOURCE_RECEIVED_REDIRECT notification
804 // instead. See http://crbug.com/78512.
[email protected]724159a2010-12-30 01:11:18805 NavigationEntry* entry;
806 if (page_id == -1)
807 entry = controller_.pending_entry();
808 else
809 entry = controller_.GetEntryWithPageID(GetSiteInstance(), page_id);
810 if (!entry || entry->url() != source_url)
811 return;
[email protected]e7d50892011-01-19 21:47:38812
[email protected]4850a7f2011-03-08 23:36:59813 // Notify observers about the provisional change in the main frame URL.
814 FOR_EACH_OBSERVER(TabContentsObserver, observers_,
[email protected]eacb080b2011-05-22 19:40:26815 ProvisionalChangeToMainFrameUrl(target_url,
816 has_opener_set));
[email protected]724159a2010-12-30 01:11:18817}
818
819void TabContents::OnDidFailProvisionalLoadWithError(
820 int64 frame_id,
821 bool is_main_frame,
822 int error_code,
823 const GURL& url,
824 bool showing_repost_interstitial) {
825 VLOG(1) << "Failed Provisional Load: " << url.possibly_invalid_spec()
826 << ", error_code: " << error_code
827 << " is_main_frame: " << is_main_frame
828 << " showing_repost_interstitial: " << showing_repost_interstitial
829 << " frame_id: " << frame_id;
830 GURL validated_url(url);
831 render_view_host()->FilterURL(ChildProcessSecurityPolicy::GetInstance(),
832 GetRenderProcessHost()->id(), &validated_url);
833
834 if (net::ERR_ABORTED == error_code) {
835 // EVIL HACK ALERT! Ignore failed loads when we're showing interstitials.
836 // This means that the interstitial won't be torn down properly, which is
837 // bad. But if we have an interstitial, go back to another tab type, and
838 // then load the same interstitial again, we could end up getting the first
839 // interstitial's "failed" message (as a result of the cancel) when we're on
840 // the second one.
841 //
842 // We can't tell this apart, so we think we're tearing down the current page
843 // which will cause a crash later one. There is also some code in
844 // RenderViewHostManager::RendererAbortedProvisionalLoad that is commented
845 // out because of this problem.
846 //
847 // http://code.google.com/p/chromium/issues/detail?id=2855
848 // Because this will not tear down the interstitial properly, if "back" is
849 // back to another tab type, the interstitial will still be somewhat alive
850 // in the previous tab type. If you navigate somewhere that activates the
851 // tab with the interstitial again, you'll see a flash before the new load
852 // commits of the interstitial page.
853 if (showing_interstitial_page()) {
854 LOG(WARNING) << "Discarding message during interstitial.";
855 return;
856 }
857
858 // This will discard our pending entry if we cancelled the load (e.g., if we
859 // decided to download the file instead of load it). Only discard the
860 // pending entry if the URLs match, otherwise the user initiated a navigate
861 // before the page loaded so that the discard would discard the wrong entry.
862 NavigationEntry* pending_entry = controller_.pending_entry();
863 if (pending_entry && pending_entry->url() == validated_url) {
[email protected]c95fa8b2011-04-28 20:26:16864 DidCancelLoading();
[email protected]724159a2010-12-30 01:11:18865 }
866
867 render_manager_.RendererAbortedProvisionalLoad(render_view_host());
868 }
869
870 // Send out a notification that we failed a provisional load with an error.
871 ProvisionalLoadDetails details(
872 is_main_frame, controller_.IsURLInPageNavigation(validated_url),
[email protected]b9e8ea62011-03-04 06:29:09873 validated_url, std::string(), false, frame_id);
[email protected]724159a2010-12-30 01:11:18874 details.set_error_code(error_code);
875
876 NotificationService::current()->Notify(
877 NotificationType::FAIL_PROVISIONAL_LOAD_WITH_ERROR,
878 Source<NavigationController>(&controller_),
879 Details<ProvisionalLoadDetails>(&details));
[email protected]0d60f0192011-04-14 12:40:10880
881 FOR_EACH_OBSERVER(TabContentsObserver, observers_,
882 DidFailProvisionalLoad(frame_id, is_main_frame,
883 validated_url, error_code));
[email protected]724159a2010-12-30 01:11:18884}
885
886void TabContents::OnDidLoadResourceFromMemoryCache(
887 const GURL& url,
[email protected]724159a2010-12-30 01:11:18888 const std::string& security_info) {
[email protected]28620862011-03-22 23:07:19889 base::StatsCounter cache("WebKit.CacheHit");
[email protected]724159a2010-12-30 01:11:18890 cache.Increment();
891
892 // Send out a notification that we loaded a resource from our memory cache.
893 int cert_id = 0, cert_status = 0, security_bits = -1, connection_status = 0;
894 SSLManager::DeserializeSecurityInfo(security_info,
895 &cert_id, &cert_status,
896 &security_bits,
897 &connection_status);
[email protected]7a8c55e2011-02-15 08:21:16898 LoadFromMemoryCacheDetails details(url, GetRenderProcessHost()->id(),
899 cert_id, cert_status);
[email protected]724159a2010-12-30 01:11:18900
901 NotificationService::current()->Notify(
902 NotificationType::LOAD_FROM_MEMORY_CACHE,
903 Source<NavigationController>(&controller_),
904 Details<LoadFromMemoryCacheDetails>(&details));
905}
906
907void TabContents::OnDidDisplayInsecureContent() {
[email protected]221a5d92011-04-28 18:23:16908 UserMetrics::RecordAction(UserMetricsAction("SSL.DisplayedInsecureContent"));
[email protected]724159a2010-12-30 01:11:18909 displayed_insecure_content_ = true;
910 SSLManager::NotifySSLInternalStateChanged();
911}
912
913void TabContents::OnDidRunInsecureContent(
[email protected]92771112011-01-20 00:13:02914 const std::string& security_origin, const GURL& target_url) {
[email protected]9941cf52011-02-08 16:17:23915 LOG(INFO) << security_origin << " ran insecure content from "
916 << target_url.possibly_invalid_spec();
[email protected]221a5d92011-04-28 18:23:16917 UserMetrics::RecordAction(UserMetricsAction("SSL.RanInsecureContent"));
[email protected]724159a2010-12-30 01:11:18918 controller_.ssl_manager()->DidRunInsecureContent(security_origin);
[email protected]f2b58c4d2011-06-01 23:29:41919 displayed_insecure_content_ = true;
920 SSLManager::NotifySSLInternalStateChanged();
[email protected]724159a2010-12-30 01:11:18921}
922
923void TabContents::OnDocumentLoadedInFrame(int64 frame_id) {
924 controller_.DocumentLoadedInFrame();
[email protected]0d60f0192011-04-14 12:40:10925 FOR_EACH_OBSERVER(TabContentsObserver, observers_,
926 DocumentLoadedInFrame(frame_id));
[email protected]724159a2010-12-30 01:11:18927}
928
929void TabContents::OnDidFinishLoad(int64 frame_id) {
[email protected]0d60f0192011-04-14 12:40:10930 FOR_EACH_OBSERVER(TabContentsObserver, observers_,
931 DidFinishLoad(frame_id));
[email protected]724159a2010-12-30 01:11:18932}
933
[email protected]c8f73ab2011-01-22 00:05:17934void TabContents::OnUpdateContentRestrictions(int restrictions) {
[email protected]c40d6232011-03-25 00:16:21935 SetContentRestrictions(restrictions);
[email protected]c8f73ab2011-01-22 00:05:17936}
937
[email protected]216813952011-05-19 22:21:26938void TabContents::OnGoToEntryAtOffset(int offset) {
939 if (!delegate_ || delegate_->OnGoToEntryOffset(offset)) {
940 NavigationEntry* entry = controller_.GetEntryAtOffset(offset);
941 if (!entry)
942 return;
943 // Note that we don't call NavigationController::GotToOffset() as we don't
944 // want to create a pending navigation entry (it might end up lingering
945 // http://crbug.com/51680).
946 entry->set_transition_type(entry->transition_type() |
947 PageTransition::FORWARD_BACK);
948 NavigateToEntry(*entry, NavigationController::NO_RELOAD);
949 }
950}
951
952void TabContents::OnUpdateZoomLimits(int minimum_percent,
953 int maximum_percent,
954 bool remember) {
955 minimum_zoom_percent_ = minimum_percent;
956 maximum_zoom_percent_ = maximum_percent;
957 temporary_zoom_settings_ = !remember;
958}
959
960void TabContents::OnFocusedNodeChanged(bool is_editable_node) {
961 NotificationService::current()->Notify(
962 NotificationType::FOCUS_CHANGED_IN_PAGE,
963 Source<TabContents>(this),
964 Details<const bool>(&is_editable_node));
965}
966
[email protected]96d185d2009-04-24 03:28:54967// Notifies the RenderWidgetHost instance about the fact that the page is
968// loading, or done loading and calls the base implementation.
969void TabContents::SetIsLoading(bool is_loading,
970 LoadNotificationDetails* details) {
971 if (is_loading == is_loading_)
972 return;
973
974 if (!is_loading) {
975 load_state_ = net::LOAD_STATE_IDLE;
976 load_state_host_.clear();
[email protected]094e5b22009-09-25 04:23:56977 upload_size_ = 0;
978 upload_position_ = 0;
[email protected]96d185d2009-04-24 03:28:54979 }
980
981 render_manager_.SetIsLoading(is_loading);
982
983 is_loading_ = is_loading;
984 waiting_for_response_ = is_loading;
985
[email protected]6ebdc9b2010-09-27 16:55:57986 if (delegate_)
987 delegate_->LoadingStateChanged(this);
[email protected]329581b2009-04-28 06:52:35988 NotifyNavigationStateChanged(INVALIDATE_LOAD);
[email protected]96d185d2009-04-24 03:28:54989
990 NotificationType type = is_loading ? NotificationType::LOAD_START :
991 NotificationType::LOAD_STOP;
[email protected]ce5c4502009-05-06 16:46:11992 NotificationDetails det = NotificationService::NoDetails();
[email protected]96d185d2009-04-24 03:28:54993 if (details)
994 det = Details<LoadNotificationDetails>(details);
995 NotificationService::current()->Notify(type,
996 Source<NavigationController>(&controller_),
997 det);
998}
999
[email protected]d0980792011-02-13 19:41:401000WebUI* TabContents::GetWebUIForCurrentState() {
[email protected]7ade2732011-02-10 00:13:581001 // When there is a pending navigation entry, we want to use the pending WebUI
[email protected]96d185d2009-04-24 03:28:541002 // that goes along with it to control the basic flags. For example, we want to
1003 // show the pending URL in the URL bar, so we want the display_url flag to
1004 // be from the pending entry.
1005 //
1006 // The confusion comes because there are multiple possibilities for the
1007 // initial load in a tab as a side effect of the way the RenderViewHostManager
1008 // works.
1009 //
[email protected]e0112912011-02-02 22:54:351010 // - For the very first tab the load looks "normal". The new tab Web UI is
[email protected]96d185d2009-04-24 03:28:541011 // the pending one, and we want it to apply here.
1012 //
1013 // - For subsequent new tabs, they'll get a new SiteInstance which will then
1014 // get switched to the one previously associated with the new tab pages.
[email protected]7ade2732011-02-10 00:13:581015 // This switching will cause the manager to commit the RVH/WebUI. So we'll
[email protected]e0112912011-02-02 22:54:351016 // have a committed Web UI in this case.
[email protected]96d185d2009-04-24 03:28:541017 //
1018 // This condition handles all of these cases:
1019 //
1020 // - First load in first tab: no committed nav entry + pending nav entry +
1021 // pending dom ui:
[email protected]e0112912011-02-02 22:54:351022 // -> Use pending Web UI if any.
[email protected]96d185d2009-04-24 03:28:541023 //
1024 // - First load in second tab: no committed nav entry + pending nav entry +
[email protected]e0112912011-02-02 22:54:351025 // no pending Web UI:
1026 // -> Use the committed Web UI if any.
[email protected]96d185d2009-04-24 03:28:541027 //
1028 // - Second navigation in any tab: committed nav entry + pending nav entry:
[email protected]e0112912011-02-02 22:54:351029 // -> Use pending Web UI if any.
[email protected]96d185d2009-04-24 03:28:541030 //
1031 // - Normal state with no load: committed nav entry + no pending nav entry:
[email protected]e0112912011-02-02 22:54:351032 // -> Use committed Web UI.
[email protected]96d185d2009-04-24 03:28:541033 if (controller_.pending_entry() &&
1034 (controller_.GetLastCommittedEntry() ||
[email protected]7ade2732011-02-10 00:13:581035 render_manager_.pending_web_ui()))
1036 return render_manager_.pending_web_ui();
1037 return render_manager_.web_ui();
[email protected]96d185d2009-04-24 03:28:541038}
[email protected]420ae012009-04-24 05:16:321039
[email protected]1fd1a502011-03-30 16:55:561040WebUI::TypeID TabContents::GetWebUITypeForCurrentState() {
1041 return content::WebUIFactory::Get()->GetWebUIType(profile(), GetURL());
1042}
1043
[email protected]420ae012009-04-24 05:16:321044void TabContents::DidNavigateMainFramePostCommit(
[email protected]8286f51a2011-05-31 17:39:131045 const content::LoadCommittedDetails& details,
[email protected]420ae012009-04-24 05:16:321046 const ViewHostMsg_FrameNavigate_Params& params) {
[email protected]1fd1a502011-03-30 16:55:561047 if (opener_web_ui_type_ != WebUI::kNoWebUI) {
[email protected]80a8fad2011-01-29 04:02:381048 // If this is a window.open navigation, use the same WebUI as the renderer
[email protected]c2e74fe82009-09-03 17:57:441049 // that opened the window, as long as both renderers have the same
1050 // privileges.
[email protected]1fd1a502011-03-30 16:55:561051 if (delegate_ && opener_web_ui_type_ == GetWebUITypeForCurrentState()) {
1052 WebUI* web_ui = content::GetContentClient()->browser()->
1053 GetWebUIFactory()->CreateWebUIForURL(this, GetURL());
[email protected]7ade2732011-02-10 00:13:581054 // web_ui might be NULL if the URL refers to a non-existent extension.
1055 if (web_ui) {
[email protected]d0980792011-02-13 19:41:401056 render_manager_.SetWebUIPostCommit(web_ui);
[email protected]7ade2732011-02-10 00:13:581057 web_ui->RenderViewCreated(render_view_host());
[email protected]c2e74fe82009-09-03 17:57:441058 }
1059 }
[email protected]1fd1a502011-03-30 16:55:561060 opener_web_ui_type_ = WebUI::kNoWebUI;
[email protected]c2e74fe82009-09-03 17:57:441061 }
1062
[email protected]420ae012009-04-24 05:16:321063 if (details.is_user_initiated_main_frame_load()) {
1064 // Clear the status bubble. This is a workaround for a bug where WebKit
1065 // doesn't let us know that the cursor left an element during a
1066 // transition (this is also why the mouse cursor remains as a hand after
1067 // clicking on a link); see bugs 1184641 and 980803. We don't want to
1068 // clear the bubble when a user navigates to a named anchor in the same
1069 // page.
1070 UpdateTargetURL(details.entry->page_id(), GURL());
[email protected]420ae012009-04-24 05:16:321071 }
1072
[email protected]a6e82fc2010-02-24 22:28:141073 if (!details.is_in_page) {
[email protected]f17a0ee2010-05-17 17:38:471074 // Once the main frame is navigated, we're no longer considered to have
1075 // displayed insecure content.
1076 displayed_insecure_content_ = false;
[email protected]aece2c7f2009-08-27 20:43:171077 }
[email protected]ce5c4502009-05-06 16:46:111078
[email protected]8cc8d492010-02-02 10:40:491079 // Close constrained windows if necessary.
1080 if (!net::RegistryControlledDomainService::SameDomainOrHost(
1081 details.previous_url, details.entry->url()))
1082 CloseConstrainedWindows();
1083
[email protected]3c9e1872010-11-18 16:17:491084 // Notify observers about navigation.
[email protected]585b30362011-01-28 02:30:171085 FOR_EACH_OBSERVER(TabContentsObserver, observers_,
[email protected]3c9e1872010-11-18 16:17:491086 DidNavigateMainFramePostCommit(details, params));
[email protected]420ae012009-04-24 05:16:321087}
1088
1089void TabContents::DidNavigateAnyFramePostCommit(
1090 RenderViewHost* render_view_host,
[email protected]8286f51a2011-05-31 17:39:131091 const content::LoadCommittedDetails& details,
[email protected]420ae012009-04-24 05:16:321092 const ViewHostMsg_FrameNavigate_Params& params) {
[email protected]3ab9cb82011-06-03 18:02:071093 // If we navigate, reset JavaScript state. This does nothing to prevent
[email protected]420ae012009-04-24 05:16:321094 // a malicious script from spamming messages, since the script could just
1095 // reload the page to stop blocking.
[email protected]3ab9cb82011-06-03 18:02:071096 if (delegate_)
1097 delegate_->GetJavaScriptDialogCreator()->ResetJavaScriptState(this);
[email protected]420ae012009-04-24 05:16:321098
[email protected]3c9e1872010-11-18 16:17:491099 // Notify observers about navigation.
[email protected]585b30362011-01-28 02:30:171100 FOR_EACH_OBSERVER(TabContentsObserver, observers_,
[email protected]3c9e1872010-11-18 16:17:491101 DidNavigateAnyFramePostCommit(details, params));
[email protected]420ae012009-04-24 05:16:321102}
1103
[email protected]8cc8d492010-02-02 10:40:491104void TabContents::CloseConstrainedWindows() {
1105 // Clear out any constrained windows since we are leaving this page entirely.
[email protected]aed59602011-02-28 22:57:331106 // To ensure that we iterate over every element in child_windows_ we
1107 // need to use a copy of child_windows_. Otherwise if
1108 // window->CloseConstrainedWindow() modifies child_windows_ we could end up
1109 // skipping some elements.
1110 ConstrainedWindowList child_windows_copy(child_windows_);
1111 for (ConstrainedWindowList::iterator it = child_windows_copy.begin();
1112 it != child_windows_copy.end(); ++it) {
1113 ConstrainedWindow* window = *it;
[email protected]fa1cf0b82010-01-15 21:49:441114 if (window) {
[email protected]420ae012009-04-24 05:16:321115 window->CloseConstrainedWindow();
[email protected]fa1cf0b82010-01-15 21:49:441116 BlockTabContent(false);
1117 }
[email protected]420ae012009-04-24 05:16:321118 }
1119}
1120
[email protected]420ae012009-04-24 05:16:321121void TabContents::UpdateMaxPageIDIfNecessary(SiteInstance* site_instance,
1122 RenderViewHost* rvh) {
1123 // If we are creating a RVH for a restored controller, then we might
1124 // have more page IDs than the SiteInstance's current max page ID. We must
1125 // make sure that the max page ID is larger than any restored page ID.
1126 // Note that it is ok for conflicting page IDs to exist in another tab
1127 // (i.e., NavigationController), but if any page ID is larger than the max,
1128 // the back/forward list will get confused.
1129 int max_restored_page_id = controller_.max_restored_page_id();
1130 if (max_restored_page_id > 0) {
1131 int curr_max_page_id = site_instance->max_page_id();
1132 if (max_restored_page_id > curr_max_page_id) {
1133 // Need to update the site instance immediately.
1134 site_instance->UpdateMaxPageID(max_restored_page_id);
1135
1136 // Also tell the renderer to update its internal representation. We
1137 // need to reserve enough IDs to make all restored page IDs less than
1138 // the max.
1139 if (curr_max_page_id < 0)
1140 curr_max_page_id = 0;
[email protected]216813952011-05-19 22:21:261141 rvh->Send(new ViewMsg_ReservePageIDRange(
1142 rvh->routing_id(), max_restored_page_id - curr_max_page_id));
[email protected]420ae012009-04-24 05:16:321143 }
1144 }
1145}
1146
[email protected]6b2f7a82011-04-25 19:30:511147bool TabContents::UpdateTitleForEntry(NavigationEntry* entry,
1148 const std::wstring& title) {
[email protected]420ae012009-04-24 05:16:321149 // For file URLs without a title, use the pathname instead. In the case of a
1150 // synthesized title, we don't want the update to count toward the "one set
1151 // per page of the title to history."
[email protected]6b2f7a82011-04-25 19:30:511152 string16 final_title;
[email protected]420ae012009-04-24 05:16:321153 bool explicit_set;
[email protected]987fc3a2011-05-26 14:18:091154 if (entry && entry->url().SchemeIsFile() && title.empty()) {
[email protected]6b2f7a82011-04-25 19:30:511155 final_title = UTF8ToUTF16(entry->url().ExtractFileName());
[email protected]420ae012009-04-24 05:16:321156 explicit_set = false; // Don't count synthetic titles toward the set limit.
1157 } else {
[email protected]6b2f7a82011-04-25 19:30:511158 TrimWhitespace(WideToUTF16Hack(title), TRIM_ALL, &final_title);
[email protected]420ae012009-04-24 05:16:321159 explicit_set = true;
1160 }
1161
[email protected]987fc3a2011-05-26 14:18:091162 // If a page is created via window.open and never navigated,
1163 // there will be no navigation entry. In this situation,
1164 // |page_title_when_no_navigaiton_entry_| will be used for page title.
1165 if (entry) {
1166 if (final_title == entry->title())
1167 return false; // Nothing changed, don't bother.
[email protected]420ae012009-04-24 05:16:321168
[email protected]987fc3a2011-05-26 14:18:091169 entry->set_title(final_title);
1170 } else {
1171 if (page_title_when_no_navigation_entry_ == final_title)
1172 return false; // Nothing changed, don't bother.
1173
1174 page_title_when_no_navigation_entry_ = final_title;
1175 }
[email protected]420ae012009-04-24 05:16:321176
[email protected]420ae012009-04-24 05:16:321177 // Lastly, set the title for the view.
[email protected]6b2f7a82011-04-25 19:30:511178 view_->SetPageTitle(UTF16ToWideHack(final_title));
[email protected]420ae012009-04-24 05:16:321179
[email protected]105bb0f2011-05-24 17:12:141180 TitleUpdatedDetails details(entry, explicit_set);
1181
[email protected]cbc0e1b2010-04-12 18:33:041182 NotificationService::current()->Notify(
1183 NotificationType::TAB_CONTENTS_TITLE_UPDATED,
1184 Source<TabContents>(this),
[email protected]105bb0f2011-05-24 17:12:141185 Details<TitleUpdatedDetails>(&details));
[email protected]cbc0e1b2010-04-12 18:33:041186
[email protected]420ae012009-04-24 05:16:321187 return true;
1188}
1189
1190void TabContents::NotifySwapped() {
1191 // After sending out a swap notification, we need to send a disconnect
1192 // notification so that clients that pick up a pointer to |this| can NULL the
1193 // pointer. See Bug 1230284.
1194 notify_disconnection_ = true;
1195 NotificationService::current()->Notify(
[email protected]57c6a652009-05-04 07:58:341196 NotificationType::TAB_CONTENTS_SWAPPED,
[email protected]d82ed61e2009-06-16 02:46:221197 Source<TabContents>(this),
[email protected]420ae012009-04-24 05:16:321198 NotificationService::NoDetails());
1199}
1200
1201void TabContents::NotifyConnected() {
1202 notify_disconnection_ = true;
1203 NotificationService::current()->Notify(
[email protected]57c6a652009-05-04 07:58:341204 NotificationType::TAB_CONTENTS_CONNECTED,
[email protected]d82ed61e2009-06-16 02:46:221205 Source<TabContents>(this),
[email protected]420ae012009-04-24 05:16:321206 NotificationService::NoDetails());
1207}
1208
1209void TabContents::NotifyDisconnected() {
1210 if (!notify_disconnection_)
1211 return;
1212
1213 notify_disconnection_ = false;
1214 NotificationService::current()->Notify(
[email protected]57c6a652009-05-04 07:58:341215 NotificationType::TAB_CONTENTS_DISCONNECTED,
[email protected]d82ed61e2009-06-16 02:46:221216 Source<TabContents>(this),
[email protected]420ae012009-04-24 05:16:321217 NotificationService::NoDetails());
1218}
1219
[email protected]8d3347f2009-07-09 22:00:211220RenderViewHostDelegate::View* TabContents::GetViewDelegate() {
[email protected]420ae012009-04-24 05:16:321221 return view_.get();
1222}
1223
[email protected]8d3347f2009-07-09 22:00:211224RenderViewHostDelegate::RendererManagement*
1225TabContents::GetRendererManagementDelegate() {
1226 return &render_manager_;
1227}
1228
[email protected]ced90ae12010-02-20 02:06:161229RenderViewHostDelegate::BookmarkDrag* TabContents::GetBookmarkDragDelegate() {
1230 return bookmark_drag_;
1231}
1232
1233void TabContents::SetBookmarkDragDelegate(
1234 RenderViewHostDelegate::BookmarkDrag* bookmark_drag) {
1235 bookmark_drag_ = bookmark_drag;
1236}
1237
[email protected]93623c5d2009-12-10 21:40:321238RendererPreferences TabContents::GetRendererPrefs(Profile* profile) const {
[email protected]840b1512009-07-21 16:53:461239 return renderer_preferences_;
[email protected]80d96fa2009-06-10 22:34:511240}
1241
[email protected]57c6a652009-05-04 07:58:341242TabContents* TabContents::GetAsTabContents() {
1243 return this;
1244}
1245
[email protected]7b291f92009-08-14 05:43:531246ViewType::Type TabContents::GetRenderViewType() const {
1247 return ViewType::TAB_CONTENTS;
1248}
1249
1250int TabContents::GetBrowserWindowID() const {
1251 return controller().window_id().id();
1252}
1253
[email protected]420ae012009-04-24 05:16:321254void TabContents::RenderViewCreated(RenderViewHost* render_view_host) {
[email protected]2e4633c2009-07-09 16:58:061255 NotificationService::current()->Notify(
1256 NotificationType::RENDER_VIEW_HOST_CREATED_FOR_TAB,
1257 Source<TabContents>(this),
1258 Details<RenderViewHost>(render_view_host));
[email protected]420ae012009-04-24 05:16:321259 NavigationEntry* entry = controller_.GetActiveEntry();
1260 if (!entry)
1261 return;
1262
1263 // When we're creating views, we're still doing initial setup, so we always
[email protected]e0112912011-02-02 22:54:351264 // use the pending Web UI rather than any possibly existing committed one.
[email protected]1fd1a502011-03-30 16:55:561265 if (render_manager_.pending_web_ui())
[email protected]7ade2732011-02-10 00:13:581266 render_manager_.pending_web_ui()->RenderViewCreated(render_view_host);
[email protected]420ae012009-04-24 05:16:321267
1268 if (entry->IsViewSourceMode()) {
1269 // Put the renderer in view source mode.
1270 render_view_host->Send(
1271 new ViewMsg_EnableViewSourceMode(render_view_host->routing_id()));
1272 }
[email protected]0666aef2009-05-13 19:48:081273
1274 view()->RenderViewCreated(render_view_host);
[email protected]11f764bb2011-05-25 19:45:261275
1276 FOR_EACH_OBSERVER(
1277 TabContentsObserver, observers_, RenderViewCreated(render_view_host));
[email protected]420ae012009-04-24 05:16:321278}
1279
1280void TabContents::RenderViewReady(RenderViewHost* rvh) {
1281 if (rvh != render_view_host()) {
1282 // Don't notify the world, since this came from a renderer in the
1283 // background.
1284 return;
1285 }
1286
1287 NotifyConnected();
[email protected]9d8a4642009-07-29 17:25:301288 bool was_crashed = is_crashed();
[email protected]443b80e2010-12-14 00:42:231289 SetIsCrashed(base::TERMINATION_STATUS_STILL_RUNNING, 0);
[email protected]9d8a4642009-07-29 17:25:301290
1291 // Restore the focus to the tab (otherwise the focus will be on the top
1292 // window).
[email protected]484ae5912010-09-29 19:16:141293 if (was_crashed && !FocusLocationBarByDefault() &&
1294 (!delegate_ || delegate_->ShouldFocusPageAfterCrash())) {
[email protected]9d8a4642009-07-29 17:25:301295 Focus();
[email protected]484ae5912010-09-29 19:16:141296 }
[email protected]420ae012009-04-24 05:16:321297}
1298
[email protected]443b80e2010-12-14 00:42:231299void TabContents::RenderViewGone(RenderViewHost* rvh,
1300 base::TerminationStatus status,
1301 int error_code) {
[email protected]420ae012009-04-24 05:16:321302 if (rvh != render_view_host()) {
1303 // The pending page's RenderViewHost is gone.
1304 return;
1305 }
1306
1307 SetIsLoading(false, NULL);
1308 NotifyDisconnected();
[email protected]443b80e2010-12-14 00:42:231309 SetIsCrashed(status, error_code);
[email protected]420ae012009-04-24 05:16:321310
[email protected]55452902011-06-01 21:57:471311 FOR_EACH_OBSERVER(TabContentsObserver, observers_, RenderViewGone());
[email protected]420ae012009-04-24 05:16:321312}
1313
[email protected]2e4633c2009-07-09 16:58:061314void TabContents::RenderViewDeleted(RenderViewHost* rvh) {
[email protected]fb7b79f72009-11-06 18:00:481315 render_manager_.RenderViewDeleted(rvh);
[email protected]2e4633c2009-07-09 16:58:061316}
1317
[email protected]420ae012009-04-24 05:16:321318void TabContents::DidNavigate(RenderViewHost* rvh,
1319 const ViewHostMsg_FrameNavigate_Params& params) {
[email protected]93f230e02011-06-01 14:40:001320 scoped_ptr<TabContentsDelegate::MainFrameCommitDetails> commit_details;
[email protected]8030f012009-09-25 18:09:371321
1322 if (PageTransition::IsMainFrame(params.transition)) {
[email protected]93f230e02011-06-01 14:40:001323 if (delegate())
1324 commit_details.reset(delegate()->CreateMainFrameCommitDetails(this));
[email protected]420ae012009-04-24 05:16:321325 render_manager_.DidNavigateMainFrame(rvh);
[email protected]8030f012009-09-25 18:09:371326 }
1327
[email protected]420ae012009-04-24 05:16:321328 // Update the site of the SiteInstance if it doesn't have one yet.
1329 if (!GetSiteInstance()->has_site())
1330 GetSiteInstance()->SetSite(params.url);
1331
1332 // Need to update MIME type here because it's referred to in
1333 // UpdateNavigationCommands() called by RendererDidNavigate() to
1334 // determine whether or not to enable the encoding menu.
1335 // It's updated only for the main frame. For a subframe,
1336 // RenderView::UpdateURL does not set params.contents_mime_type.
1337 // (see http://code.google.com/p/chromium/issues/detail?id=2929 )
1338 // TODO(jungshik): Add a test for the encoding menu to avoid
1339 // regressing it again.
1340 if (PageTransition::IsMainFrame(params.transition))
1341 contents_mime_type_ = params.contents_mime_type;
1342
[email protected]8286f51a2011-05-31 17:39:131343 content::LoadCommittedDetails details;
[email protected]93f230e02011-06-01 14:40:001344 bool did_navigate = controller_.RendererDidNavigate(params, &details);
[email protected]3e90d4a2009-07-03 17:38:391345
[email protected]a9c0bfe2010-09-17 08:35:221346 // Send notification about committed provisional loads. This notification is
1347 // different from the NAV_ENTRY_COMMITTED notification which doesn't include
1348 // the actual URL navigated to and isn't sent for AUTO_SUBFRAME navigations.
1349 if (details.type != NavigationType::NAV_IGNORE) {
[email protected]dabb0d12010-10-05 12:50:071350 // For AUTO_SUBFRAME navigations, an event for the main frame is generated
1351 // that is not recorded in the navigation history. For the purpose of
1352 // tracking navigation events, we treat this event as a sub frame navigation
1353 // event.
1354 bool is_main_frame = did_navigate ? details.is_main_frame : false;
[email protected]0d60f0192011-04-14 12:40:101355 PageTransition::Type transition_type = params.transition;
[email protected]a9c0bfe2010-09-17 08:35:221356 // Whether or not a page transition was triggered by going backward or
1357 // forward in the history is only stored in the navigation controller's
1358 // entry list.
1359 if (did_navigate &&
1360 (controller_.GetActiveEntry()->transition_type() &
1361 PageTransition::FORWARD_BACK)) {
[email protected]0d60f0192011-04-14 12:40:101362 transition_type = params.transition | PageTransition::FORWARD_BACK;
[email protected]a9c0bfe2010-09-17 08:35:221363 }
[email protected]0d60f0192011-04-14 12:40:101364 // Notify observers about the commit of the provisional load.
1365 FOR_EACH_OBSERVER(TabContentsObserver, observers_,
1366 DidCommitProvisionalLoadForFrame(params.frame_id,
1367 is_main_frame, params.url, transition_type));
[email protected]a9c0bfe2010-09-17 08:35:221368 }
1369
[email protected]76543b92009-08-31 17:27:451370 if (!did_navigate)
1371 return; // No navigation happened.
[email protected]420ae012009-04-24 05:16:321372
1373 // DO NOT ADD MORE STUFF TO THIS FUNCTION! Your component should either listen
1374 // for the appropriate notification (best) or you can add it to
1375 // DidNavigateMainFramePostCommit / DidNavigateAnyFramePostCommit (only if
1376 // necessary, please).
1377
1378 // Run post-commit tasks.
[email protected]93f230e02011-06-01 14:40:001379 if (details.is_main_frame) {
[email protected]420ae012009-04-24 05:16:321380 DidNavigateMainFramePostCommit(details, params);
[email protected]93f230e02011-06-01 14:40:001381 if (delegate() && commit_details.get())
1382 delegate()->DidNavigateMainFramePostCommit(this, *commit_details);
1383 }
[email protected]420ae012009-04-24 05:16:321384 DidNavigateAnyFramePostCommit(rvh, details, params);
1385}
1386
1387void TabContents::UpdateState(RenderViewHost* rvh,
1388 int32 page_id,
1389 const std::string& state) {
[email protected]992db4c2011-05-12 15:37:151390 // Ensure that this state update comes from either the active RVH or one of
1391 // the swapped out RVHs. We don't expect to hear from any other RVHs.
1392 DCHECK(rvh == render_view_host() || render_manager_.IsSwappedOut(rvh));
[email protected]420ae012009-04-24 05:16:321393
1394 // We must be prepared to handle state updates for any page, these occur
1395 // when the user is scrolling and entering form data, as well as when we're
1396 // leaving a page, in which case our state may have already been moved to
1397 // the next page. The navigation controller will look up the appropriate
1398 // NavigationEntry and update it when it is notified via the delegate.
1399
1400 int entry_index = controller_.GetEntryIndexWithPageID(
[email protected]992db4c2011-05-12 15:37:151401 rvh->site_instance(), page_id);
[email protected]420ae012009-04-24 05:16:321402 if (entry_index < 0)
1403 return;
1404 NavigationEntry* entry = controller_.GetEntryAtIndex(entry_index);
1405
1406 if (state == entry->content_state())
1407 return; // Nothing to update.
1408 entry->set_content_state(state);
1409 controller_.NotifyEntryChanged(entry, entry_index);
1410}
1411
1412void TabContents::UpdateTitle(RenderViewHost* rvh,
[email protected]6b2f7a82011-04-25 19:30:511413 int32 page_id, const std::wstring& title) {
[email protected]420ae012009-04-24 05:16:321414 // If we have a title, that's a pretty good indication that we've started
1415 // getting useful data.
1416 SetNotWaitingForResponse();
1417
1418 DCHECK(rvh == render_view_host());
[email protected]371cc8b2010-09-01 16:03:481419 NavigationEntry* entry = controller_.GetEntryWithPageID(rvh->site_instance(),
[email protected]ec0b6c42010-08-26 03:16:581420 page_id);
[email protected]987fc3a2011-05-26 14:18:091421
1422 if (!UpdateTitleForEntry(entry, title))
[email protected]420ae012009-04-24 05:16:321423 return;
1424
1425 // Broadcast notifications when the UI should be updated.
1426 if (entry == controller_.GetEntryAtOffset(0))
[email protected]f1cd5e82009-10-23 17:19:031427 NotifyNavigationStateChanged(INVALIDATE_TITLE);
[email protected]420ae012009-04-24 05:16:321428}
1429
[email protected]420ae012009-04-24 05:16:321430void TabContents::UpdateEncoding(RenderViewHost* render_view_host,
[email protected]41fc0322009-09-04 22:23:401431 const std::string& encoding) {
[email protected]420ae012009-04-24 05:16:321432 set_encoding(encoding);
1433}
1434
1435void TabContents::UpdateTargetURL(int32 page_id, const GURL& url) {
1436 if (delegate())
1437 delegate()->UpdateTargetURL(this, url);
1438}
1439
[email protected]c4e98902010-06-01 10:20:141440void TabContents::UpdateInspectorSetting(const std::string& key,
1441 const std::string& value) {
[email protected]24d27d72010-10-12 16:30:051442 RenderViewHostDelegateHelper::UpdateInspectorSetting(profile(), key, value);
[email protected]0df30122009-06-03 12:13:081443}
1444
[email protected]45aafc92010-06-07 14:18:531445void TabContents::ClearInspectorSettings() {
[email protected]24d27d72010-10-12 16:30:051446 RenderViewHostDelegateHelper::ClearInspectorSettings(profile());
[email protected]45aafc92010-06-07 14:18:531447}
1448
[email protected]420ae012009-04-24 05:16:321449void TabContents::Close(RenderViewHost* rvh) {
[email protected]07707302009-11-06 00:50:291450 // The UI may be in an event-tracking loop, such as between the
1451 // mouse-down and mouse-up in text selection or a button click.
1452 // Defer the close until after tracking is complete, so that we
1453 // don't free objects out from under the UI.
1454 // TODO(shess): This could probably be integrated with the
1455 // IsDoingDrag() test below. Punting for now because I need more
1456 // research to understand how this impacts platforms other than Mac.
1457 // TODO(shess): This could get more fine-grained. For instance,
1458 // closing a tab in another window while selecting text in the
1459 // current window's Omnibox should be just fine.
1460 if (view()->IsEventTracking()) {
1461 view()->CloseTabAfterEventTracking();
1462 return;
1463 }
1464
[email protected]24a4d1062009-07-10 23:10:421465 // If we close the tab while we're in the middle of a drag, we'll crash.
1466 // Instead, cancel the drag and close it as soon as the drag ends.
1467 if (view()->IsDoingDrag()) {
1468 view()->CancelDragAndCloseTab();
1469 return;
1470 }
1471
[email protected]420ae012009-04-24 05:16:321472 // Ignore this if it comes from a RenderViewHost that we aren't showing.
1473 if (delegate() && rvh == render_view_host())
1474 delegate()->CloseContents(this);
1475}
1476
1477void TabContents::RequestMove(const gfx::Rect& new_bounds) {
[email protected]b35b26b32011-05-05 20:35:141478 if (delegate() && delegate()->IsPopupOrPanel(this))
[email protected]420ae012009-04-24 05:16:321479 delegate()->MoveContents(this, new_bounds);
1480}
1481
[email protected]7ab1e7d62009-10-14 23:32:011482void TabContents::DidStartLoading() {
[email protected]420ae012009-04-24 05:16:321483 SetIsLoading(true, NULL);
[email protected]3c9e1872010-11-18 16:17:491484
[email protected]c40d6232011-03-25 00:16:211485 if (delegate() && content_restrictions_) {
1486 content_restrictions_ = 0;
[email protected]de4761b2010-12-07 21:05:211487 delegate()->ContentRestrictionsChanged(this);
[email protected]9e823662010-10-13 23:36:001488 }
[email protected]3c9e1872010-11-18 16:17:491489
1490 // Notify observers about navigation.
[email protected]585b30362011-01-28 02:30:171491 FOR_EACH_OBSERVER(TabContentsObserver, observers_, DidStartLoading());
[email protected]420ae012009-04-24 05:16:321492}
1493
[email protected]7ab1e7d62009-10-14 23:32:011494void TabContents::DidStopLoading() {
[email protected]420ae012009-04-24 05:16:321495 scoped_ptr<LoadNotificationDetails> details;
1496
1497 NavigationEntry* entry = controller_.GetActiveEntry();
1498 // An entry may not exist for a stop when loading an initial blank page or
1499 // if an iframe injected by script into a blank page finishes loading.
1500 if (entry) {
[email protected]420ae012009-04-24 05:16:321501 base::TimeDelta elapsed = base::TimeTicks::Now() - current_load_start_;
1502
1503 details.reset(new LoadNotificationDetails(
[email protected]ebe89e062009-08-13 23:16:541504 entry->virtual_url(),
[email protected]420ae012009-04-24 05:16:321505 entry->transition_type(),
1506 elapsed,
1507 &controller_,
1508 controller_.GetCurrentEntryIndex()));
1509 }
1510
[email protected]420ae012009-04-24 05:16:321511 SetIsLoading(false, details.get());
[email protected]3c9e1872010-11-18 16:17:491512
1513 // Notify observers about navigation.
[email protected]585b30362011-01-28 02:30:171514 FOR_EACH_OBSERVER(TabContentsObserver, observers_, DidStopLoading());
[email protected]420ae012009-04-24 05:16:321515}
1516
[email protected]c95fa8b2011-04-28 20:26:161517void TabContents::DidCancelLoading() {
1518 controller_.DiscardNonCommittedEntries();
1519
1520 // Update the URL display.
1521 NotifyNavigationStateChanged(TabContents::INVALIDATE_URL);
1522}
1523
[email protected]1a3c3cb2010-12-16 21:03:401524void TabContents::DidChangeLoadProgress(double progress) {
1525 if (delegate())
1526 delegate()->LoadProgressChanged(progress);
1527}
1528
[email protected]25497492010-09-11 15:15:081529void TabContents::DocumentOnLoadCompletedInMainFrame(
1530 RenderViewHost* render_view_host,
1531 int32 page_id) {
1532 NotificationService::current()->Notify(
1533 NotificationType::LOAD_COMPLETED_MAIN_FRAME,
1534 Source<TabContents>(this),
1535 Details<int>(&page_id));
1536}
1537
[email protected]420ae012009-04-24 05:16:321538void TabContents::RequestOpenURL(const GURL& url, const GURL& referrer,
1539 WindowOpenDisposition disposition) {
[email protected]7ade2732011-02-10 00:13:581540 if (render_manager_.web_ui()) {
[email protected]e0112912011-02-02 22:54:351541 // When we're a Web UI, it will provide a page transition type for us (this
[email protected]420ae012009-04-24 05:16:321542 // is so the new tab page can specify AUTO_BOOKMARK for automatically
1543 // generated suggestions).
1544 //
[email protected]e0112912011-02-02 22:54:351545 // Note also that we hide the referrer for Web UI pages. We don't really
[email protected]60e448982009-05-06 04:21:161546 // want web sites to see a referrer of "chrome://blah" (and some
1547 // chrome: URLs might have search terms or other stuff we don't want to
[email protected]420ae012009-04-24 05:16:321548 // send to the site), so we send no referrer.
1549 OpenURL(url, GURL(), disposition,
[email protected]7ade2732011-02-10 00:13:581550 render_manager_.web_ui()->link_transition_type());
[email protected]420ae012009-04-24 05:16:321551 } else {
1552 OpenURL(url, referrer, disposition, PageTransition::LINK);
1553 }
1554}
1555
[email protected]420ae012009-04-24 05:16:321556void TabContents::RunJavaScriptMessage(
[email protected]992db4c2011-05-12 15:37:151557 const RenderViewHost* rvh,
[email protected]4f5ce842011-05-27 19:34:411558 const string16& message,
1559 const string16& default_prompt,
[email protected]420ae012009-04-24 05:16:321560 const GURL& frame_url,
1561 const int flags,
1562 IPC::Message* reply_msg,
1563 bool* did_suppress_message) {
[email protected]3ab9cb82011-06-03 18:02:071564 // Suppress JavaScript dialogs when requested. Also suppress messages when
1565 // showing an interstitial as it's shown over the previous page and we don't
1566 // want the hidden page's dialogs to interfere with the interstitial.
[email protected]8f55e802010-12-06 18:11:501567 bool suppress_this_message =
[email protected]992db4c2011-05-12 15:37:151568 rvh->is_swapped_out() ||
[email protected]8f55e802010-12-06 18:11:501569 showing_interstitial_page() ||
[email protected]3ab9cb82011-06-03 18:02:071570 !delegate_ ||
1571 delegate_->ShouldSuppressDialogs();
[email protected]420ae012009-04-24 05:16:321572
1573 if (!suppress_this_message) {
[email protected]3ab9cb82011-06-03 18:02:071574 delegate_->GetJavaScriptDialogCreator()->RunJavaScriptDialog(
1575 this,
1576 frame_url,
1577 flags,
1578 message,
1579 default_prompt,
1580 reply_msg,
1581 &suppress_this_message,
1582 profile());
[email protected]420ae012009-04-24 05:16:321583 }
[email protected]3ab9cb82011-06-03 18:02:071584
1585 if (suppress_this_message) {
1586 // If we are suppressing messages, just reply as if the user immediately
1587 // pressed "Cancel".
1588 OnDialogClosed(reply_msg, false, string16());
1589 }
1590
1591 *did_suppress_message = suppress_this_message;
[email protected]420ae012009-04-24 05:16:321592}
1593
[email protected]992db4c2011-05-12 15:37:151594void TabContents::RunBeforeUnloadConfirm(const RenderViewHost* rvh,
[email protected]4f5ce842011-05-27 19:34:411595 const string16& message,
[email protected]420ae012009-04-24 05:16:321596 IPC::Message* reply_msg) {
[email protected]5aab5e22010-12-08 22:13:291597 if (delegate())
1598 delegate()->WillRunBeforeUnloadConfirm();
[email protected]3ab9cb82011-06-03 18:02:071599
1600 bool suppress_this_message =
1601 rvh->is_swapped_out() ||
1602 !delegate_ ||
1603 delegate_->ShouldSuppressDialogs();
[email protected]992db4c2011-05-12 15:37:151604 if (suppress_this_message) {
[email protected]4f5ce842011-05-27 19:34:411605 render_view_host()->JavaScriptDialogClosed(reply_msg, true, string16());
[email protected]8f55e802010-12-06 18:11:501606 return;
1607 }
[email protected]3ab9cb82011-06-03 18:02:071608
[email protected]7ab1e7d62009-10-14 23:32:011609 is_showing_before_unload_dialog_ = true;
[email protected]3ab9cb82011-06-03 18:02:071610 delegate_->GetJavaScriptDialogCreator()->RunBeforeUnloadDialog(
1611 this,
1612 message,
1613 reply_msg);
[email protected]420ae012009-04-24 05:16:321614}
1615
[email protected]420ae012009-04-24 05:16:321616WebPreferences TabContents::GetWebkitPrefs() {
[email protected]6c32ce72010-03-08 05:18:061617 Profile* profile = render_view_host()->process()->profile();
[email protected]7ade2732011-02-10 00:13:581618 bool is_web_ui = false;
[email protected]447021c2010-09-08 21:29:081619 WebPreferences web_prefs =
[email protected]7ade2732011-02-10 00:13:581620 RenderViewHostDelegateHelper::GetWebkitPrefs(profile, is_web_ui);
[email protected]447021c2010-09-08 21:29:081621
[email protected]b8299c12011-06-03 19:52:281622 // Force accelerated compositing and 2d canvas off for chrome:, about: and
1623 // chrome-devtools: pages.
[email protected]27c790d42010-10-22 09:28:431624 if (GetURL().SchemeIs(chrome::kChromeDevToolsScheme) ||
[email protected]b8299c12011-06-03 19:52:281625 GetURL().SchemeIs(chrome::kChromeUIScheme) ||
1626 GetURL().SchemeIs(chrome::kAboutScheme)) {
[email protected]447021c2010-09-08 21:29:081627 web_prefs.accelerated_compositing_enabled = false;
[email protected]9beff752010-09-22 19:35:431628 web_prefs.accelerated_2d_canvas_enabled = false;
[email protected]447021c2010-09-08 21:29:081629 }
1630
[email protected]39553442010-09-09 00:01:551631#if defined(OS_MACOSX)
1632 // Disable accelerated compositing if IOSurface's are not supported,
1633 // as is the case in 10.5.
1634 if (!IOSurfaceSupport::Initialize())
1635 web_prefs.accelerated_compositing_enabled = false;
1636#endif
1637
[email protected]447021c2010-09-08 21:29:081638 return web_prefs;
[email protected]420ae012009-04-24 05:16:321639}
1640
[email protected]7d472472011-01-22 01:30:251641void TabContents::OnUserGesture() {
[email protected]ddb85052011-05-18 14:40:271642 // Notify observers.
1643 FOR_EACH_OBSERVER(TabContentsObserver, observers_, DidGetUserGesture());
[email protected]7d472472011-01-22 01:30:251644}
1645
[email protected]fa1cf0b82010-01-15 21:49:441646void TabContents::OnIgnoredUIEvent() {
1647 if (constrained_window_count()) {
1648 ConstrainedWindow* window = *constrained_window_begin();
1649 window->FocusConstrainedWindow();
1650 }
1651}
1652
[email protected]420ae012009-04-24 05:16:321653void TabContents::OnCrossSiteResponse(int new_render_process_host_id,
1654 int new_request_id) {
[email protected]57c6a652009-05-04 07:58:341655 // Allows the TabContents to react when a cross-site response is ready to be
[email protected]420ae012009-04-24 05:16:321656 // delivered to a pending RenderViewHost. We must first run the onunload
1657 // handler of the old RenderViewHost before we can allow it to proceed.
1658 render_manager_.OnCrossSiteResponse(new_render_process_host_id,
1659 new_request_id);
1660}
1661
[email protected]420ae012009-04-24 05:16:321662void TabContents::RendererUnresponsive(RenderViewHost* rvh,
1663 bool is_during_unload) {
[email protected]992db4c2011-05-12 15:37:151664 // Don't show hung renderer dialog for a swapped out RVH.
1665 if (rvh != render_view_host())
1666 return;
1667
[email protected]420ae012009-04-24 05:16:321668 if (is_during_unload) {
1669 // Hang occurred while firing the beforeunload/unload handler.
1670 // Pretend the handler fired so tab closing continues as if it had.
[email protected]829e7612009-04-25 01:15:111671 rvh->set_sudden_termination_allowed(true);
[email protected]420ae012009-04-24 05:16:321672
1673 if (!render_manager_.ShouldCloseTabOnUnresponsiveRenderer())
1674 return;
1675
1676 // If the tab hangs in the beforeunload/unload handler there's really
1677 // nothing we can do to recover. Pretend the unload listeners have
1678 // all fired and close the tab. If the hang is in the beforeunload handler
1679 // then the user will not have the option of cancelling the close.
1680 Close(rvh);
1681 return;
1682 }
1683
[email protected]55452902011-06-01 21:57:471684 if (!render_view_host() || !render_view_host()->IsRenderViewLive())
1685 return;
1686
1687 if (delegate())
1688 delegate()->RendererUnresponsive(this);
[email protected]420ae012009-04-24 05:16:321689}
1690
1691void TabContents::RendererResponsive(RenderViewHost* render_view_host) {
[email protected]55452902011-06-01 21:57:471692 if (delegate())
1693 delegate()->RendererResponsive(this);
[email protected]420ae012009-04-24 05:16:321694}
1695
1696void TabContents::LoadStateChanged(const GURL& url,
[email protected]094e5b22009-09-25 04:23:561697 net::LoadState load_state,
1698 uint64 upload_position,
1699 uint64 upload_size) {
[email protected]420ae012009-04-24 05:16:321700 load_state_ = load_state;
[email protected]094e5b22009-09-25 04:23:561701 upload_position_ = upload_position;
1702 upload_size_ = upload_size;
[email protected]04866c42011-05-03 20:03:501703 load_state_host_ = net::IDNToUnicode(url.host(),
[email protected]b5cca982011-05-26 04:42:081704 content::GetContentClient()->browser()->GetAcceptLangs(this));
[email protected]420ae012009-04-24 05:16:321705 if (load_state_ == net::LOAD_STATE_READING_RESPONSE)
1706 SetNotWaitingForResponse();
1707 if (is_loading())
[email protected]c9cd2222009-05-06 05:16:501708 NotifyNavigationStateChanged(INVALIDATE_LOAD | INVALIDATE_TAB);
[email protected]420ae012009-04-24 05:16:321709}
1710
[email protected]1ee614862009-07-06 20:29:181711bool TabContents::IsExternalTabContainer() const {
1712 if (!delegate())
1713 return false;
1714
1715 return delegate()->IsExternalTabContainer();
1716}
1717
[email protected]7d472472011-01-22 01:30:251718void TabContents::WorkerCrashed() {
[email protected]0dd3a0ab2011-02-18 08:17:441719 if (delegate())
[email protected]55452902011-06-01 21:57:471720 delegate()->WorkerCrashed(this);
[email protected]7d472472011-01-22 01:30:251721}
1722
[email protected]f364d1392011-04-08 21:03:101723void TabContents::RequestDesktopNotificationPermission(
1724 const GURL& source_origin, int callback_context) {
1725 DesktopNotificationService* service =
[email protected]dcb72d52011-04-13 12:36:531726 DesktopNotificationServiceFactory::GetForProfile(profile());
[email protected]f364d1392011-04-08 21:03:101727 service->RequestPermission(
1728 source_origin, GetRenderProcessHost()->id(),
1729 render_view_host()->routing_id(), callback_context, this);
1730}
1731
[email protected]420ae012009-04-24 05:16:321732void TabContents::BeforeUnloadFiredFromRenderManager(
1733 bool proceed,
1734 bool* proceed_to_fire_unload) {
1735 if (delegate())
1736 delegate()->BeforeUnloadFired(this, proceed, proceed_to_fire_unload);
1737}
1738
[email protected]3a3d47472010-07-15 21:03:541739void TabContents::DidStartLoadingFromRenderManager(
1740 RenderViewHost* render_view_host) {
1741 DidStartLoading();
1742}
1743
1744void TabContents::RenderViewGoneFromRenderManager(
1745 RenderViewHost* render_view_host) {
[email protected]443b80e2010-12-14 00:42:231746 DCHECK(crashed_status_ != base::TERMINATION_STATUS_STILL_RUNNING);
1747 RenderViewGone(render_view_host, crashed_status_, crashed_error_code_);
[email protected]3a3d47472010-07-15 21:03:541748}
1749
[email protected]420ae012009-04-24 05:16:321750void TabContents::UpdateRenderViewSizeForRenderManager() {
1751 // TODO(brettw) this is a hack. See TabContentsView::SizeContents.
[email protected]0323ee42010-02-17 22:03:261752 gfx::Size size = view_->GetContainerSize();
1753 // 0x0 isn't a valid window size (minimal window size is 1x1) but it may be
1754 // here during container initialization and normal window size will be set
1755 // later. In case of tab duplication this resizing to 0x0 prevents setting
1756 // normal size later so just ignore it.
1757 if (!size.IsEmpty())
1758 view_->SizeContents(size);
[email protected]420ae012009-04-24 05:16:321759}
1760
[email protected]3a3d47472010-07-15 21:03:541761void TabContents::NotifySwappedFromRenderManager() {
1762 NotifySwapped();
1763}
1764
1765NavigationController& TabContents::GetControllerForRenderManager() {
1766 return controller();
1767}
1768
[email protected]d0980792011-02-13 19:41:401769WebUI* TabContents::CreateWebUIForRenderManager(const GURL& url) {
[email protected]1fd1a502011-03-30 16:55:561770 return content::WebUIFactory::Get()->CreateWebUIForURL(this, url);
[email protected]420ae012009-04-24 05:16:321771}
1772
1773NavigationEntry*
1774TabContents::GetLastCommittedNavigationEntryForRenderManager() {
1775 return controller_.GetLastCommittedEntry();
1776}
1777
1778bool TabContents::CreateRenderViewForRenderManager(
1779 RenderViewHost* render_view_host) {
[email protected]420ae012009-04-24 05:16:321780 RenderWidgetHostView* rwh_view = view_->CreateViewForWidget(render_view_host);
[email protected]1a98a932009-11-17 00:12:521781
[email protected]420ae012009-04-24 05:16:321782 // Now that the RenderView has been created, we need to tell it its size.
1783 rwh_view->SetSize(view_->GetContainerSize());
1784
[email protected]a4127722011-04-27 23:13:521785 if (!render_view_host->CreateRenderView(string16()))
1786 return false;
1787
[email protected]f8233cc2011-05-31 20:24:501788#if defined(OS_LINUX)
1789 // Force a ViewMsg_Resize to be sent, needed to make plugins show up on
1790 // linux. See crbug.com/83941.
1791 if (RenderWidgetHost* render_widget_host = rwh_view->GetRenderWidgetHost())
1792 render_widget_host->WasResized();
1793#endif
1794
[email protected]420ae012009-04-24 05:16:321795 UpdateMaxPageIDIfNecessary(render_view_host->site_instance(),
1796 render_view_host);
1797 return true;
1798}
1799
1800void TabContents::Observe(NotificationType type,
1801 const NotificationSource& source,
1802 const NotificationDetails& details) {
1803 switch (type.value) {
[email protected]420ae012009-04-24 05:16:321804 case NotificationType::RENDER_WIDGET_HOST_DESTROYED:
1805 view_->RenderWidgetHostDestroyed(Source<RenderWidgetHost>(source).ptr());
1806 break;
[email protected]420ae012009-04-24 05:16:321807 default:
1808 NOTREACHED();
1809 }
1810}
[email protected]aacd7cc2009-09-02 14:51:101811
[email protected]3ab9cb82011-06-03 18:02:071812// Overridden from JavaScriptDialogDelegate
[email protected]beb440c2009-11-06 04:08:541813
[email protected]3ab9cb82011-06-03 18:02:071814void TabContents::OnDialogClosed(IPC::Message* reply_msg,
1815 bool success,
1816 const string16& user_input) {
[email protected]beb440c2009-11-06 04:08:541817 if (is_showing_before_unload_dialog_ && !success) {
1818 // If a beforeunload dialog is canceled, we need to stop the throbber from
1819 // spinning, since we forced it to start spinning in Navigate.
1820 DidStopLoading();
1821
1822 tab_close_start_time_ = base::TimeTicks();
1823 }
1824 is_showing_before_unload_dialog_ = false;
[email protected]4f5ce842011-05-27 19:34:411825 render_view_host()->JavaScriptDialogClosed(reply_msg,
1826 success,
[email protected]3ab9cb82011-06-03 18:02:071827 user_input);
[email protected]beb440c2009-11-06 04:08:541828}
1829
[email protected]3ab9cb82011-06-03 18:02:071830gfx::NativeWindow TabContents::GetDialogRootWindow() {
1831 return view_->GetTopLevelNativeWindow();
[email protected]beb440c2009-11-06 04:08:541832}
1833
[email protected]3a3d47472010-07-15 21:03:541834TabContents* TabContents::AsTabContents() {
1835 return this;
1836}
1837
1838ExtensionHost* TabContents::AsExtensionHost() {
1839 return NULL;
1840}
1841
[email protected]41fc0322009-09-04 22:23:401842void TabContents::set_encoding(const std::string& encoding) {
[email protected]763ec4ca2011-04-29 15:48:121843 encoding_ = content::GetContentClient()->browser()->
1844 GetCanonicalEncodingNameByAliasName(encoding);
[email protected]aacd7cc2009-09-02 14:51:101845}
[email protected]f45d2a72010-03-08 23:28:351846
[email protected]33f74972010-12-08 16:40:361847void TabContents::SwapInRenderViewHost(RenderViewHost* rvh) {
1848 render_manager_.SwapInRenderViewHost(rvh);
1849}
1850
1851void TabContents::CreateViewAndSetSizeForRVH(RenderViewHost* rvh) {
1852 RenderWidgetHostView* rwh_view = view()->CreateViewForWidget(rvh);
1853 rwh_view->SetSize(view()->GetContainerSize());
1854}
[email protected]e7d50892011-01-19 21:47:381855
[email protected]232a5812011-03-04 22:42:081856void TabContents::OnOnlineStateChanged(bool online) {
1857 render_view_host()->Send(new ViewMsg_NetworkStateChanged(
1858 render_view_host()->routing_id(), online));
1859}