blob: 1b6fe89ffa911b02baa2413e2cb4ae9c9f9d246d [file] [log] [blame]
[email protected]91854cd2012-01-10 19:43:571// Copyright (c) 2012 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]567812d2011-02-24 17:40:5016#include "content/browser/child_process_security_policy.h"
[email protected]0e12d7d2011-12-01 16:21:4417#include "content/browser/debugger/devtools_manager_impl.h"
[email protected]8bd9e562011-08-16 23:55:4618#include "content/browser/download/download_stats.h"
[email protected]567812d2011-02-24 17:40:5019#include "content/browser/host_zoom_map.h"
20#include "content/browser/in_process_webkit/session_storage_namespace.h"
[email protected]0d9989d2011-12-21 20:26:0021#include "content/browser/intents/web_intents_dispatcher_impl.h"
[email protected]37a72af2011-06-13 05:42:0122#include "content/browser/load_from_memory_cache_details.h"
[email protected]35e251d2011-05-24 21:01:0423#include "content/browser/load_notification_details.h"
[email protected]f3b1a082011-11-18 00:34:3024#include "content/browser/renderer_host/render_process_host_impl.h"
[email protected]567812d2011-02-24 17:40:5025#include "content/browser/renderer_host/render_view_host.h"
26#include "content/browser/renderer_host/render_widget_host_view.h"
[email protected]686493142011-07-15 21:47:2227#include "content/browser/renderer_host/resource_dispatcher_host.h"
[email protected]567812d2011-02-24 17:40:5028#include "content/browser/renderer_host/resource_request_details.h"
29#include "content/browser/site_instance.h"
[email protected]0dd3a0ab2011-02-18 08:17:4430#include "content/browser/tab_contents/interstitial_page.h"
[email protected]10f417c52011-12-28 21:04:2331#include "content/browser/tab_contents/navigation_entry_impl.h"
[email protected]0dd3a0ab2011-02-18 08:17:4432#include "content/browser/tab_contents/provisional_load_details.h"
[email protected]105bb0f2011-05-24 17:12:1433#include "content/browser/tab_contents/title_updated_details.h"
[email protected]d2353452012-01-19 19:53:5634#include "content/browser/webui/web_ui_impl.h"
[email protected]ce9751942011-09-21 01:57:2435#include "content/common/intents_messages.h"
[email protected]2c5569662011-03-22 20:45:0236#include "content/common/view_messages.h"
[email protected]ccb797302011-12-15 16:55:1137#include "content/public/browser/browser_context.h"
[email protected]87f3c082011-10-19 18:07:4438#include "content/public/browser/content_browser_client.h"
[email protected]0e12d7d2011-12-01 16:21:4439#include "content/public/browser/devtools_agent_host_registry.h"
[email protected]e582fdd2011-12-20 16:48:1740#include "content/public/browser/download_manager.h"
[email protected]d9083482012-01-06 00:38:4641#include "content/public/browser/invalidate_type.h"
[email protected]5b96836f2011-12-22 07:39:0042#include "content/public/browser/navigation_details.h"
[email protected]54087fe2011-10-28 22:02:4843#include "content/public/browser/notification_service.h"
[email protected]7f6f44c2011-12-14 13:23:3844#include "content/public/browser/user_metrics.h"
[email protected]674bc592011-12-20 23:00:4245#include "content/public/browser/web_contents_delegate.h"
[email protected]d8c660432011-12-22 20:51:2546#include "content/public/browser/web_contents_observer.h"
[email protected]8643e6d2012-01-18 20:26:1047#include "content/public/browser/web_contents_view.h"
[email protected]f3f3b722012-01-07 01:29:4348#include "content/public/browser/web_ui_factory.h"
[email protected]e091df82011-10-11 18:13:2149#include "content/public/common/bindings_policy.h"
[email protected]54087fe2011-10-28 22:02:4850#include "content/public/common/content_constants.h"
[email protected]4573fbd2011-10-31 20:25:1851#include "content/public/common/content_restriction.h"
[email protected]a1d29162011-10-14 17:14:0352#include "content/public/common/url_constants.h"
[email protected]d686e812009-06-03 19:10:2953#include "net/base/net_util.h"
[email protected]abe2c032011-03-31 18:49:3454#include "net/url_request/url_request_context_getter.h"
[email protected]8bd0fe62011-01-17 06:44:3755#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
[email protected]08397d52011-02-05 01:53:3856#include "ui/gfx/codec/png_codec.h"
[email protected]ce9751942011-09-21 01:57:2457#include "webkit/glue/web_intent_data.h"
[email protected]3c733bde2010-12-21 19:56:3158#include "webkit/glue/webpreferences.h"
59
60#if defined(OS_MACOSX)
[email protected]b9b751f22011-03-25 14:04:1261#include "ui/gfx/surface/io_surface_support_mac.h"
[email protected]3c733bde2010-12-21 19:56:3162#endif // defined(OS_MACOSX)
[email protected]3e45ba92009-02-20 21:09:0063
[email protected]420ae012009-04-24 05:16:3264// Cross-Site Navigations
65//
66// If a TabContents is told to navigate to a different web site (as determined
67// by SiteInstance), it will replace its current RenderViewHost with a new
68// RenderViewHost dedicated to the new SiteInstance. This works as follows:
69//
70// - Navigate determines whether the destination is cross-site, and if so,
[email protected]a2750082011-09-01 12:29:4671// it creates a pending_render_view_host_.
[email protected]420ae012009-04-24 05:16:3272// - The pending RVH is "suspended," so that no navigation messages are sent to
73// its renderer until the onbeforeunload JavaScript handler has a chance to
74// run in the current RVH.
75// - The pending RVH tells CrossSiteRequestManager (a thread-safe singleton)
76// that it has a pending cross-site request. ResourceDispatcherHost will
77// check for this when the response arrives.
78// - The current RVH runs its onbeforeunload handler. If it returns false, we
[email protected]a2750082011-09-01 12:29:4679// cancel all the pending logic. Otherwise we allow the pending RVH to send
80// the navigation request to its renderer.
81// - ResourceDispatcherHost receives a ResourceRequest on the IO thread for the
82// main resource load on the pending RVH. It checks CrossSiteRequestManager
83// to see that it is a cross-site request, and installs a
84// CrossSiteResourceHandler.
85// - When RDH receives a response, the BufferedResourceHandler determines
86// whether it is a download. If so, it sends a message to the new renderer
87// causing it to cancel the request, and the download proceeds. For now, the
88// pending RVH remains until the next DidNavigate event for this TabContents.
89// This isn't ideal, but it doesn't affect any functionality.
[email protected]420ae012009-04-24 05:16:3290// - After RDH receives a response and determines that it is safe and not a
91// download, it pauses the response to first run the old page's onunload
92// handler. It does this by asynchronously calling the OnCrossSiteResponse
[email protected]992db4c2011-05-12 15:37:1593// method of TabContents on the UI thread, which sends a SwapOut message
[email protected]420ae012009-04-24 05:16:3294// to the current RVH.
[email protected]992db4c2011-05-12 15:37:1595// - Once the onunload handler is finished, a SwapOut_ACK message is sent to
[email protected]420ae012009-04-24 05:16:3296// the ResourceDispatcherHost, who unpauses the response. Data is then sent
97// to the pending RVH.
98// - The pending renderer sends a FrameNavigate message that invokes the
99// DidNavigate method. This replaces the current RVH with the
[email protected]a2750082011-09-01 12:29:46100// pending RVH.
[email protected]992db4c2011-05-12 15:37:15101// - The previous renderer is kept swapped out in RenderViewHostManager in case
102// the user goes back. The process only stays live if another tab is using
103// it, but if so, the existing frame relationships will be maintained.
[email protected]0e47edc2011-11-22 08:01:02104//
105// It is possible that we trigger a new navigation after we have received
106// a SwapOut_ACK message but before the FrameNavigation has been confirmed.
107// In this case the old RVH has been swapped out but the new one has not
108// replaced it, yet. Therefore, we cancel the pending RVH and skip the unloading
109// of the old RVH.
[email protected]420ae012009-04-24 05:16:32110
[email protected]0e12d7d2011-12-01 16:21:44111using content::DevToolsAgentHost;
112using content::DevToolsAgentHostRegistry;
113using content::DevToolsManagerImpl;
[email protected]e582fdd2011-12-20 16:48:17114using content::DownloadItem;
115using content::DownloadManager;
[email protected]e5d549d2011-12-28 01:29:20116using content::GlobalRequestID;
[email protected]c5eed492012-01-04 17:07:50117using content::NavigationController;
[email protected]10f417c52011-12-28 21:04:23118using content::NavigationEntry;
119using content::NavigationEntryImpl;
[email protected]e5d549d2011-12-28 01:29:20120using content::OpenURLParams;
[email protected]b0b67cf2012-01-18 21:59:57121using content::RenderViewHostDelegate;
[email protected]d583e3f22011-12-27 21:38:17122using content::SSLStatus;
[email protected]7f6f44c2011-12-14 13:23:38123using content::UserMetricsAction;
[email protected]ea049a02011-12-25 21:37:09124using content::WebContents;
[email protected]d8c660432011-12-22 20:51:25125using content::WebContentsObserver;
[email protected]d2353452012-01-19 19:53:56126using content::WebUI;
[email protected]c63cedf22012-01-17 18:42:22127using content::WebUIController;
[email protected]0e12d7d2011-12-01 16:21:44128
[email protected]420ae012009-04-24 05:16:32129namespace {
130
131// Amount of time we wait between when a key event is received and the renderer
132// is queried for its state and pushed to the NavigationEntry.
133const int kQueryStateDelay = 5000;
134
[email protected]6ebdc9b2010-09-27 16:55:57135const int kSyncWaitDelay = 40;
136
[email protected]ca406032011-07-19 21:53:05137static const char kDotGoogleDotCom[] = ".google.com";
138
[email protected]420ae012009-04-24 05:16:32139#if defined(OS_WIN)
140
141BOOL CALLBACK InvalidateWindow(HWND hwnd, LPARAM lparam) {
142 // Note: erase is required to properly paint some widgets borders. This can
143 // be seen with textfields.
144 InvalidateRect(hwnd, NULL, TRUE);
145 return TRUE;
146}
147#endif
148
[email protected]2c5569662011-03-22 20:45:02149ViewMsg_Navigate_Type::Value GetNavigationType(
[email protected]10f417c52011-12-28 21:04:23150 content::BrowserContext* browser_context, const NavigationEntryImpl& entry,
[email protected]c5eed492012-01-04 17:07:50151 NavigationController::ReloadType reload_type) {
[email protected]1ccb3568d2010-02-19 10:51:16152 switch (reload_type) {
[email protected]d202a7c2012-01-04 07:53:47153 case NavigationControllerImpl::RELOAD:
[email protected]2c5569662011-03-22 20:45:02154 return ViewMsg_Navigate_Type::RELOAD;
[email protected]d202a7c2012-01-04 07:53:47155 case NavigationControllerImpl::RELOAD_IGNORING_CACHE:
[email protected]2c5569662011-03-22 20:45:02156 return ViewMsg_Navigate_Type::RELOAD_IGNORING_CACHE;
[email protected]d202a7c2012-01-04 07:53:47157 case NavigationControllerImpl::NO_RELOAD:
[email protected]1ccb3568d2010-02-19 10:51:16158 break; // Fall through to rest of function.
159 }
[email protected]5e369672009-11-03 23:48:30160
[email protected]10f417c52011-12-28 21:04:23161 if (entry.restore_type() == NavigationEntryImpl::RESTORE_LAST_SESSION &&
[email protected]3d7474ff2011-07-27 17:47:37162 browser_context->DidLastSessionExitCleanly())
[email protected]2c5569662011-03-22 20:45:02163 return ViewMsg_Navigate_Type::RESTORE;
[email protected]5e369672009-11-03 23:48:30164
[email protected]2c5569662011-03-22 20:45:02165 return ViewMsg_Navigate_Type::NORMAL;
[email protected]5e369672009-11-03 23:48:30166}
167
[email protected]10f417c52011-12-28 21:04:23168void MakeNavigateParams(const NavigationEntryImpl& entry,
[email protected]d202a7c2012-01-04 07:53:47169 const NavigationControllerImpl& controller,
[email protected]674bc592011-12-20 23:00:42170 content::WebContentsDelegate* delegate,
[email protected]c5eed492012-01-04 17:07:50171 NavigationController::ReloadType reload_type,
[email protected]1ccb3568d2010-02-19 10:51:16172 ViewMsg_Navigate_Params* params) {
[email protected]36fc0392011-12-25 03:59:51173 params->page_id = entry.GetPageID();
[email protected]876bc832010-09-07 16:29:54174 params->pending_history_list_offset = controller.GetIndexOfEntry(&entry);
[email protected]a26023822011-12-29 00:23:55175 params->current_history_list_offset = controller.GetLastCommittedEntryIndex();
176 params->current_history_list_length = controller.GetEntryCount();
[email protected]36fc0392011-12-25 03:59:51177 params->url = entry.GetURL();
178 params->referrer = entry.GetReferrer();
179 params->transition = entry.GetTransitionType();
180 params->state = entry.GetContentState();
[email protected]3cc72b12010-03-18 23:03:00181 params->navigation_type =
[email protected]a26023822011-12-29 00:23:55182 GetNavigationType(controller.GetBrowserContext(), entry, reload_type);
[email protected]056de2d2009-06-26 16:41:34183 params->request_time = base::Time::Now();
[email protected]6c6b02d2011-09-02 03:36:47184 params->extra_headers = entry.extra_headers();
[email protected]4ad5d77d2011-12-03 02:00:48185 params->transferred_request_child_id =
186 entry.transferred_global_request_id().child_id;
187 params->transferred_request_request_id =
188 entry.transferred_global_request_id().request_id;
[email protected]6c6b02d2011-09-02 03:36:47189
190 if (delegate)
191 delegate->AddNavigationHeaders(params->url, &params->extra_headers);
[email protected]056de2d2009-06-26 16:41:34192}
193
[email protected]420ae012009-04-24 05:16:32194} // namespace
195
[email protected]a81343d232011-12-27 07:39:20196namespace content {
197
198WebContents* WebContents::Create(
199 BrowserContext* browser_context,
200 SiteInstance* site_instance,
201 int routing_id,
202 const WebContents* base_tab_contents,
203 SessionStorageNamespace* session_storage_namespace) {
204 return new TabContents(browser_context,
205 site_instance,
206 routing_id,
207 static_cast<const TabContents*>(base_tab_contents),
208 session_storage_namespace);
209}
210}
[email protected]f4f50ef2011-01-21 19:01:19211
212// TabContents ----------------------------------------------------------------
[email protected]420ae012009-04-24 05:16:32213
[email protected]3d7474ff2011-07-27 17:47:37214TabContents::TabContents(content::BrowserContext* browser_context,
[email protected]420ae012009-04-24 05:16:32215 SiteInstance* site_instance,
216 int routing_id,
[email protected]6ee12c42010-09-14 09:36:07217 const TabContents* base_tab_contents,
218 SessionStorageNamespace* session_storage_namespace)
[email protected]b680ad22009-04-15 23:19:42219 : delegate_(NULL),
[email protected]6ee12c42010-09-14 09:36:07220 ALLOW_THIS_IN_INITIALIZER_LIST(controller_(
[email protected]3d7474ff2011-07-27 17:47:37221 this, browser_context, session_storage_namespace)),
[email protected]66ba4932009-06-04 19:22:13222 ALLOW_THIS_IN_INITIALIZER_LIST(view_(
[email protected]8643e6d2012-01-18 20:26:10223 content::GetContentClient()->browser()->CreateWebContentsView(this))),
[email protected]d82ed61e2009-06-16 02:46:22224 ALLOW_THIS_IN_INITIALIZER_LIST(render_manager_(this, this)),
[email protected]d5f942ba2008-09-26 19:30:34225 is_loading_(false),
[email protected]443b80e2010-12-14 00:42:23226 crashed_status_(base::TERMINATION_STATUS_STILL_RUNNING),
227 crashed_error_code_(0),
[email protected]d5f942ba2008-09-26 19:30:34228 waiting_for_response_(false),
[email protected]9c235f042011-08-10 22:28:21229 load_state_(net::LOAD_STATE_IDLE, string16()),
[email protected]094e5b22009-09-25 04:23:56230 upload_size_(0),
231 upload_position_(0),
[email protected]f17a0ee2010-05-17 17:38:47232 displayed_insecure_content_(false),
[email protected]fdd61c62009-04-22 19:22:57233 capturing_contents_(false),
234 is_being_destroyed_(false),
235 notify_disconnection_(false),
[email protected]2e5b90c2011-08-16 21:11:55236 dialog_creator_(NULL),
[email protected]fdd61c62009-04-22 19:22:57237#if defined(OS_WIN)
238 message_box_active_(CreateEvent(NULL, TRUE, FALSE, NULL)),
239#endif
[email protected]7ab1e7d62009-10-14 23:32:01240 is_showing_before_unload_dialog_(false),
[email protected]1fd1a502011-03-30 16:55:56241 opener_web_ui_type_(WebUI::kNoWebUI),
[email protected]ebf40a72010-07-22 01:46:38242 closed_by_user_gesture_(false),
[email protected]b75b8292010-10-01 07:28:25243 minimum_zoom_percent_(
[email protected]0f083402011-11-22 02:59:01244 static_cast<int>(content::kMinimumZoomFactor * 100)),
[email protected]b75b8292010-10-01 07:28:25245 maximum_zoom_percent_(
[email protected]0f083402011-11-22 02:59:01246 static_cast<int>(content::kMaximumZoomFactor * 100)),
[email protected]9e823662010-10-13 23:36:00247 temporary_zoom_settings_(false),
[email protected]32ded2212011-11-10 18:51:43248 content_restrictions_(0),
249 view_type_(content::VIEW_TYPE_TAB_CONTENTS) {
[email protected]3d7474ff2011-07-27 17:47:37250 render_manager_.Init(browser_context, site_instance, routing_id);
[email protected]420ae012009-04-24 05:16:32251
[email protected]34ac70502009-09-25 17:07:23252 // We have the initial size of the view be based on the size of the passed in
253 // tab contents (normally a tab from the same window).
254 view_->CreateView(base_tab_contents ?
[email protected]d487beefe2011-12-21 05:41:21255 base_tab_contents->GetView()->GetContainerSize() : gfx::Size());
[email protected]483623eb2011-10-25 09:30:00256
257#if defined(ENABLE_JAVA_BRIDGE)
258 java_bridge_dispatcher_host_manager_.reset(
259 new JavaBridgeDispatcherHostManager(this));
260#endif
[email protected]332af7732009-03-11 13:21:35261}
initial.commit09911bf2008-07-26 23:55:29262
263TabContents::~TabContents() {
[email protected]420ae012009-04-24 05:16:32264 is_being_destroyed_ = true;
265
[email protected]3ab9cb82011-06-03 18:02:07266 // Clear out any JavaScript state.
[email protected]2e5b90c2011-08-16 21:11:55267 if (dialog_creator_)
268 dialog_creator_->ResetJavaScriptState(this);
[email protected]3ab9cb82011-06-03 18:02:07269
[email protected]420ae012009-04-24 05:16:32270 NotifyDisconnected();
[email protected]420ae012009-04-24 05:16:32271
[email protected]420ae012009-04-24 05:16:32272 // Notify any observer that have a reference on this tab contents.
[email protected]ad50def52011-10-19 23:17:07273 content::NotificationService::current()->Notify(
[email protected]ea049a02011-12-25 21:37:09274 content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
275 content::Source<WebContents>(this),
[email protected]ad50def52011-10-19 23:17:07276 content::NotificationService::NoDetails());
[email protected]420ae012009-04-24 05:16:32277
278 // TODO(brettw) this should be moved to the view.
[email protected]010882f2011-11-14 22:32:07279#if defined(OS_WIN) && !defined(USE_AURA)
[email protected]420ae012009-04-24 05:16:32280 // If we still have a window handle, destroy it. GetNativeView can return
281 // NULL if this contents was part of a window that closed.
[email protected]50bd6452010-11-27 19:39:42282 if (GetNativeView()) {
[email protected]151a63d2011-12-20 22:32:52283 RenderViewHost* host = GetRenderViewHost();
[email protected]b9a1fb42011-04-12 23:16:44284 if (host && host->view())
[email protected]50bd6452010-11-27 19:39:42285 host->view()->WillWmDestroy();
[email protected]50bd6452010-11-27 19:39:42286 }
[email protected]420ae012009-04-24 05:16:32287#endif
[email protected]7ab1e7d62009-10-14 23:32:01288
289 // OnCloseStarted isn't called in unit tests.
290 if (!tab_close_start_time_.is_null()) {
291 UMA_HISTOGRAM_TIMES("Tab.Close",
292 base::TimeTicks::Now() - tab_close_start_time_);
293 }
[email protected]b5a1d11c2011-02-17 03:09:42294
[email protected]d8c660432011-12-22 20:51:25295 FOR_EACH_OBSERVER(WebContentsObserver, observers_, TabContentsDestroyed());
[email protected]232a5812011-03-04 22:42:08296
[email protected]6934a702011-12-20 00:04:51297 SetDelegate(NULL);
[email protected]b5a1d11c2011-02-17 03:09:42298}
299
[email protected]d202a7c2012-01-04 07:53:47300NavigationControllerImpl& TabContents::GetControllerImpl() {
[email protected]cdcb1dee2012-01-04 00:46:20301 return controller_;
302}
303
[email protected]765187182012-01-11 23:59:28304RenderViewHostManager* TabContents::GetRenderManagerForTesting() {
305 return &render_manager_;
306}
307
[email protected]724159a2010-12-30 01:11:18308bool TabContents::OnMessageReceived(const IPC::Message& message) {
[email protected]d2353452012-01-19 19:53:56309 if (GetWebUI() &&
310 static_cast<WebUIImpl*>(GetWebUI())->OnMessageReceived(message)) {
[email protected]f82d57b52011-04-27 19:13:17311 return true;
[email protected]d2353452012-01-19 19:53:56312 }
[email protected]f82d57b52011-04-27 19:13:17313
[email protected]d8c660432011-12-22 20:51:25314 ObserverListBase<WebContentsObserver>::Iterator it(observers_);
315 WebContentsObserver* observer;
[email protected]0f180ee2011-01-21 18:23:10316 while ((observer = it.GetNext()) != NULL)
317 if (observer->OnMessageReceived(message))
[email protected]403415a2011-01-10 18:57:53318 return true;
[email protected]403415a2011-01-10 18:57:53319
[email protected]724159a2010-12-30 01:11:18320 bool handled = true;
321 bool message_is_ok = true;
322 IPC_BEGIN_MESSAGE_MAP_EX(TabContents, message, message_is_ok)
[email protected]8b5af492011-11-28 21:50:58323 IPC_MESSAGE_HANDLER(IntentsHostMsg_RegisterIntentService,
324 OnRegisterIntentService)
[email protected]ce9751942011-09-21 01:57:24325 IPC_MESSAGE_HANDLER(IntentsHostMsg_WebIntentDispatch,
326 OnWebIntentDispatch)
[email protected]724159a2010-12-30 01:11:18327 IPC_MESSAGE_HANDLER(ViewHostMsg_DidStartProvisionalLoadForFrame,
328 OnDidStartProvisionalLoadForFrame)
329 IPC_MESSAGE_HANDLER(ViewHostMsg_DidRedirectProvisionalLoad,
330 OnDidRedirectProvisionalLoad)
331 IPC_MESSAGE_HANDLER(ViewHostMsg_DidFailProvisionalLoadWithError,
332 OnDidFailProvisionalLoadWithError)
333 IPC_MESSAGE_HANDLER(ViewHostMsg_DidLoadResourceFromMemoryCache,
334 OnDidLoadResourceFromMemoryCache)
335 IPC_MESSAGE_HANDLER(ViewHostMsg_DidDisplayInsecureContent,
336 OnDidDisplayInsecureContent)
337 IPC_MESSAGE_HANDLER(ViewHostMsg_DidRunInsecureContent,
338 OnDidRunInsecureContent)
339 IPC_MESSAGE_HANDLER(ViewHostMsg_DocumentLoadedInFrame,
340 OnDocumentLoadedInFrame)
341 IPC_MESSAGE_HANDLER(ViewHostMsg_DidFinishLoad, OnDidFinishLoad)
[email protected]c8f73ab2011-01-22 00:05:17342 IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateContentRestrictions,
343 OnUpdateContentRestrictions)
[email protected]7d472472011-01-22 01:30:25344 IPC_MESSAGE_HANDLER(ViewHostMsg_GoToEntryAtOffset, OnGoToEntryAtOffset)
[email protected]216813952011-05-19 22:21:26345 IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateZoomLimits, OnUpdateZoomLimits)
[email protected]c7dd2f62011-07-18 15:57:59346 IPC_MESSAGE_HANDLER(ViewHostMsg_SaveURLAs, OnSaveURL)
[email protected]3a29a6e2011-08-24 18:26:21347 IPC_MESSAGE_HANDLER(ViewHostMsg_EnumerateDirectory, OnEnumerateDirectory)
[email protected]7d189022011-08-25 22:54:20348 IPC_MESSAGE_HANDLER(ViewHostMsg_JSOutOfMemory, OnJSOutOfMemory)
349 IPC_MESSAGE_HANDLER(ViewHostMsg_RegisterProtocolHandler,
350 OnRegisterProtocolHandler)
[email protected]b888919c2011-09-02 00:32:16351 IPC_MESSAGE_HANDLER(ViewHostMsg_Find_Reply, OnFindReply)
[email protected]d952a052011-09-06 18:42:45352 IPC_MESSAGE_HANDLER(ViewHostMsg_CrashedPlugin, OnCrashedPlugin)
[email protected]7fc4bbb2011-09-08 21:23:10353 IPC_MESSAGE_HANDLER(ViewHostMsg_AppCacheAccessed, OnAppCacheAccessed)
[email protected]724159a2010-12-30 01:11:18354 IPC_MESSAGE_UNHANDLED(handled = false)
355 IPC_END_MESSAGE_MAP_EX()
356
357 if (!message_is_ok) {
[email protected]7f6f44c2011-12-14 13:23:38358 content::RecordAction(UserMetricsAction("BadMessageTerminate_RVD"));
[email protected]724159a2010-12-30 01:11:18359 GetRenderProcessHost()->ReceivedBadMessage();
360 }
361
362 return handled;
363}
364
[email protected]6c2e472f2011-08-24 23:26:18365void TabContents::RunFileChooser(
366 RenderViewHost* render_view_host,
[email protected]8caadeb2011-11-22 02:45:23367 const content::FileChooserParams& params) {
[email protected]6934a702011-12-20 00:04:51368 delegate_->RunFileChooser(this, params);
[email protected]6c2e472f2011-08-24 23:26:18369}
370
[email protected]c5eed492012-01-04 17:07:50371NavigationController& TabContents::GetController() {
[email protected]f5fa20e2011-12-21 22:35:56372 return controller_;
373}
374
[email protected]c5eed492012-01-04 17:07:50375const NavigationController& TabContents::GetController() const {
[email protected]f5fa20e2011-12-21 22:35:56376 return controller_;
377}
378
[email protected]627e0512011-12-21 22:55:30379content::BrowserContext* TabContents::GetBrowserContext() const {
[email protected]a26023822011-12-29 00:23:55380 return controller_.GetBrowserContext();
[email protected]627e0512011-12-21 22:55:30381}
382
[email protected]f5fa20e2011-12-21 22:35:56383void TabContents::SetViewType(content::ViewType type) {
384 view_type_ = type;
385}
386
[email protected]ea049a02011-12-25 21:37:09387content::ViewType TabContents::GetViewType() const {
388 return view_type_;
389}
390
[email protected]be1f56ab2011-12-22 06:55:31391const GURL& TabContents::GetURL() const {
392 // We may not have a navigation entry yet
[email protected]10f417c52011-12-28 21:04:23393 NavigationEntry* entry = controller_.GetActiveEntry();
[email protected]36fc0392011-12-25 03:59:51394 return entry ? entry->GetVirtualURL() : GURL::EmptyGURL();
[email protected]be1f56ab2011-12-22 06:55:31395}
396
397
398const base::PropertyBag* TabContents::GetPropertyBag() const {
399 return &property_bag_;
400}
401
402base::PropertyBag* TabContents::GetPropertyBag() {
403 return &property_bag_;
404}
405
406content::WebContentsDelegate* TabContents::GetDelegate() {
407 return delegate_;
408}
409
410void TabContents::SetDelegate(content::WebContentsDelegate* delegate) {
411 // TODO(cbentzel): remove this debugging code?
412 if (delegate == delegate_)
413 return;
414 if (delegate_)
415 delegate_->Detach(this);
416 delegate_ = delegate;
417 if (delegate_)
418 delegate_->Attach(this);
419}
420
[email protected]f3b1a082011-11-18 00:34:30421content::RenderProcessHost* TabContents::GetRenderProcessHost() const {
[email protected]4d0df262011-10-03 20:05:03422 if (render_manager_.current_host())
423 return render_manager_.current_host()->process();
424 else
425 return NULL;
[email protected]8cb5d5b2010-02-09 11:36:16426}
427
[email protected]be1f56ab2011-12-22 06:55:31428RenderViewHost* TabContents::GetRenderViewHost() const {
429 return render_manager_.current_host();
430}
431
432RenderWidgetHostView* TabContents::GetRenderWidgetHostView() const {
433 return render_manager_.GetRenderWidgetHostView();
434}
435
[email protected]8643e6d2012-01-18 20:26:10436content::WebContentsView* TabContents::GetView() const {
[email protected]be1f56ab2011-12-22 06:55:31437 return view_.get();
438}
439
[email protected]01ec4ec2012-01-18 04:13:47440content::WebUI* TabContents::CreateWebUI(const GURL& url) {
[email protected]d2353452012-01-19 19:53:56441 WebUIImpl* web_ui = new WebUIImpl(this);
[email protected]c63cedf22012-01-17 18:42:22442 WebUIController* controller =
443 content::GetContentClient()->browser()->GetWebUIFactory()->
444 CreateWebUIForURL(web_ui, url);
445 if (controller) {
446 web_ui->SetController(controller);
447 return web_ui;
448 }
449
450 delete web_ui;
451 return NULL;
452}
453
[email protected]01ec4ec2012-01-18 04:13:47454content::WebUI* TabContents::GetWebUI() const {
[email protected]be1f56ab2011-12-22 06:55:31455 return render_manager_.web_ui() ? render_manager_.web_ui()
456 : render_manager_.pending_web_ui();
457}
458
[email protected]01ec4ec2012-01-18 04:13:47459content::WebUI* TabContents::GetCommittedWebUI() const {
[email protected]be1f56ab2011-12-22 06:55:31460 return render_manager_.web_ui();
[email protected]d5f942ba2008-09-26 19:30:34461}
462
[email protected]96d185d2009-04-24 03:28:54463const string16& TabContents::GetTitle() const {
[email protected]4c6092c5b2009-06-06 00:23:55464 // Transient entries take precedence. They are used for interstitial pages
465 // that are shown on top of existing pages.
[email protected]10f417c52011-12-28 21:04:23466 NavigationEntry* entry = controller_.GetTransientEntry();
[email protected]b5cca982011-05-26 04:42:08467 std::string accept_languages =
[email protected]597a867b2011-11-18 18:31:20468 content::GetContentClient()->browser()->GetAcceptLangs(
[email protected]627e0512011-12-21 22:55:30469 GetBrowserContext());
[email protected]45d0ef7f2011-01-05 13:46:23470 if (entry) {
[email protected]b5cca982011-05-26 04:42:08471 return entry->GetTitleForDisplay(accept_languages);
[email protected]45d0ef7f2011-01-05 13:46:23472 }
[email protected]7ade2732011-02-10 00:13:58473 WebUI* our_web_ui = render_manager_.pending_web_ui() ?
474 render_manager_.pending_web_ui() : render_manager_.web_ui();
475 if (our_web_ui) {
[email protected]96d185d2009-04-24 03:28:54476 // Don't override the title in view source mode.
[email protected]4c6092c5b2009-06-06 00:23:55477 entry = controller_.GetActiveEntry();
[email protected]96d185d2009-04-24 03:28:54478 if (!(entry && entry->IsViewSourceMode())) {
[email protected]e0112912011-02-02 22:54:35479 // Give the Web UI the chance to override our title.
[email protected]c63cedf22012-01-17 18:42:22480 const string16& title = our_web_ui->GetOverriddenTitle();
[email protected]96d185d2009-04-24 03:28:54481 if (!title.empty())
482 return title;
483 }
484 }
485
486 // We use the title for the last committed entry rather than a pending
487 // navigation entry. For example, when the user types in a URL, we want to
488 // keep the old page's title until the new load has committed and we get a new
489 // title.
[email protected]96d185d2009-04-24 03:28:54490 entry = controller_.GetLastCommittedEntry();
[email protected]45d0ef7f2011-01-05 13:46:23491 if (entry) {
[email protected]b5cca982011-05-26 04:42:08492 return entry->GetTitleForDisplay(accept_languages);
[email protected]45d0ef7f2011-01-05 13:46:23493 }
[email protected]987fc3a2011-05-26 14:18:09494
495 // |page_title_when_no_navigation_entry_| is finally used
496 // if no title cannot be retrieved.
497 return page_title_when_no_navigation_entry_;
[email protected]96d185d2009-04-24 03:28:54498}
499
[email protected]d5f942ba2008-09-26 19:30:34500int32 TabContents::GetMaxPageID() {
[email protected]74ce1ad2011-12-16 21:51:46501 return GetMaxPageIDForSiteInstance(GetSiteInstance());
502}
503
504int32 TabContents::GetMaxPageIDForSiteInstance(SiteInstance* site_instance) {
505 if (max_page_ids_.find(site_instance->id()) == max_page_ids_.end())
506 max_page_ids_[site_instance->id()] = -1;
507
508 return max_page_ids_[site_instance->id()];
[email protected]d5f942ba2008-09-26 19:30:34509}
510
511void TabContents::UpdateMaxPageID(int32 page_id) {
[email protected]74ce1ad2011-12-16 21:51:46512 UpdateMaxPageIDForSiteInstance(GetSiteInstance(), page_id);
513}
514
515void TabContents::UpdateMaxPageIDForSiteInstance(SiteInstance* site_instance,
516 int32 page_id) {
517 if (GetMaxPageIDForSiteInstance(site_instance) < page_id)
518 max_page_ids_[site_instance->id()] = page_id;
[email protected]d5f942ba2008-09-26 19:30:34519}
520
[email protected]91854cd2012-01-10 19:43:57521void TabContents::CopyMaxPageIDsFrom(TabContents* tab_contents) {
522 max_page_ids_ = tab_contents->max_page_ids_;
523}
524
[email protected]96d185d2009-04-24 03:28:54525SiteInstance* TabContents::GetSiteInstance() const {
526 return render_manager_.current_host()->site_instance();
527}
528
[email protected]77362eb2011-08-01 17:18:38529SiteInstance* TabContents::GetPendingSiteInstance() const {
530 RenderViewHost* dest_rvh = render_manager_.pending_render_view_host() ?
531 render_manager_.pending_render_view_host() :
532 render_manager_.current_host();
533 return dest_rvh->site_instance();
534}
535
[email protected]be1f56ab2011-12-22 06:55:31536bool TabContents::IsLoading() const {
537 return is_loading_;
[email protected]3c9e1872010-11-18 16:17:49538}
539
[email protected]be1f56ab2011-12-22 06:55:31540bool TabContents::IsWaitingForResponse() const {
541 return waiting_for_response_;
542}
543
544const net::LoadStateWithParam& TabContents::GetLoadState() const {
545 return load_state_;
546}
547
548const string16& TabContents::GetLoadStateHost() const {
549 return load_state_host_;
550}
551
552uint64 TabContents::GetUploadSize() const {
553 return upload_size_;
554}
555
556uint64 TabContents::GetUploadPosition() const {
557 return upload_position_;
558}
559
560const std::string& TabContents::GetEncoding() const {
561 return encoding_;
562}
563
564bool TabContents::DisplayedInsecureContent() const {
565 return displayed_insecure_content_;
566}
567
568void TabContents::SetCapturingContents(bool cap) {
569 capturing_contents_ = cap;
570}
571
572bool TabContents::IsCrashed() const {
573 return (crashed_status_ == base::TERMINATION_STATUS_PROCESS_CRASHED ||
574 crashed_status_ == base::TERMINATION_STATUS_ABNORMAL_TERMINATION ||
575 crashed_status_ == base::TERMINATION_STATUS_PROCESS_WAS_KILLED);
[email protected]3c9e1872010-11-18 16:17:49576}
577
[email protected]443b80e2010-12-14 00:42:23578void TabContents::SetIsCrashed(base::TerminationStatus status, int error_code) {
579 if (status == crashed_status_)
[email protected]d5f942ba2008-09-26 19:30:34580 return;
581
[email protected]443b80e2010-12-14 00:42:23582 crashed_status_ = status;
583 crashed_error_code_ = error_code;
[email protected]d9083482012-01-06 00:38:46584 NotifyNavigationStateChanged(content::INVALIDATE_TYPE_TAB);
[email protected]d5f942ba2008-09-26 19:30:34585}
586
[email protected]be1f56ab2011-12-22 06:55:31587base::TerminationStatus TabContents::GetCrashedStatus() const {
588 return crashed_status_;
589}
590
591bool TabContents::IsBeingDestroyed() const {
592 return is_being_destroyed_;
593}
594
[email protected]d5f942ba2008-09-26 19:30:34595void TabContents::NotifyNavigationStateChanged(unsigned changed_flags) {
596 if (delegate_)
597 delegate_->NavigationStateChanged(this, changed_flags);
598}
599
[email protected]96d185d2009-04-24 03:28:54600void TabContents::DidBecomeSelected() {
601 controller_.SetActive(true);
[email protected]8cb5d5b2010-02-09 11:36:16602 RenderWidgetHostView* rwhv = GetRenderWidgetHostView();
603 if (rwhv) {
604 rwhv->DidBecomeSelected();
[email protected]789e9152009-08-04 21:59:43605#if defined(OS_MACOSX)
[email protected]8cb5d5b2010-02-09 11:36:16606 rwhv->SetActive(true);
[email protected]789e9152009-08-04 21:59:43607#endif
608 }
[email protected]96d185d2009-04-24 03:28:54609
[email protected]5ac20162010-11-24 23:33:11610 last_selected_time_ = base::TimeTicks::Now();
[email protected]3e69bc82011-05-26 23:22:38611
[email protected]d8c660432011-12-22 20:51:25612 FOR_EACH_OBSERVER(WebContentsObserver, observers_, DidBecomeSelected());
[email protected]96d185d2009-04-24 03:28:54613}
614
[email protected]be1f56ab2011-12-22 06:55:31615
616base::TimeTicks TabContents::GetLastSelectedTime() const {
617 return last_selected_time_;
618}
619
[email protected]96d185d2009-04-24 03:28:54620void TabContents::WasHidden() {
[email protected]be1f56ab2011-12-22 06:55:31621 if (!capturing_contents_) {
[email protected]151a63d2011-12-20 22:32:52622 // |GetRenderViewHost()| can be NULL if the user middle clicks a link to
623 // open a tab in then background, then closes the tab before selecting it.
624 // This is because closing the tab calls TabContents::Destroy(), which
625 // removes the |GetRenderViewHost()|; then when we actually destroy the
626 // window, OnWindowPosChanged() notices and calls HideContents() (which
627 // calls us).
[email protected]8cb5d5b2010-02-09 11:36:16628 RenderWidgetHostView* rwhv = GetRenderWidgetHostView();
629 if (rwhv)
630 rwhv->WasHidden();
[email protected]96d185d2009-04-24 03:28:54631 }
632
[email protected]ad50def52011-10-19 23:17:07633 content::NotificationService::current()->Notify(
[email protected]ea049a02011-12-25 21:37:09634 content::NOTIFICATION_WEB_CONTENTS_HIDDEN,
635 content::Source<WebContents>(this),
[email protected]ad50def52011-10-19 23:17:07636 content::NotificationService::NoDetails());
[email protected]96d185d2009-04-24 03:28:54637}
638
[email protected]be1f56ab2011-12-22 06:55:31639void TabContents::ShowContents() {
640 RenderWidgetHostView* rwhv = GetRenderWidgetHostView();
641 if (rwhv)
642 rwhv->DidBecomeSelected();
643}
644
645void TabContents::HideContents() {
646 // TODO(pkasting): http://b/1239839 Right now we purposefully don't call
647 // our superclass HideContents(), because some callers want to be very picky
648 // about the order in which these get called. In addition to making the code
649 // here practically impossible to understand, this also means we end up
650 // calling TabContents::WasHidden() twice if callers call both versions of
651 // HideContents() on a TabContents.
652 WasHidden();
653}
654
655bool TabContents::NeedToFireBeforeUnload() {
656 // TODO(creis): Should we fire even for interstitial pages?
[email protected]0bfbf882011-12-22 18:19:27657 return WillNotifyDisconnection() &&
658 !ShowingInterstitialPage() &&
[email protected]be1f56ab2011-12-22 06:55:31659 !GetRenderViewHost()->SuddenTerminationAllowed();
660}
661
[email protected]0bfbf882011-12-22 18:19:27662void TabContents::Stop() {
663 render_manager_.Stop();
[email protected]d8c660432011-12-22 20:51:25664 FOR_EACH_OBSERVER(WebContentsObserver, observers_, StopNavigation());
[email protected]0bfbf882011-12-22 18:19:27665}
666
[email protected]d9083482012-01-06 00:38:46667WebContents* TabContents::Clone() {
[email protected]0bfbf882011-12-22 18:19:27668 // We create a new SiteInstance so that the new tab won't share processes
669 // with the old one. This can be changed in the future if we need it to share
670 // processes for some reason.
671 TabContents* tc = new TabContents(
672 GetBrowserContext(),
673 SiteInstance::CreateSiteInstance(GetBrowserContext()),
674 MSG_ROUTING_NONE, this, NULL);
[email protected]cdcb1dee2012-01-04 00:46:20675 tc->GetControllerImpl().CopyStateFrom(controller_);
[email protected]0bfbf882011-12-22 18:19:27676 return tc;
677}
678
679void TabContents::ShowPageInfo(const GURL& url,
[email protected]d583e3f22011-12-27 21:38:17680 const SSLStatus& ssl,
[email protected]0bfbf882011-12-22 18:19:27681 bool show_history) {
682 if (!delegate_)
683 return;
684
685 delegate_->ShowPageInfo(GetBrowserContext(), url, ssl, show_history);
686}
687
[email protected]2a6bc3e2011-12-28 23:51:33688void TabContents::AddNewContents(WebContents* new_contents,
[email protected]0bfbf882011-12-22 18:19:27689 WindowOpenDisposition disposition,
690 const gfx::Rect& initial_pos,
691 bool user_gesture) {
692 if (!delegate_)
693 return;
694
695 delegate_->AddNewContents(this, new_contents, disposition, initial_pos,
696 user_gesture);
697}
698
699gfx::NativeView TabContents::GetContentNativeView() const {
700 return view_->GetContentNativeView();
701}
702
703gfx::NativeView TabContents::GetNativeView() const {
704 return view_->GetNativeView();
705}
706
707void TabContents::GetContainerBounds(gfx::Rect* out) const {
708 view_->GetContainerBounds(out);
709}
710
711void TabContents::Focus() {
712 view_->Focus();
713}
714
[email protected]d8c660432011-12-22 20:51:25715void TabContents::AddObserver(WebContentsObserver* observer) {
[email protected]be1f56ab2011-12-22 06:55:31716 observers_.AddObserver(observer);
717}
718
[email protected]d8c660432011-12-22 20:51:25719void TabContents::RemoveObserver(WebContentsObserver* observer) {
[email protected]be1f56ab2011-12-22 06:55:31720 observers_.RemoveObserver(observer);
721}
722
[email protected]d5f942ba2008-09-26 19:30:34723void TabContents::Activate() {
724 if (delegate_)
725 delegate_->ActivateContents(this);
726}
727
[email protected]ea42e7782010-08-23 23:58:12728void TabContents::Deactivate() {
729 if (delegate_)
730 delegate_->DeactivateContents(this);
731}
732
[email protected]63954792011-07-11 04:17:48733void TabContents::LostCapture() {
734 if (delegate_)
735 delegate_->LostCapture();
736}
737
738bool TabContents::PreHandleKeyboardEvent(const NativeWebKeyboardEvent& event,
739 bool* is_keyboard_shortcut) {
740 return delegate_ &&
741 delegate_->PreHandleKeyboardEvent(event, is_keyboard_shortcut);
742}
743
744void TabContents::HandleKeyboardEvent(const NativeWebKeyboardEvent& event) {
745 if (delegate_)
746 delegate_->HandleKeyboardEvent(event);
747}
748
[email protected]32ded2212011-11-10 18:51:43749void TabContents::HandleMouseDown() {
750 if (delegate_)
751 delegate_->HandleMouseDown();
752}
753
[email protected]63954792011-07-11 04:17:48754void TabContents::HandleMouseUp() {
755 if (delegate_)
756 delegate_->HandleMouseUp();
757}
758
759void TabContents::HandleMouseActivate() {
760 if (delegate_)
761 delegate_->HandleMouseActivate();
762}
763
[email protected]8a5e0ca2011-08-25 06:30:47764void TabContents::ToggleFullscreenMode(bool enter_fullscreen) {
765 if (delegate_)
766 delegate_->ToggleFullscreenModeForTab(this, enter_fullscreen);
767}
768
[email protected]5d5f7af2011-10-01 01:38:12769bool TabContents::IsFullscreenForCurrentTab() const {
770 return delegate_ ? delegate_->IsFullscreenForTab(this) : false;
771}
772
[email protected]e9621112011-10-17 05:38:37773void TabContents::RequestToLockMouse() {
774 if (delegate_) {
775 delegate_->RequestToLockMouse(this);
776 } else {
777 GotResponseToLockMouseRequest(false);
778 }
779}
780
781void TabContents::LostMouseLock() {
782 if (delegate_)
783 delegate_->LostMouseLock();
784}
785
[email protected]0548c5352011-09-07 00:33:33786void TabContents::UpdatePreferredSize(const gfx::Size& pref_size) {
[email protected]bcd2815602012-01-14 18:17:23787 preferred_size_ = pref_size;
[email protected]0548c5352011-09-07 00:33:33788 if (delegate_)
789 delegate_->UpdatePreferredSize(this, pref_size);
790}
791
[email protected]32ded2212011-11-10 18:51:43792void TabContents::WebUISend(RenderViewHost* render_view_host,
793 const GURL& source_url,
794 const std::string& name,
795 const base::ListValue& args) {
796 if (delegate_)
797 delegate_->WebUISend(this, source_url, name, args);
798}
799
[email protected]e5d549d2011-12-28 01:29:20800WebContents* TabContents::OpenURL(const OpenURLParams& params) {
801 if (!delegate_)
802 return NULL;
[email protected]00c37fc2011-08-02 00:22:50803
[email protected]e5d549d2011-12-28 01:29:20804 WebContents* new_contents = delegate_->OpenURLFromTab(this, params);
805 // Notify observers.
806 FOR_EACH_OBSERVER(WebContentsObserver, observers_,
807 DidOpenURL(params.url, params.referrer,
808 params.disposition, params.transition));
809 return new_contents;
[email protected]d5f942ba2008-09-26 19:30:34810}
811
[email protected]1ccb3568d2010-02-19 10:51:16812bool TabContents::NavigateToPendingEntry(
[email protected]c5eed492012-01-04 17:07:50813 NavigationController::ReloadType reload_type) {
[email protected]022af742011-12-28 18:37:25814 return NavigateToEntry(
[email protected]10f417c52011-12-28 21:04:23815 *NavigationEntryImpl::FromNavigationEntry(controller_.GetPendingEntry()),
[email protected]022af742011-12-28 18:37:25816 reload_type);
[email protected]876bc832010-09-07 16:29:54817}
[email protected]96d185d2009-04-24 03:28:54818
[email protected]876bc832010-09-07 16:29:54819bool TabContents::NavigateToEntry(
[email protected]10f417c52011-12-28 21:04:23820 const NavigationEntryImpl& entry,
[email protected]c5eed492012-01-04 17:07:50821 NavigationController::ReloadType reload_type) {
[email protected]19e81142011-10-03 16:19:40822 // The renderer will reject IPC messages with URLs longer than
823 // this limit, so don't attempt to navigate with a longer URL.
[email protected]36fc0392011-12-25 03:59:51824 if (entry.GetURL().spec().size() > content::kMaxURLChars)
[email protected]19e81142011-10-03 16:19:40825 return false;
826
[email protected]dd11de52011-11-03 22:54:27827 RenderViewHost* dest_render_view_host = render_manager_.Navigate(entry);
[email protected]ffc906f2011-10-04 22:55:40828 if (!dest_render_view_host)
829 return false; // Unable to create the desired render view host.
830
[email protected]80a8fad2011-01-29 04:02:38831 // For security, we should never send non-Web-UI URLs to a Web UI renderer.
[email protected]05fdd492010-11-15 17:52:07832 // Double check that here.
[email protected]54ec6472010-04-09 19:39:58833 int enabled_bindings = dest_render_view_host->enabled_bindings();
[email protected]1fd1a502011-03-30 16:55:56834 bool is_allowed_in_web_ui_renderer = content::GetContentClient()->
[email protected]627e0512011-12-21 22:55:30835 browser()->GetWebUIFactory()->IsURLAcceptableForWebUI(GetBrowserContext(),
[email protected]36fc0392011-12-25 03:59:51836 entry.GetURL());
[email protected]32ded2212011-11-10 18:51:43837#if defined(OS_CHROMEOS)
[email protected]36fc0392011-12-25 03:59:51838 is_allowed_in_web_ui_renderer |= entry.GetURL().SchemeIs(chrome::kDataScheme);
[email protected]32ded2212011-11-10 18:51:43839#endif
[email protected]e091df82011-10-11 18:13:21840 CHECK(!(enabled_bindings & content::BINDINGS_POLICY_WEB_UI) ||
[email protected]c09163a2011-02-15 00:05:55841 is_allowed_in_web_ui_renderer);
[email protected]54ec6472010-04-09 19:39:58842
[email protected]96d185d2009-04-24 03:28:54843 // Tell DevTools agent that it is attached prior to the navigation.
[email protected]0e12d7d2011-12-01 16:21:44844 DevToolsManagerImpl::GetInstance()->OnNavigatingToPendingEntry(
[email protected]151a63d2011-12-20 22:32:52845 GetRenderViewHost(),
[email protected]0e12d7d2011-12-01 16:21:44846 dest_render_view_host,
[email protected]36fc0392011-12-25 03:59:51847 entry.GetURL());
[email protected]96d185d2009-04-24 03:28:54848
849 // Used for page load time metrics.
850 current_load_start_ = base::TimeTicks::Now();
851
852 // Navigate in the desired RenderViewHost.
[email protected]056de2d2009-06-26 16:41:34853 ViewMsg_Navigate_Params navigate_params;
[email protected]dd11de52011-11-03 22:54:27854 MakeNavigateParams(entry, controller_, delegate_, reload_type,
[email protected]6c6b02d2011-09-02 03:36:47855 &navigate_params);
[email protected]056de2d2009-06-26 16:41:34856 dest_render_view_host->Navigate(navigate_params);
[email protected]96d185d2009-04-24 03:28:54857
[email protected]36fc0392011-12-25 03:59:51858 if (entry.GetPageID() == -1) {
[email protected]96d185d2009-04-24 03:28:54859 // HACK!! This code suppresses javascript: URLs from being added to
860 // session history, which is what we want to do for javascript: URLs that
861 // do not generate content. What we really need is a message from the
862 // renderer telling us that a new page was not created. The same message
863 // could be used for mailto: URLs and the like.
[email protected]36fc0392011-12-25 03:59:51864 if (entry.GetURL().SchemeIs(chrome::kJavaScriptScheme))
[email protected]96d185d2009-04-24 03:28:54865 return false;
866 }
867
[email protected]3c9e1872010-11-18 16:17:49868 // Notify observers about navigation.
[email protected]d8c660432011-12-22 20:51:25869 FOR_EACH_OBSERVER(WebContentsObserver,
[email protected]b375c5d2011-05-03 21:15:04870 observers_,
[email protected]36fc0392011-12-25 03:59:51871 NavigateToPendingEntry(entry.GetURL(), reload_type));
[email protected]96d185d2009-04-24 03:28:54872
[email protected]09b29342011-06-24 19:18:48873 if (delegate_)
874 delegate_->DidNavigateToPendingEntry(this);
875
[email protected]d5f942ba2008-09-26 19:30:34876 return true;
877}
878
[email protected]9e1ad4b2011-08-14 16:49:19879void TabContents::SetHistoryLengthAndPrune(const SiteInstance* site_instance,
880 int history_length,
881 int32 minimum_page_id) {
[email protected]5229253b2011-08-16 14:36:41882 // SetHistoryLengthAndPrune doesn't work when there are pending cross-site
883 // navigations. Callers should ensure that this is the case.
[email protected]9e1ad4b2011-08-14 16:49:19884 if (render_manager_.pending_render_view_host()) {
885 NOTREACHED();
[email protected]796931a92011-08-10 01:32:14886 return;
[email protected]9e1ad4b2011-08-14 16:49:19887 }
[email protected]151a63d2011-12-20 22:32:52888 RenderViewHost* rvh = GetRenderViewHost();
[email protected]9e1ad4b2011-08-14 16:49:19889 if (!rvh) {
890 NOTREACHED();
891 return;
892 }
893 if (site_instance && rvh->site_instance() != site_instance) {
894 NOTREACHED();
895 return;
896 }
897 rvh->Send(new ViewMsg_SetHistoryLengthAndPrune(rvh->routing_id(),
898 history_length,
899 minimum_page_id));
[email protected]796931a92011-08-10 01:32:14900}
901
[email protected]90daadb42009-06-08 21:27:28902void TabContents::FocusThroughTabTraversal(bool reverse) {
[email protected]0bfbf882011-12-22 18:19:27903 if (ShowingInterstitialPage()) {
[email protected]7e383692009-06-12 19:14:54904 render_manager_.interstitial_page()->FocusThroughTabTraversal(reverse);
905 return;
906 }
[email protected]151a63d2011-12-20 22:32:52907 GetRenderViewHost()->SetInitialFocus(reverse);
[email protected]96d185d2009-04-24 03:28:54908}
909
[email protected]0bfbf882011-12-22 18:19:27910bool TabContents::ShowingInterstitialPage() const {
911 return render_manager_.interstitial_page() != NULL;
[email protected]96d185d2009-04-24 03:28:54912}
913
[email protected]0bfbf882011-12-22 18:19:27914InterstitialPage* TabContents::GetInterstitialPage() const {
915 return render_manager_.interstitial_page();
[email protected]686493142011-07-15 21:47:22916}
917
[email protected]c7dd2f62011-07-18 15:57:59918void TabContents::OnSavePage() {
919 // If we can not save the page, try to download it.
[email protected]0bfbf882011-12-22 18:19:27920 if (!SavePackage::IsSavableContents(GetContentsMimeType())) {
[email protected]627e0512011-12-21 22:55:30921 DownloadManager* dlm = GetBrowserContext()->GetDownloadManager();
[email protected]c7dd2f62011-07-18 15:57:59922 const GURL& current_page_url = GetURL();
923 if (dlm && current_page_url.is_valid()) {
924 dlm->DownloadUrl(current_page_url, GURL(), "", this);
[email protected]8bd9e562011-08-16 23:55:46925 download_stats::RecordDownloadCount(
926 download_stats::INITIATED_BY_SAVE_PACKAGE_FAILURE_COUNT);
[email protected]c7dd2f62011-07-18 15:57:59927 return;
928 }
929 }
930
931 Stop();
932
933 // Create the save package and possibly prompt the user for the name to save
934 // the page as. The user prompt is an asynchronous operation that runs on
935 // another thread.
936 save_package_ = new SavePackage(this);
937 save_package_->GetSaveInfo();
938}
939
940// Used in automated testing to bypass prompting the user for file names.
941// Instead, the names and paths are hard coded rather than running them through
942// file name sanitation and extension / mime checking.
943bool TabContents::SavePage(const FilePath& main_file, const FilePath& dir_path,
944 SavePackage::SavePackageType save_type) {
945 // Stop the page from navigating.
946 Stop();
947
948 save_package_ = new SavePackage(this, save_type, main_file, dir_path);
949 return save_package_->Init();
950}
951
[email protected]420ae012009-04-24 05:16:32952bool TabContents::IsActiveEntry(int32 page_id) {
[email protected]10f417c52011-12-28 21:04:23953 NavigationEntryImpl* active_entry =
954 NavigationEntryImpl::FromNavigationEntry(controller_.GetActiveEntry());
[email protected]420ae012009-04-24 05:16:32955 return (active_entry != NULL &&
956 active_entry->site_instance() == GetSiteInstance() &&
[email protected]36fc0392011-12-25 03:59:51957 active_entry->GetPageID() == page_id);
[email protected]420ae012009-04-24 05:16:32958}
959
[email protected]0bfbf882011-12-22 18:19:27960const std::string& TabContents::GetContentsMimeType() const {
961 return contents_mime_type_;
962}
963
964bool TabContents::WillNotifyDisconnection() const {
965 return notify_disconnection_;
966}
967
[email protected]b2fe07d12010-02-09 14:38:08968void TabContents::SetOverrideEncoding(const std::string& encoding) {
[email protected]be1f56ab2011-12-22 06:55:31969 SetEncoding(encoding);
[email protected]151a63d2011-12-20 22:32:52970 GetRenderViewHost()->Send(new ViewMsg_SetPageEncoding(
971 GetRenderViewHost()->routing_id(), encoding));
[email protected]8cb5d5b2010-02-09 11:36:16972}
973
[email protected]b2fe07d12010-02-09 14:38:08974void TabContents::ResetOverrideEncoding() {
[email protected]be1f56ab2011-12-22 06:55:31975 encoding_.clear();
[email protected]151a63d2011-12-20 22:32:52976 GetRenderViewHost()->Send(new ViewMsg_ResetPageEncodingToDefault(
977 GetRenderViewHost()->routing_id()));
[email protected]8cb5d5b2010-02-09 11:36:16978}
979
[email protected]0bfbf882011-12-22 18:19:27980content::RendererPreferences* TabContents::GetMutableRendererPrefs() {
981 return &renderer_preferences_;
982}
983
984void TabContents::SetNewTabStartTime(const base::TimeTicks& time) {
985 new_tab_start_time_ = time;
986}
987
988base::TimeTicks TabContents::GetNewTabStartTime() const {
989 return new_tab_start_time_;
990}
991
[email protected]7ab1e7d62009-10-14 23:32:01992void TabContents::OnCloseStarted() {
993 if (tab_close_start_time_.is_null())
994 tab_close_start_time_ = base::TimeTicks::Now();
995}
996
[email protected]46624bf2010-06-09 16:04:19997bool TabContents::ShouldAcceptDragAndDrop() const {
998#if defined(OS_CHROMEOS)
999 // ChromeOS panels (pop-ups) do not take drag-n-drop.
1000 // See http://crosbug.com/2413
[email protected]6934a702011-12-20 00:04:511001 if (delegate_ && delegate_->IsPopupOrPanel(this))
[email protected]b83af492010-10-09 03:21:201002 return false;
1003 return true;
[email protected]46624bf2010-06-09 16:04:191004#else
1005 return true;
1006#endif
1007}
1008
[email protected]7813bd72011-02-05 02:19:341009void TabContents::SystemDragEnded() {
[email protected]151a63d2011-12-20 22:32:521010 if (GetRenderViewHost())
1011 GetRenderViewHost()->DragSourceSystemDragEnded();
[email protected]6934a702011-12-20 00:04:511012 if (delegate_)
1013 delegate_->DragEnded();
[email protected]7813bd72011-02-05 02:19:341014}
1015
[email protected]0bfbf882011-12-22 18:19:271016void TabContents::SetClosedByUserGesture(bool value) {
1017 closed_by_user_gesture_ = value;
1018}
1019
1020bool TabContents::GetClosedByUserGesture() const {
1021 return closed_by_user_gesture_;
1022}
1023
[email protected]d0b8d092010-10-25 04:05:171024double TabContents::GetZoomLevel() const {
[email protected]627e0512011-12-21 22:55:301025 HostZoomMap* zoom_map = GetBrowserContext()->GetHostZoomMap();
[email protected]b75b8292010-10-01 07:28:251026 if (!zoom_map)
[email protected]d0b8d092010-10-25 04:05:171027 return 0;
[email protected]b75b8292010-10-01 07:28:251028
1029 double zoom_level;
1030 if (temporary_zoom_settings_) {
1031 zoom_level = zoom_map->GetTemporaryZoomLevel(
[email protected]151a63d2011-12-20 22:32:521032 GetRenderProcessHost()->GetID(), GetRenderViewHost()->routing_id());
[email protected]b75b8292010-10-01 07:28:251033 } else {
[email protected]2ae88d12011-10-14 09:11:191034 GURL url;
[email protected]10f417c52011-12-28 21:04:231035 NavigationEntry* active_entry = GetController().GetActiveEntry();
[email protected]2ae88d12011-10-14 09:11:191036 // Since zoom map is updated using rewritten URL, use rewritten URL
1037 // to get the zoom level.
[email protected]36fc0392011-12-25 03:59:511038 url = active_entry ? active_entry->GetURL() : GURL::EmptyGURL();
[email protected]2ae88d12011-10-14 09:11:191039 zoom_level = zoom_map->GetZoomLevel(net::GetHostOrSpecFromURL(url));
[email protected]b75b8292010-10-01 07:28:251040 }
[email protected]d0b8d092010-10-25 04:05:171041 return zoom_level;
1042}
[email protected]b75b8292010-10-01 07:28:251043
[email protected]d0b8d092010-10-25 04:05:171044int TabContents::GetZoomPercent(bool* enable_increment,
1045 bool* enable_decrement) {
1046 *enable_decrement = *enable_increment = false;
[email protected]0f083402011-11-22 02:59:011047 // Calculate the zoom percent from the factor. Round up to the nearest whole
1048 // number.
[email protected]b75b8292010-10-01 07:28:251049 int percent = static_cast<int>(
[email protected]0f083402011-11-22 02:59:011050 WebKit::WebView::zoomLevelToZoomFactor(GetZoomLevel()) * 100 + 0.5);
[email protected]b75b8292010-10-01 07:28:251051 *enable_decrement = percent > minimum_zoom_percent_;
1052 *enable_increment = percent < maximum_zoom_percent_;
1053 return percent;
1054}
1055
[email protected]3c733bde2010-12-21 19:56:311056void TabContents::ViewSource() {
[email protected]1788e772010-12-15 16:40:501057 if (!delegate_)
1058 return;
1059
[email protected]10f417c52011-12-28 21:04:231060 NavigationEntry* active_entry = GetController().GetActiveEntry();
[email protected]1788e772010-12-15 16:40:501061 if (!active_entry)
1062 return;
1063
[email protected]36fc0392011-12-25 03:59:511064 delegate_->ViewSourceForTab(this, active_entry->GetURL());
[email protected]77d8d622010-12-15 10:30:121065}
1066
[email protected]932b7a12011-03-09 12:50:271067void TabContents::ViewFrameSource(const GURL& url,
1068 const std::string& content_state) {
1069 if (!delegate_)
1070 return;
1071
1072 delegate_->ViewSourceForFrame(this, url, content_state);
1073}
1074
[email protected]0bfbf882011-12-22 18:19:271075int TabContents::GetMinimumZoomPercent() const {
1076 return minimum_zoom_percent_;
1077}
1078
1079int TabContents::GetMaximumZoomPercent() const {
1080 return maximum_zoom_percent_;
1081}
1082
[email protected]bcd2815602012-01-14 18:17:231083gfx::Size TabContents::GetPreferredSize() const {
1084 return preferred_size_;
1085}
1086
[email protected]0bfbf882011-12-22 18:19:271087int TabContents::GetContentRestrictions() const {
1088 return content_restrictions_;
1089}
1090
1091WebUI::TypeID TabContents::GetWebUITypeForCurrentState() {
[email protected]f3f3b722012-01-07 01:29:431092 return content::GetContentClient()->browser()->GetWebUIFactory()->
1093 GetWebUIType(GetBrowserContext(), GetURL());
[email protected]0bfbf882011-12-22 18:19:271094}
1095
[email protected]01ec4ec2012-01-18 04:13:471096content::WebUI* TabContents::GetWebUIForCurrentState() {
[email protected]0bfbf882011-12-22 18:19:271097 // When there is a pending navigation entry, we want to use the pending WebUI
1098 // that goes along with it to control the basic flags. For example, we want to
1099 // show the pending URL in the URL bar, so we want the display_url flag to
1100 // be from the pending entry.
1101 //
1102 // The confusion comes because there are multiple possibilities for the
1103 // initial load in a tab as a side effect of the way the RenderViewHostManager
1104 // works.
1105 //
1106 // - For the very first tab the load looks "normal". The new tab Web UI is
1107 // the pending one, and we want it to apply here.
1108 //
1109 // - For subsequent new tabs, they'll get a new SiteInstance which will then
1110 // get switched to the one previously associated with the new tab pages.
1111 // This switching will cause the manager to commit the RVH/WebUI. So we'll
1112 // have a committed Web UI in this case.
1113 //
1114 // This condition handles all of these cases:
1115 //
1116 // - First load in first tab: no committed nav entry + pending nav entry +
1117 // pending dom ui:
1118 // -> Use pending Web UI if any.
1119 //
1120 // - First load in second tab: no committed nav entry + pending nav entry +
1121 // no pending Web UI:
1122 // -> Use the committed Web UI if any.
1123 //
1124 // - Second navigation in any tab: committed nav entry + pending nav entry:
1125 // -> Use pending Web UI if any.
1126 //
1127 // - Normal state with no load: committed nav entry + no pending nav entry:
1128 // -> Use committed Web UI.
[email protected]022af742011-12-28 18:37:251129 if (controller_.GetPendingEntry() &&
[email protected]0bfbf882011-12-22 18:19:271130 (controller_.GetLastCommittedEntry() ||
1131 render_manager_.pending_web_ui()))
1132 return render_manager_.pending_web_ui();
1133 return render_manager_.web_ui();
1134}
1135
1136bool TabContents::GotResponseToLockMouseRequest(bool allowed) {
1137 return GetRenderViewHost() ?
1138 GetRenderViewHost()->GotResponseToLockMouseRequest(allowed) : false;
1139}
1140
1141bool TabContents::FocusLocationBarByDefault() {
[email protected]01ec4ec2012-01-18 04:13:471142 content::WebUI* web_ui = GetWebUIForCurrentState();
[email protected]0bfbf882011-12-22 18:19:271143 if (web_ui)
[email protected]c63cedf22012-01-17 18:42:221144 return web_ui->ShouldFocusLocationBarByDefault();
[email protected]10f417c52011-12-28 21:04:231145 NavigationEntry* entry = controller_.GetActiveEntry();
[email protected]36fc0392011-12-25 03:59:511146 if (entry && entry->GetURL() == GURL(chrome::kAboutBlankURL))
[email protected]0bfbf882011-12-22 18:19:271147 return true;
1148 return false;
1149}
1150
1151void TabContents::SetFocusToLocationBar(bool select_all) {
1152 if (delegate_)
1153 delegate_->SetFocusToLocationBar(select_all);
[email protected]c40d6232011-03-25 00:16:211154}
1155
[email protected]8b5af492011-11-28 21:50:581156void TabContents::OnRegisterIntentService(const string16& action,
[email protected]63c239322011-10-31 23:56:301157 const string16& type,
1158 const string16& href,
1159 const string16& title,
1160 const string16& disposition) {
[email protected]6934a702011-12-20 00:04:511161 delegate_->RegisterIntentHandler(
[email protected]63c239322011-10-31 23:56:301162 this, action, type, href, title, disposition);
1163}
1164
[email protected]678105012011-12-09 04:01:211165void TabContents::OnWebIntentDispatch(const webkit_glue::WebIntentData& intent,
[email protected]63c239322011-10-31 23:56:301166 int intent_id) {
[email protected]0d9989d2011-12-21 20:26:001167 WebIntentsDispatcherImpl* intents_dispatcher =
1168 new WebIntentsDispatcherImpl(this, intent, intent_id);
1169 delegate_->WebIntentDispatch(this, intents_dispatcher);
[email protected]63c239322011-10-31 23:56:301170}
1171
[email protected]724159a2010-12-30 01:11:181172void TabContents::OnDidStartProvisionalLoadForFrame(int64 frame_id,
1173 bool is_main_frame,
[email protected]57b9396c2011-10-07 19:11:591174 const GURL& opener_url,
[email protected]724159a2010-12-30 01:11:181175 const GURL& url) {
1176 bool is_error_page = (url.spec() == chrome::kUnreachableWebDataURL);
1177 GURL validated_url(url);
[email protected]151a63d2011-12-20 22:32:521178 GetRenderViewHost()->FilterURL(ChildProcessSecurityPolicy::GetInstance(),
[email protected]f3b1a082011-11-18 00:34:301179 GetRenderProcessHost()->GetID(), &validated_url);
[email protected]724159a2010-12-30 01:11:181180
[email protected]8093a542011-05-13 07:29:321181 RenderViewHost* rvh =
1182 render_manager_.pending_render_view_host() ?
[email protected]151a63d2011-12-20 22:32:521183 render_manager_.pending_render_view_host() : GetRenderViewHost();
[email protected]0d60f0192011-04-14 12:40:101184 // Notify observers about the start of the provisional load.
[email protected]d8c660432011-12-22 20:51:251185 FOR_EACH_OBSERVER(WebContentsObserver, observers_,
[email protected]0d60f0192011-04-14 12:40:101186 DidStartProvisionalLoadForFrame(frame_id, is_main_frame,
[email protected]8093a542011-05-13 07:29:321187 validated_url, is_error_page, rvh));
[email protected]0d60f0192011-04-14 12:40:101188
[email protected]724159a2010-12-30 01:11:181189 if (is_main_frame) {
[email protected]4850a7f2011-03-08 23:36:591190 // Notify observers about the provisional change in the main frame URL.
[email protected]d8c660432011-12-22 20:51:251191 FOR_EACH_OBSERVER(WebContentsObserver, observers_,
[email protected]57b9396c2011-10-07 19:11:591192 ProvisionalChangeToMainFrameUrl(url, opener_url));
[email protected]724159a2010-12-30 01:11:181193 }
1194}
1195
1196void TabContents::OnDidRedirectProvisionalLoad(int32 page_id,
[email protected]57b9396c2011-10-07 19:11:591197 const GURL& opener_url,
[email protected]724159a2010-12-30 01:11:181198 const GURL& source_url,
1199 const GURL& target_url) {
[email protected]18ba2b12011-04-06 16:35:491200 // TODO(creis): Remove this method and have the pre-rendering code listen to
1201 // the ResourceDispatcherHost's RESOURCE_RECEIVED_REDIRECT notification
1202 // instead. See http://crbug.com/78512.
[email protected]10f417c52011-12-28 21:04:231203 NavigationEntry* entry;
[email protected]724159a2010-12-30 01:11:181204 if (page_id == -1)
[email protected]022af742011-12-28 18:37:251205 entry = controller_.GetPendingEntry();
[email protected]724159a2010-12-30 01:11:181206 else
1207 entry = controller_.GetEntryWithPageID(GetSiteInstance(), page_id);
[email protected]36fc0392011-12-25 03:59:511208 if (!entry || entry->GetURL() != source_url)
[email protected]724159a2010-12-30 01:11:181209 return;
[email protected]e7d50892011-01-19 21:47:381210
[email protected]4850a7f2011-03-08 23:36:591211 // Notify observers about the provisional change in the main frame URL.
[email protected]d8c660432011-12-22 20:51:251212 FOR_EACH_OBSERVER(WebContentsObserver, observers_,
[email protected]eacb080b2011-05-22 19:40:261213 ProvisionalChangeToMainFrameUrl(target_url,
[email protected]57b9396c2011-10-07 19:11:591214 opener_url));
[email protected]724159a2010-12-30 01:11:181215}
1216
1217void TabContents::OnDidFailProvisionalLoadWithError(
[email protected]d7b175e2011-10-11 15:31:581218 const ViewHostMsg_DidFailProvisionalLoadWithError_Params& params) {
1219 VLOG(1) << "Failed Provisional Load: " << params.url.possibly_invalid_spec()
1220 << ", error_code: " << params.error_code
1221 << ", error_description: " << params.error_description
1222 << ", is_main_frame: " << params.is_main_frame
1223 << ", showing_repost_interstitial: " <<
1224 params.showing_repost_interstitial
1225 << ", frame_id: " << params.frame_id;
1226 GURL validated_url(params.url);
[email protected]151a63d2011-12-20 22:32:521227 GetRenderViewHost()->FilterURL(ChildProcessSecurityPolicy::GetInstance(),
[email protected]f3b1a082011-11-18 00:34:301228 GetRenderProcessHost()->GetID(), &validated_url);
[email protected]724159a2010-12-30 01:11:181229
[email protected]d7b175e2011-10-11 15:31:581230 if (net::ERR_ABORTED == params.error_code) {
[email protected]724159a2010-12-30 01:11:181231 // EVIL HACK ALERT! Ignore failed loads when we're showing interstitials.
1232 // This means that the interstitial won't be torn down properly, which is
1233 // bad. But if we have an interstitial, go back to another tab type, and
1234 // then load the same interstitial again, we could end up getting the first
1235 // interstitial's "failed" message (as a result of the cancel) when we're on
1236 // the second one.
1237 //
1238 // We can't tell this apart, so we think we're tearing down the current page
1239 // which will cause a crash later one. There is also some code in
1240 // RenderViewHostManager::RendererAbortedProvisionalLoad that is commented
1241 // out because of this problem.
1242 //
1243 // http://code.google.com/p/chromium/issues/detail?id=2855
1244 // Because this will not tear down the interstitial properly, if "back" is
1245 // back to another tab type, the interstitial will still be somewhat alive
1246 // in the previous tab type. If you navigate somewhere that activates the
1247 // tab with the interstitial again, you'll see a flash before the new load
1248 // commits of the interstitial page.
[email protected]0bfbf882011-12-22 18:19:271249 if (ShowingInterstitialPage()) {
[email protected]724159a2010-12-30 01:11:181250 LOG(WARNING) << "Discarding message during interstitial.";
1251 return;
1252 }
1253
[email protected]02102f82011-06-13 20:37:021254 // Discard our pending entry if the load canceled (e.g. if we decided to
1255 // download the file instead of load it). We do not verify that the URL
1256 // being canceled matches the pending entry's URL because they will not
1257 // match if a redirect occurred (in which case we do not want to leave a
1258 // stale redirect URL showing). This means that we also cancel the pending
1259 // entry if the user started a new navigation. As a result, the navigation
1260 // controller may not remember that a load is in progress, but the
1261 // navigation will still commit even if there is no pending entry.
[email protected]022af742011-12-28 18:37:251262 if (controller_.GetPendingEntry())
[email protected]c95fa8b2011-04-28 20:26:161263 DidCancelLoading();
[email protected]724159a2010-12-30 01:11:181264
[email protected]151a63d2011-12-20 22:32:521265 render_manager_.RendererAbortedProvisionalLoad(GetRenderViewHost());
[email protected]724159a2010-12-30 01:11:181266 }
1267
1268 // Send out a notification that we failed a provisional load with an error.
1269 ProvisionalLoadDetails details(
[email protected]d7b175e2011-10-11 15:31:581270 params.is_main_frame,
1271 controller_.IsURLInPageNavigation(validated_url),
1272 validated_url,
1273 std::string(),
1274 false,
1275 params.frame_id);
1276 details.set_error_code(params.error_code);
[email protected]724159a2010-12-30 01:11:181277
[email protected]ad50def52011-10-19 23:17:071278 content::NotificationService::current()->Notify(
[email protected]432115822011-07-10 15:52:271279 content::NOTIFICATION_FAIL_PROVISIONAL_LOAD_WITH_ERROR,
[email protected]c5eed492012-01-04 17:07:501280 content::Source<NavigationController>(&controller_),
[email protected]6c2381d2011-10-19 02:52:531281 content::Details<ProvisionalLoadDetails>(&details));
[email protected]0d60f0192011-04-14 12:40:101282
[email protected]d8c660432011-12-22 20:51:251283 FOR_EACH_OBSERVER(WebContentsObserver,
[email protected]d7b175e2011-10-11 15:31:581284 observers_,
1285 DidFailProvisionalLoad(params.frame_id,
1286 params.is_main_frame,
1287 validated_url,
1288 params.error_code,
1289 params.error_description));
[email protected]724159a2010-12-30 01:11:181290}
1291
1292void TabContents::OnDidLoadResourceFromMemoryCache(
1293 const GURL& url,
[email protected]70435962011-08-02 20:13:281294 const std::string& security_info,
1295 const std::string& http_method,
1296 ResourceType::Type resource_type) {
[email protected]28620862011-03-22 23:07:191297 base::StatsCounter cache("WebKit.CacheHit");
[email protected]724159a2010-12-30 01:11:181298 cache.Increment();
1299
1300 // Send out a notification that we loaded a resource from our memory cache.
[email protected]70d66502011-09-23 00:55:081301 int cert_id = 0;
1302 net::CertStatus cert_status = 0;
1303 int security_bits = -1;
1304 int connection_status = 0;
[email protected]724159a2010-12-30 01:11:181305 SSLManager::DeserializeSecurityInfo(security_info,
1306 &cert_id, &cert_status,
1307 &security_bits,
1308 &connection_status);
[email protected]f3b1a082011-11-18 00:34:301309 LoadFromMemoryCacheDetails details(url, GetRenderProcessHost()->GetID(),
[email protected]7a8c55e2011-02-15 08:21:161310 cert_id, cert_status);
[email protected]724159a2010-12-30 01:11:181311
[email protected]ad50def52011-10-19 23:17:071312 content::NotificationService::current()->Notify(
[email protected]432115822011-07-10 15:52:271313 content::NOTIFICATION_LOAD_FROM_MEMORY_CACHE,
[email protected]c5eed492012-01-04 17:07:501314 content::Source<NavigationController>(&controller_),
[email protected]6c2381d2011-10-19 02:52:531315 content::Details<LoadFromMemoryCacheDetails>(&details));
[email protected]724159a2010-12-30 01:11:181316}
1317
1318void TabContents::OnDidDisplayInsecureContent() {
[email protected]7f6f44c2011-12-14 13:23:381319 content::RecordAction(UserMetricsAction("SSL.DisplayedInsecureContent"));
[email protected]724159a2010-12-30 01:11:181320 displayed_insecure_content_ = true;
[email protected]cdcb1dee2012-01-04 00:46:201321 SSLManager::NotifySSLInternalStateChanged(&GetControllerImpl());
[email protected]724159a2010-12-30 01:11:181322}
1323
1324void TabContents::OnDidRunInsecureContent(
[email protected]92771112011-01-20 00:13:021325 const std::string& security_origin, const GURL& target_url) {
[email protected]9941cf52011-02-08 16:17:231326 LOG(INFO) << security_origin << " ran insecure content from "
1327 << target_url.possibly_invalid_spec();
[email protected]7f6f44c2011-12-14 13:23:381328 content::RecordAction(UserMetricsAction("SSL.RanInsecureContent"));
[email protected]ca406032011-07-19 21:53:051329 if (EndsWith(security_origin, kDotGoogleDotCom, false)) {
[email protected]7f6f44c2011-12-14 13:23:381330 content::RecordAction(
[email protected]ca406032011-07-19 21:53:051331 UserMetricsAction("SSL.RanInsecureContentGoogle"));
1332 }
[email protected]71fde352011-12-29 03:29:561333 controller_.GetSSLManager()->DidRunInsecureContent(security_origin);
[email protected]f2b58c4d2011-06-01 23:29:411334 displayed_insecure_content_ = true;
[email protected]cdcb1dee2012-01-04 00:46:201335 SSLManager::NotifySSLInternalStateChanged(&GetControllerImpl());
[email protected]724159a2010-12-30 01:11:181336}
1337
1338void TabContents::OnDocumentLoadedInFrame(int64 frame_id) {
1339 controller_.DocumentLoadedInFrame();
[email protected]d8c660432011-12-22 20:51:251340 FOR_EACH_OBSERVER(WebContentsObserver, observers_,
[email protected]0d60f0192011-04-14 12:40:101341 DocumentLoadedInFrame(frame_id));
[email protected]724159a2010-12-30 01:11:181342}
1343
[email protected]1a55c5be2011-11-29 11:36:311344void TabContents::OnDidFinishLoad(
1345 int64 frame_id,
1346 const GURL& validated_url,
1347 bool is_main_frame) {
[email protected]d8c660432011-12-22 20:51:251348 FOR_EACH_OBSERVER(WebContentsObserver, observers_,
[email protected]1a55c5be2011-11-29 11:36:311349 DidFinishLoad(frame_id, validated_url, is_main_frame));
1350}
1351
1352void TabContents::OnDidFailLoadWithError(int64 frame_id,
1353 const GURL& validated_url,
1354 bool is_main_frame,
1355 int error_code,
1356 const string16& error_description) {
[email protected]d8c660432011-12-22 20:51:251357 FOR_EACH_OBSERVER(WebContentsObserver, observers_,
[email protected]1a55c5be2011-11-29 11:36:311358 DidFailLoad(frame_id, validated_url, is_main_frame,
1359 error_code, error_description));
[email protected]724159a2010-12-30 01:11:181360}
1361
[email protected]c8f73ab2011-01-22 00:05:171362void TabContents::OnUpdateContentRestrictions(int restrictions) {
[email protected]0bfbf882011-12-22 18:19:271363 content_restrictions_ = restrictions;
1364 delegate_->ContentRestrictionsChanged(this);
[email protected]c8f73ab2011-01-22 00:05:171365}
1366
[email protected]216813952011-05-19 22:21:261367void TabContents::OnGoToEntryAtOffset(int offset) {
1368 if (!delegate_ || delegate_->OnGoToEntryOffset(offset)) {
[email protected]10f417c52011-12-28 21:04:231369 NavigationEntryImpl* entry = NavigationEntryImpl::FromNavigationEntry(
[email protected]022af742011-12-28 18:37:251370 controller_.GetEntryAtOffset(offset));
[email protected]216813952011-05-19 22:21:261371 if (!entry)
1372 return;
1373 // Note that we don't call NavigationController::GotToOffset() as we don't
1374 // want to create a pending navigation entry (it might end up lingering
1375 // http://crbug.com/51680).
[email protected]022af742011-12-28 18:37:251376 entry->SetTransitionType(
[email protected]2905f742011-10-13 03:51:581377 content::PageTransitionFromInt(
[email protected]36fc0392011-12-25 03:59:511378 entry->GetTransitionType() |
[email protected]2905f742011-10-13 03:51:581379 content::PAGE_TRANSITION_FORWARD_BACK));
[email protected]d202a7c2012-01-04 07:53:471380 NavigateToEntry(*entry, NavigationControllerImpl::NO_RELOAD);
[email protected]a13cc362011-07-28 21:29:571381
1382 // If the entry is being restored and doesn't have a SiteInstance yet, fill
1383 // it in now that we know. This allows us to find the entry when it commits.
1384 if (!entry->site_instance() &&
[email protected]10f417c52011-12-28 21:04:231385 entry->restore_type() != NavigationEntryImpl::RESTORE_NONE) {
[email protected]77362eb2011-08-01 17:18:381386 entry->set_site_instance(GetPendingSiteInstance());
[email protected]a13cc362011-07-28 21:29:571387 }
[email protected]216813952011-05-19 22:21:261388 }
1389}
1390
1391void TabContents::OnUpdateZoomLimits(int minimum_percent,
1392 int maximum_percent,
1393 bool remember) {
1394 minimum_zoom_percent_ = minimum_percent;
1395 maximum_zoom_percent_ = maximum_percent;
1396 temporary_zoom_settings_ = !remember;
1397}
1398
[email protected]0bfbf882011-12-22 18:19:271399void TabContents::OnSaveURL(const GURL& url) {
1400 DownloadManager* dlm = GetBrowserContext()->GetDownloadManager();
1401 dlm->DownloadUrl(url, GetURL(), "", this);
1402}
1403
[email protected]3a29a6e2011-08-24 18:26:211404void TabContents::OnEnumerateDirectory(int request_id,
1405 const FilePath& path) {
[email protected]6934a702011-12-20 00:04:511406 delegate_->EnumerateDirectory(this, request_id, path);
[email protected]3a29a6e2011-08-24 18:26:211407}
1408
[email protected]7d189022011-08-25 22:54:201409void TabContents::OnJSOutOfMemory() {
[email protected]6934a702011-12-20 00:04:511410 delegate_->JSOutOfMemory(this);
[email protected]7d189022011-08-25 22:54:201411}
1412
1413void TabContents::OnRegisterProtocolHandler(const std::string& protocol,
1414 const GURL& url,
1415 const string16& title) {
[email protected]6934a702011-12-20 00:04:511416 delegate_->RegisterProtocolHandler(this, protocol, url, title);
[email protected]7d189022011-08-25 22:54:201417}
1418
[email protected]b888919c2011-09-02 00:32:161419void TabContents::OnFindReply(int request_id,
1420 int number_of_matches,
1421 const gfx::Rect& selection_rect,
1422 int active_match_ordinal,
1423 bool final_update) {
[email protected]6934a702011-12-20 00:04:511424 delegate_->FindReply(this, request_id, number_of_matches, selection_rect,
1425 active_match_ordinal, final_update);
[email protected]4e6239c2011-09-23 00:11:001426 // Send a notification to the renderer that we are ready to receive more
1427 // results from the scoping effort of the Find operation. The FindInPage
1428 // scoping is asynchronous and periodically sends results back up to the
1429 // browser using IPC. In an effort to not spam the browser we have the
1430 // browser send an ACK for each FindReply message and have the renderer
1431 // queue up the latest status message while waiting for this ACK.
[email protected]151a63d2011-12-20 22:32:521432 GetRenderViewHost()->Send(
1433 new ViewMsg_FindReplyACK(GetRenderViewHost()->routing_id()));
[email protected]b888919c2011-09-02 00:32:161434}
1435
[email protected]d952a052011-09-06 18:42:451436void TabContents::OnCrashedPlugin(const FilePath& plugin_path) {
[email protected]6934a702011-12-20 00:04:511437 delegate_->CrashedPlugin(this, plugin_path);
[email protected]d952a052011-09-06 18:42:451438}
1439
[email protected]7fc4bbb2011-09-08 21:23:101440void TabContents::OnAppCacheAccessed(const GURL& manifest_url,
1441 bool blocked_by_policy) {
1442 // Notify observers about navigation.
[email protected]d8c660432011-12-22 20:51:251443 FOR_EACH_OBSERVER(WebContentsObserver, observers_,
[email protected]7fc4bbb2011-09-08 21:23:101444 AppCacheAccessed(manifest_url, blocked_by_policy));
1445}
1446
[email protected]96d185d2009-04-24 03:28:541447// Notifies the RenderWidgetHost instance about the fact that the page is
1448// loading, or done loading and calls the base implementation.
1449void TabContents::SetIsLoading(bool is_loading,
1450 LoadNotificationDetails* details) {
1451 if (is_loading == is_loading_)
1452 return;
1453
1454 if (!is_loading) {
[email protected]9c235f042011-08-10 22:28:211455 load_state_ = net::LoadStateWithParam(net::LOAD_STATE_IDLE, string16());
[email protected]96d185d2009-04-24 03:28:541456 load_state_host_.clear();
[email protected]094e5b22009-09-25 04:23:561457 upload_size_ = 0;
1458 upload_position_ = 0;
[email protected]96d185d2009-04-24 03:28:541459 }
1460
1461 render_manager_.SetIsLoading(is_loading);
1462
1463 is_loading_ = is_loading;
1464 waiting_for_response_ = is_loading;
1465
[email protected]6ebdc9b2010-09-27 16:55:571466 if (delegate_)
1467 delegate_->LoadingStateChanged(this);
[email protected]d9083482012-01-06 00:38:461468 NotifyNavigationStateChanged(content::INVALIDATE_TYPE_LOAD);
[email protected]96d185d2009-04-24 03:28:541469
[email protected]432115822011-07-10 15:52:271470 int type = is_loading ? content::NOTIFICATION_LOAD_START :
1471 content::NOTIFICATION_LOAD_STOP;
[email protected]ad50def52011-10-19 23:17:071472 content::NotificationDetails det = content::NotificationService::NoDetails();
[email protected]96d185d2009-04-24 03:28:541473 if (details)
[email protected]6c2381d2011-10-19 02:52:531474 det = content::Details<LoadNotificationDetails>(details);
[email protected]ad50def52011-10-19 23:17:071475 content::NotificationService::current()->Notify(type,
[email protected]c5eed492012-01-04 17:07:501476 content::Source<NavigationController>(&controller_),
[email protected]96d185d2009-04-24 03:28:541477 det);
1478}
1479
[email protected]420ae012009-04-24 05:16:321480void TabContents::DidNavigateMainFramePostCommit(
[email protected]8286f51a2011-05-31 17:39:131481 const content::LoadCommittedDetails& details,
[email protected]420ae012009-04-24 05:16:321482 const ViewHostMsg_FrameNavigate_Params& params) {
[email protected]1fd1a502011-03-30 16:55:561483 if (opener_web_ui_type_ != WebUI::kNoWebUI) {
[email protected]80a8fad2011-01-29 04:02:381484 // If this is a window.open navigation, use the same WebUI as the renderer
[email protected]c2e74fe82009-09-03 17:57:441485 // that opened the window, as long as both renderers have the same
1486 // privileges.
[email protected]1fd1a502011-03-30 16:55:561487 if (delegate_ && opener_web_ui_type_ == GetWebUITypeForCurrentState()) {
[email protected]d2353452012-01-19 19:53:561488 WebUIImpl* web_ui = static_cast<WebUIImpl*>(CreateWebUI(GetURL()));
[email protected]7ade2732011-02-10 00:13:581489 // web_ui might be NULL if the URL refers to a non-existent extension.
1490 if (web_ui) {
[email protected]d0980792011-02-13 19:41:401491 render_manager_.SetWebUIPostCommit(web_ui);
[email protected]151a63d2011-12-20 22:32:521492 web_ui->RenderViewCreated(GetRenderViewHost());
[email protected]c2e74fe82009-09-03 17:57:441493 }
1494 }
[email protected]1fd1a502011-03-30 16:55:561495 opener_web_ui_type_ = WebUI::kNoWebUI;
[email protected]c2e74fe82009-09-03 17:57:441496 }
1497
[email protected]4e697b042011-07-08 06:44:561498 if (details.is_navigation_to_different_page()) {
[email protected]420ae012009-04-24 05:16:321499 // Clear the status bubble. This is a workaround for a bug where WebKit
1500 // doesn't let us know that the cursor left an element during a
1501 // transition (this is also why the mouse cursor remains as a hand after
1502 // clicking on a link); see bugs 1184641 and 980803. We don't want to
1503 // clear the bubble when a user navigates to a named anchor in the same
1504 // page.
[email protected]36fc0392011-12-25 03:59:511505 UpdateTargetURL(details.entry->GetPageID(), GURL());
[email protected]420ae012009-04-24 05:16:321506 }
1507
[email protected]a6e82fc2010-02-24 22:28:141508 if (!details.is_in_page) {
[email protected]f17a0ee2010-05-17 17:38:471509 // Once the main frame is navigated, we're no longer considered to have
1510 // displayed insecure content.
1511 displayed_insecure_content_ = false;
[email protected]aece2c7f2009-08-27 20:43:171512 }
[email protected]ce5c4502009-05-06 16:46:111513
[email protected]3c9e1872010-11-18 16:17:491514 // Notify observers about navigation.
[email protected]d8c660432011-12-22 20:51:251515 FOR_EACH_OBSERVER(WebContentsObserver, observers_,
[email protected]a6e16aec2011-11-11 18:53:041516 DidNavigateMainFrame(details, params));
[email protected]420ae012009-04-24 05:16:321517}
1518
1519void TabContents::DidNavigateAnyFramePostCommit(
1520 RenderViewHost* render_view_host,
[email protected]8286f51a2011-05-31 17:39:131521 const content::LoadCommittedDetails& details,
[email protected]420ae012009-04-24 05:16:321522 const ViewHostMsg_FrameNavigate_Params& params) {
[email protected]e550f5e2012-01-11 07:22:061523 // If we navigate off the page, reset JavaScript state. This does nothing
1524 // to prevent a malicious script from spamming messages, since the script
1525 // could just reload the page to stop blocking.
1526 if (dialog_creator_ && !details.is_in_page) {
[email protected]2e5b90c2011-08-16 21:11:551527 dialog_creator_->ResetJavaScriptState(this);
1528 dialog_creator_ = NULL;
1529 }
[email protected]420ae012009-04-24 05:16:321530
[email protected]3c9e1872010-11-18 16:17:491531 // Notify observers about navigation.
[email protected]d8c660432011-12-22 20:51:251532 FOR_EACH_OBSERVER(WebContentsObserver, observers_,
[email protected]a6e16aec2011-11-11 18:53:041533 DidNavigateAnyFrame(details, params));
[email protected]420ae012009-04-24 05:16:321534}
1535
[email protected]74ce1ad2011-12-16 21:51:461536void TabContents::UpdateMaxPageIDIfNecessary(RenderViewHost* rvh) {
1537 // If we are creating a RVH for a restored controller, then we need to make
1538 // sure the RenderView starts with a next_page_id_ larger than the number
1539 // of restored entries. This must be called before the RenderView starts
1540 // navigating (to avoid a race between the browser updating max_page_id and
1541 // the renderer updating next_page_id_). Because of this, we only call this
1542 // from CreateRenderView and allow that to notify the RenderView for us.
[email protected]71fde352011-12-29 03:29:561543 int max_restored_page_id = controller_.GetMaxRestoredPageID();
[email protected]74ce1ad2011-12-16 21:51:461544 if (max_restored_page_id > GetMaxPageIDForSiteInstance(rvh->site_instance()))
1545 UpdateMaxPageIDForSiteInstance(rvh->site_instance(), max_restored_page_id);
[email protected]420ae012009-04-24 05:16:321546}
1547
[email protected]10f417c52011-12-28 21:04:231548bool TabContents::UpdateTitleForEntry(NavigationEntryImpl* entry,
[email protected]acafd272011-07-26 17:35:571549 const string16& title) {
[email protected]420ae012009-04-24 05:16:321550 // For file URLs without a title, use the pathname instead. In the case of a
1551 // synthesized title, we don't want the update to count toward the "one set
1552 // per page of the title to history."
[email protected]6b2f7a82011-04-25 19:30:511553 string16 final_title;
[email protected]420ae012009-04-24 05:16:321554 bool explicit_set;
[email protected]36fc0392011-12-25 03:59:511555 if (entry && entry->GetURL().SchemeIsFile() && title.empty()) {
1556 final_title = UTF8ToUTF16(entry->GetURL().ExtractFileName());
[email protected]420ae012009-04-24 05:16:321557 explicit_set = false; // Don't count synthetic titles toward the set limit.
1558 } else {
[email protected]acafd272011-07-26 17:35:571559 TrimWhitespace(title, TRIM_ALL, &final_title);
[email protected]420ae012009-04-24 05:16:321560 explicit_set = true;
1561 }
1562
[email protected]987fc3a2011-05-26 14:18:091563 // If a page is created via window.open and never navigated,
1564 // there will be no navigation entry. In this situation,
1565 // |page_title_when_no_navigaiton_entry_| will be used for page title.
1566 if (entry) {
[email protected]36fc0392011-12-25 03:59:511567 if (final_title == entry->GetTitle())
[email protected]987fc3a2011-05-26 14:18:091568 return false; // Nothing changed, don't bother.
[email protected]420ae012009-04-24 05:16:321569
[email protected]36fc0392011-12-25 03:59:511570 entry->SetTitle(final_title);
[email protected]987fc3a2011-05-26 14:18:091571 } else {
1572 if (page_title_when_no_navigation_entry_ == final_title)
1573 return false; // Nothing changed, don't bother.
1574
1575 page_title_when_no_navigation_entry_ = final_title;
1576 }
[email protected]420ae012009-04-24 05:16:321577
[email protected]420ae012009-04-24 05:16:321578 // Lastly, set the title for the view.
[email protected]790e2fd2011-09-21 20:28:231579 view_->SetPageTitle(final_title);
[email protected]420ae012009-04-24 05:16:321580
[email protected]105bb0f2011-05-24 17:12:141581 TitleUpdatedDetails details(entry, explicit_set);
1582
[email protected]ad50def52011-10-19 23:17:071583 content::NotificationService::current()->Notify(
[email protected]bb81f382012-01-03 22:45:441584 content::NOTIFICATION_WEB_CONTENTS_TITLE_UPDATED,
1585 content::Source<WebContents>(this),
[email protected]6c2381d2011-10-19 02:52:531586 content::Details<TitleUpdatedDetails>(&details));
[email protected]cbc0e1b2010-04-12 18:33:041587
[email protected]420ae012009-04-24 05:16:321588 return true;
1589}
1590
1591void TabContents::NotifySwapped() {
1592 // After sending out a swap notification, we need to send a disconnect
1593 // notification so that clients that pick up a pointer to |this| can NULL the
1594 // pointer. See Bug 1230284.
1595 notify_disconnection_ = true;
[email protected]ad50def52011-10-19 23:17:071596 content::NotificationService::current()->Notify(
[email protected]4ca15302012-01-03 05:53:201597 content::NOTIFICATION_WEB_CONTENTS_SWAPPED,
1598 content::Source<WebContents>(this),
[email protected]ad50def52011-10-19 23:17:071599 content::NotificationService::NoDetails());
[email protected]420ae012009-04-24 05:16:321600}
1601
1602void TabContents::NotifyConnected() {
1603 notify_disconnection_ = true;
[email protected]ad50def52011-10-19 23:17:071604 content::NotificationService::current()->Notify(
[email protected]ef9572e2012-01-04 22:14:121605 content::NOTIFICATION_WEB_CONTENTS_CONNECTED,
1606 content::Source<WebContents>(this),
[email protected]ad50def52011-10-19 23:17:071607 content::NotificationService::NoDetails());
[email protected]420ae012009-04-24 05:16:321608}
1609
1610void TabContents::NotifyDisconnected() {
1611 if (!notify_disconnection_)
1612 return;
1613
1614 notify_disconnection_ = false;
[email protected]ad50def52011-10-19 23:17:071615 content::NotificationService::current()->Notify(
[email protected]fbc5e5f92012-01-02 06:08:321616 content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED,
1617 content::Source<WebContents>(this),
[email protected]ad50def52011-10-19 23:17:071618 content::NotificationService::NoDetails());
[email protected]420ae012009-04-24 05:16:321619}
1620
[email protected]8d3347f2009-07-09 22:00:211621RenderViewHostDelegate::View* TabContents::GetViewDelegate() {
[email protected]420ae012009-04-24 05:16:321622 return view_.get();
1623}
1624
[email protected]8d3347f2009-07-09 22:00:211625RenderViewHostDelegate::RendererManagement*
1626TabContents::GetRendererManagementDelegate() {
1627 return &render_manager_;
1628}
1629
[email protected]daf82f82011-10-31 22:35:311630content::RendererPreferences TabContents::GetRendererPrefs(
[email protected]3d7474ff2011-07-27 17:47:371631 content::BrowserContext* browser_context) const {
[email protected]840b1512009-07-21 16:53:461632 return renderer_preferences_;
[email protected]80d96fa2009-06-10 22:34:511633}
1634
[email protected]57c6a652009-05-04 07:58:341635TabContents* TabContents::GetAsTabContents() {
1636 return this;
1637}
1638
[email protected]768c5472011-12-26 19:06:171639WebContents* TabContents::GetAsWebContents() {
1640 return this;
1641}
1642
[email protected]da4dfc42011-10-12 15:53:561643content::ViewType TabContents::GetRenderViewType() const {
[email protected]32ded2212011-11-10 18:51:431644 return view_type_;
[email protected]7b291f92009-08-14 05:43:531645}
1646
[email protected]420ae012009-04-24 05:16:321647void TabContents::RenderViewCreated(RenderViewHost* render_view_host) {
[email protected]ad50def52011-10-19 23:17:071648 content::NotificationService::current()->Notify(
[email protected]432115822011-07-10 15:52:271649 content::NOTIFICATION_RENDER_VIEW_HOST_CREATED_FOR_TAB,
[email protected]fbc5e5f92012-01-02 06:08:321650 content::Source<WebContents>(this),
[email protected]6c2381d2011-10-19 02:52:531651 content::Details<RenderViewHost>(render_view_host));
[email protected]10f417c52011-12-28 21:04:231652 NavigationEntry* entry = controller_.GetActiveEntry();
[email protected]420ae012009-04-24 05:16:321653 if (!entry)
1654 return;
1655
1656 // When we're creating views, we're still doing initial setup, so we always
[email protected]e0112912011-02-02 22:54:351657 // use the pending Web UI rather than any possibly existing committed one.
[email protected]1fd1a502011-03-30 16:55:561658 if (render_manager_.pending_web_ui())
[email protected]7ade2732011-02-10 00:13:581659 render_manager_.pending_web_ui()->RenderViewCreated(render_view_host);
[email protected]420ae012009-04-24 05:16:321660
1661 if (entry->IsViewSourceMode()) {
1662 // Put the renderer in view source mode.
1663 render_view_host->Send(
1664 new ViewMsg_EnableViewSourceMode(render_view_host->routing_id()));
1665 }
[email protected]0666aef2009-05-13 19:48:081666
[email protected]d487beefe2011-12-21 05:41:211667 GetView()->RenderViewCreated(render_view_host);
[email protected]11f764bb2011-05-25 19:45:261668
1669 FOR_EACH_OBSERVER(
[email protected]d8c660432011-12-22 20:51:251670 WebContentsObserver, observers_, RenderViewCreated(render_view_host));
[email protected]420ae012009-04-24 05:16:321671}
1672
1673void TabContents::RenderViewReady(RenderViewHost* rvh) {
[email protected]151a63d2011-12-20 22:32:521674 if (rvh != GetRenderViewHost()) {
[email protected]420ae012009-04-24 05:16:321675 // Don't notify the world, since this came from a renderer in the
1676 // background.
1677 return;
1678 }
1679
1680 NotifyConnected();
[email protected]be1f56ab2011-12-22 06:55:311681 bool was_crashed = IsCrashed();
[email protected]443b80e2010-12-14 00:42:231682 SetIsCrashed(base::TERMINATION_STATUS_STILL_RUNNING, 0);
[email protected]9d8a4642009-07-29 17:25:301683
1684 // Restore the focus to the tab (otherwise the focus will be on the top
1685 // window).
[email protected]484ae5912010-09-29 19:16:141686 if (was_crashed && !FocusLocationBarByDefault() &&
1687 (!delegate_ || delegate_->ShouldFocusPageAfterCrash())) {
[email protected]9d8a4642009-07-29 17:25:301688 Focus();
[email protected]484ae5912010-09-29 19:16:141689 }
[email protected]32ded2212011-11-10 18:51:431690
[email protected]d8c660432011-12-22 20:51:251691 FOR_EACH_OBSERVER(WebContentsObserver, observers_, RenderViewReady());
[email protected]420ae012009-04-24 05:16:321692}
1693
[email protected]443b80e2010-12-14 00:42:231694void TabContents::RenderViewGone(RenderViewHost* rvh,
1695 base::TerminationStatus status,
1696 int error_code) {
[email protected]151a63d2011-12-20 22:32:521697 if (rvh != GetRenderViewHost()) {
[email protected]420ae012009-04-24 05:16:321698 // The pending page's RenderViewHost is gone.
1699 return;
1700 }
1701
1702 SetIsLoading(false, NULL);
1703 NotifyDisconnected();
[email protected]443b80e2010-12-14 00:42:231704 SetIsCrashed(status, error_code);
[email protected]be1f56ab2011-12-22 06:55:311705 GetView()->OnTabCrashed(GetCrashedStatus(), crashed_error_code_);
[email protected]420ae012009-04-24 05:16:321706
[email protected]d8c660432011-12-22 20:51:251707 FOR_EACH_OBSERVER(WebContentsObserver,
[email protected]9cddb1a22011-11-15 15:04:271708 observers_,
[email protected]be1f56ab2011-12-22 06:55:311709 RenderViewGone(GetCrashedStatus()));
[email protected]420ae012009-04-24 05:16:321710}
1711
[email protected]2e4633c2009-07-09 16:58:061712void TabContents::RenderViewDeleted(RenderViewHost* rvh) {
[email protected]fb7b79f72009-11-06 18:00:481713 render_manager_.RenderViewDeleted(rvh);
[email protected]d8c660432011-12-22 20:51:251714 FOR_EACH_OBSERVER(WebContentsObserver, observers_, RenderViewDeleted(rvh));
[email protected]2e4633c2009-07-09 16:58:061715}
1716
[email protected]420ae012009-04-24 05:16:321717void TabContents::DidNavigate(RenderViewHost* rvh,
1718 const ViewHostMsg_FrameNavigate_Params& params) {
[email protected]2905f742011-10-13 03:51:581719 if (content::PageTransitionIsMainFrame(params.transition))
[email protected]420ae012009-04-24 05:16:321720 render_manager_.DidNavigateMainFrame(rvh);
[email protected]8030f012009-09-25 18:09:371721
[email protected]420ae012009-04-24 05:16:321722 // Update the site of the SiteInstance if it doesn't have one yet.
1723 if (!GetSiteInstance()->has_site())
1724 GetSiteInstance()->SetSite(params.url);
1725
1726 // Need to update MIME type here because it's referred to in
1727 // UpdateNavigationCommands() called by RendererDidNavigate() to
1728 // determine whether or not to enable the encoding menu.
1729 // It's updated only for the main frame. For a subframe,
1730 // RenderView::UpdateURL does not set params.contents_mime_type.
1731 // (see http://code.google.com/p/chromium/issues/detail?id=2929 )
1732 // TODO(jungshik): Add a test for the encoding menu to avoid
1733 // regressing it again.
[email protected]2905f742011-10-13 03:51:581734 if (content::PageTransitionIsMainFrame(params.transition))
[email protected]420ae012009-04-24 05:16:321735 contents_mime_type_ = params.contents_mime_type;
1736
[email protected]8286f51a2011-05-31 17:39:131737 content::LoadCommittedDetails details;
[email protected]93f230e02011-06-01 14:40:001738 bool did_navigate = controller_.RendererDidNavigate(params, &details);
[email protected]3e90d4a2009-07-03 17:38:391739
[email protected]a9c0bfe2010-09-17 08:35:221740 // Send notification about committed provisional loads. This notification is
1741 // different from the NAV_ENTRY_COMMITTED notification which doesn't include
1742 // the actual URL navigated to and isn't sent for AUTO_SUBFRAME navigations.
[email protected]610cbb82011-10-18 16:35:081743 if (details.type != content::NAVIGATION_TYPE_NAV_IGNORE) {
[email protected]dabb0d12010-10-05 12:50:071744 // For AUTO_SUBFRAME navigations, an event for the main frame is generated
1745 // that is not recorded in the navigation history. For the purpose of
1746 // tracking navigation events, we treat this event as a sub frame navigation
1747 // event.
1748 bool is_main_frame = did_navigate ? details.is_main_frame : false;
[email protected]2905f742011-10-13 03:51:581749 content::PageTransition transition_type = params.transition;
[email protected]a9c0bfe2010-09-17 08:35:221750 // Whether or not a page transition was triggered by going backward or
1751 // forward in the history is only stored in the navigation controller's
1752 // entry list.
1753 if (did_navigate &&
[email protected]36fc0392011-12-25 03:59:511754 (controller_.GetActiveEntry()->GetTransitionType() &
[email protected]2905f742011-10-13 03:51:581755 content::PAGE_TRANSITION_FORWARD_BACK)) {
1756 transition_type = content::PageTransitionFromInt(
1757 params.transition | content::PAGE_TRANSITION_FORWARD_BACK);
[email protected]a9c0bfe2010-09-17 08:35:221758 }
[email protected]0d60f0192011-04-14 12:40:101759 // Notify observers about the commit of the provisional load.
[email protected]d8c660432011-12-22 20:51:251760 FOR_EACH_OBSERVER(WebContentsObserver, observers_,
[email protected]0d60f0192011-04-14 12:40:101761 DidCommitProvisionalLoadForFrame(params.frame_id,
1762 is_main_frame, params.url, transition_type));
[email protected]a9c0bfe2010-09-17 08:35:221763 }
1764
[email protected]76543b92009-08-31 17:27:451765 if (!did_navigate)
1766 return; // No navigation happened.
[email protected]420ae012009-04-24 05:16:321767
1768 // DO NOT ADD MORE STUFF TO THIS FUNCTION! Your component should either listen
1769 // for the appropriate notification (best) or you can add it to
1770 // DidNavigateMainFramePostCommit / DidNavigateAnyFramePostCommit (only if
1771 // necessary, please).
1772
1773 // Run post-commit tasks.
[email protected]93f230e02011-06-01 14:40:001774 if (details.is_main_frame) {
[email protected]420ae012009-04-24 05:16:321775 DidNavigateMainFramePostCommit(details, params);
[email protected]6934a702011-12-20 00:04:511776 if (delegate_)
1777 delegate_->DidNavigateMainFramePostCommit(this);
[email protected]93f230e02011-06-01 14:40:001778 }
[email protected]420ae012009-04-24 05:16:321779 DidNavigateAnyFramePostCommit(rvh, details, params);
1780}
1781
1782void TabContents::UpdateState(RenderViewHost* rvh,
1783 int32 page_id,
1784 const std::string& state) {
[email protected]992db4c2011-05-12 15:37:151785 // Ensure that this state update comes from either the active RVH or one of
1786 // the swapped out RVHs. We don't expect to hear from any other RVHs.
[email protected]151a63d2011-12-20 22:32:521787 DCHECK(rvh == GetRenderViewHost() || render_manager_.IsSwappedOut(rvh));
[email protected]420ae012009-04-24 05:16:321788
1789 // We must be prepared to handle state updates for any page, these occur
1790 // when the user is scrolling and entering form data, as well as when we're
1791 // leaving a page, in which case our state may have already been moved to
1792 // the next page. The navigation controller will look up the appropriate
1793 // NavigationEntry and update it when it is notified via the delegate.
1794
1795 int entry_index = controller_.GetEntryIndexWithPageID(
[email protected]992db4c2011-05-12 15:37:151796 rvh->site_instance(), page_id);
[email protected]420ae012009-04-24 05:16:321797 if (entry_index < 0)
1798 return;
[email protected]10f417c52011-12-28 21:04:231799 NavigationEntry* entry = controller_.GetEntryAtIndex(entry_index);
[email protected]420ae012009-04-24 05:16:321800
[email protected]36fc0392011-12-25 03:59:511801 if (state == entry->GetContentState())
[email protected]420ae012009-04-24 05:16:321802 return; // Nothing to update.
[email protected]36fc0392011-12-25 03:59:511803 entry->SetContentState(state);
[email protected]420ae012009-04-24 05:16:321804 controller_.NotifyEntryChanged(entry, entry_index);
1805}
1806
1807void TabContents::UpdateTitle(RenderViewHost* rvh,
[email protected]acafd272011-07-26 17:35:571808 int32 page_id,
[email protected]a49e10b2011-08-01 23:57:461809 const string16& title,
1810 base::i18n::TextDirection title_direction) {
[email protected]420ae012009-04-24 05:16:321811 // If we have a title, that's a pretty good indication that we've started
1812 // getting useful data.
1813 SetNotWaitingForResponse();
1814
[email protected]151a63d2011-12-20 22:32:521815 DCHECK(rvh == GetRenderViewHost());
[email protected]10f417c52011-12-28 21:04:231816 NavigationEntryImpl* entry = controller_.GetEntryWithPageID(
1817 rvh->site_instance(), page_id);
[email protected]987fc3a2011-05-26 14:18:091818
[email protected]a49e10b2011-08-01 23:57:461819 // TODO(evan): make use of title_direction.
1820 // http://code.google.com/p/chromium/issues/detail?id=27094
[email protected]987fc3a2011-05-26 14:18:091821 if (!UpdateTitleForEntry(entry, title))
[email protected]420ae012009-04-24 05:16:321822 return;
1823
1824 // Broadcast notifications when the UI should be updated.
1825 if (entry == controller_.GetEntryAtOffset(0))
[email protected]d9083482012-01-06 00:38:461826 NotifyNavigationStateChanged(content::INVALIDATE_TYPE_TITLE);
[email protected]420ae012009-04-24 05:16:321827}
1828
[email protected]420ae012009-04-24 05:16:321829void TabContents::UpdateEncoding(RenderViewHost* render_view_host,
[email protected]41fc0322009-09-04 22:23:401830 const std::string& encoding) {
[email protected]be1f56ab2011-12-22 06:55:311831 SetEncoding(encoding);
[email protected]420ae012009-04-24 05:16:321832}
1833
1834void TabContents::UpdateTargetURL(int32 page_id, const GURL& url) {
[email protected]6934a702011-12-20 00:04:511835 if (delegate_)
1836 delegate_->UpdateTargetURL(this, page_id, url);
[email protected]420ae012009-04-24 05:16:321837}
1838
[email protected]420ae012009-04-24 05:16:321839void TabContents::Close(RenderViewHost* rvh) {
[email protected]07707302009-11-06 00:50:291840 // The UI may be in an event-tracking loop, such as between the
1841 // mouse-down and mouse-up in text selection or a button click.
1842 // Defer the close until after tracking is complete, so that we
1843 // don't free objects out from under the UI.
1844 // TODO(shess): This could probably be integrated with the
1845 // IsDoingDrag() test below. Punting for now because I need more
1846 // research to understand how this impacts platforms other than Mac.
1847 // TODO(shess): This could get more fine-grained. For instance,
1848 // closing a tab in another window while selecting text in the
1849 // current window's Omnibox should be just fine.
[email protected]d487beefe2011-12-21 05:41:211850 if (GetView()->IsEventTracking()) {
1851 GetView()->CloseTabAfterEventTracking();
[email protected]07707302009-11-06 00:50:291852 return;
1853 }
1854
[email protected]24a4d1062009-07-10 23:10:421855 // If we close the tab while we're in the middle of a drag, we'll crash.
1856 // Instead, cancel the drag and close it as soon as the drag ends.
[email protected]d487beefe2011-12-21 05:41:211857 if (GetView()->IsDoingDrag()) {
1858 GetView()->CancelDragAndCloseTab();
[email protected]24a4d1062009-07-10 23:10:421859 return;
1860 }
1861
[email protected]420ae012009-04-24 05:16:321862 // Ignore this if it comes from a RenderViewHost that we aren't showing.
[email protected]151a63d2011-12-20 22:32:521863 if (delegate_ && rvh == GetRenderViewHost())
[email protected]6934a702011-12-20 00:04:511864 delegate_->CloseContents(this);
[email protected]420ae012009-04-24 05:16:321865}
1866
[email protected]cd9ed79d2011-11-15 19:22:571867void TabContents::SwappedOut(RenderViewHost* rvh) {
[email protected]151a63d2011-12-20 22:32:521868 if (delegate_ && rvh == GetRenderViewHost())
[email protected]6934a702011-12-20 00:04:511869 delegate_->SwappedOut(this);
[email protected]cd9ed79d2011-11-15 19:22:571870}
1871
[email protected]420ae012009-04-24 05:16:321872void TabContents::RequestMove(const gfx::Rect& new_bounds) {
[email protected]6934a702011-12-20 00:04:511873 if (delegate_ && delegate_->IsPopupOrPanel(this))
1874 delegate_->MoveContents(this, new_bounds);
[email protected]420ae012009-04-24 05:16:321875}
1876
[email protected]7ab1e7d62009-10-14 23:32:011877void TabContents::DidStartLoading() {
[email protected]420ae012009-04-24 05:16:321878 SetIsLoading(true, NULL);
[email protected]3c9e1872010-11-18 16:17:491879
[email protected]6934a702011-12-20 00:04:511880 if (delegate_ && content_restrictions_) {
[email protected]c40d6232011-03-25 00:16:211881 content_restrictions_ = 0;
[email protected]6934a702011-12-20 00:04:511882 delegate_->ContentRestrictionsChanged(this);
[email protected]9e823662010-10-13 23:36:001883 }
[email protected]3c9e1872010-11-18 16:17:491884
1885 // Notify observers about navigation.
[email protected]d8c660432011-12-22 20:51:251886 FOR_EACH_OBSERVER(WebContentsObserver, observers_, DidStartLoading());
[email protected]420ae012009-04-24 05:16:321887}
1888
[email protected]7ab1e7d62009-10-14 23:32:011889void TabContents::DidStopLoading() {
[email protected]420ae012009-04-24 05:16:321890 scoped_ptr<LoadNotificationDetails> details;
1891
[email protected]10f417c52011-12-28 21:04:231892 NavigationEntry* entry = controller_.GetActiveEntry();
[email protected]420ae012009-04-24 05:16:321893 // An entry may not exist for a stop when loading an initial blank page or
1894 // if an iframe injected by script into a blank page finishes loading.
1895 if (entry) {
[email protected]420ae012009-04-24 05:16:321896 base::TimeDelta elapsed = base::TimeTicks::Now() - current_load_start_;
1897
1898 details.reset(new LoadNotificationDetails(
[email protected]36fc0392011-12-25 03:59:511899 entry->GetVirtualURL(),
1900 entry->GetTransitionType(),
[email protected]420ae012009-04-24 05:16:321901 elapsed,
1902 &controller_,
1903 controller_.GetCurrentEntryIndex()));
1904 }
1905
[email protected]420ae012009-04-24 05:16:321906 SetIsLoading(false, details.get());
[email protected]3c9e1872010-11-18 16:17:491907
1908 // Notify observers about navigation.
[email protected]d8c660432011-12-22 20:51:251909 FOR_EACH_OBSERVER(WebContentsObserver, observers_, DidStopLoading());
[email protected]420ae012009-04-24 05:16:321910}
1911
[email protected]c95fa8b2011-04-28 20:26:161912void TabContents::DidCancelLoading() {
1913 controller_.DiscardNonCommittedEntries();
1914
1915 // Update the URL display.
[email protected]d9083482012-01-06 00:38:461916 NotifyNavigationStateChanged(content::INVALIDATE_TYPE_URL);
[email protected]c95fa8b2011-04-28 20:26:161917}
1918
[email protected]1a3c3cb2010-12-16 21:03:401919void TabContents::DidChangeLoadProgress(double progress) {
[email protected]6934a702011-12-20 00:04:511920 if (delegate_)
1921 delegate_->LoadProgressChanged(progress);
[email protected]1a3c3cb2010-12-16 21:03:401922}
1923
[email protected]952a68e2011-11-17 00:36:101924void TabContents::DocumentAvailableInMainFrame(
1925 RenderViewHost* render_view_host) {
[email protected]d8c660432011-12-22 20:51:251926 FOR_EACH_OBSERVER(WebContentsObserver, observers_,
[email protected]952a68e2011-11-17 00:36:101927 DocumentAvailableInMainFrame());
1928}
1929
[email protected]25497492010-09-11 15:15:081930void TabContents::DocumentOnLoadCompletedInMainFrame(
1931 RenderViewHost* render_view_host,
1932 int32 page_id) {
[email protected]ad50def52011-10-19 23:17:071933 content::NotificationService::current()->Notify(
[email protected]432115822011-07-10 15:52:271934 content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
[email protected]fbc5e5f92012-01-02 06:08:321935 content::Source<WebContents>(this),
[email protected]6c2381d2011-10-19 02:52:531936 content::Details<int>(&page_id));
[email protected]25497492010-09-11 15:15:081937}
1938
[email protected]ae5184d62011-10-06 19:25:581939void TabContents::RequestOpenURL(const GURL& url,
[email protected]445e1042011-12-03 21:03:151940 const content::Referrer& referrer,
[email protected]ae5184d62011-10-06 19:25:581941 WindowOpenDisposition disposition,
1942 int64 source_frame_id) {
[email protected]4ad5d77d2011-12-03 02:00:481943 // Delegate to RequestTransferURL because this is just the generic
1944 // case where |old_request_id| is empty.
[email protected]bce1f1c2011-12-05 15:11:581945 RequestTransferURL(url, referrer, disposition, source_frame_id,
[email protected]4ad5d77d2011-12-03 02:00:481946 GlobalRequestID());
1947}
1948
1949void TabContents::RequestTransferURL(const GURL& url,
[email protected]bce1f1c2011-12-05 15:11:581950 const content::Referrer& referrer,
[email protected]4ad5d77d2011-12-03 02:00:481951 WindowOpenDisposition disposition,
1952 int64 source_frame_id,
1953 const GlobalRequestID& old_request_id) {
[email protected]e5d549d2011-12-28 01:29:201954 WebContents* new_contents = NULL;
[email protected]2905f742011-10-13 03:51:581955 content::PageTransition transition_type = content::PAGE_TRANSITION_LINK;
[email protected]7ade2732011-02-10 00:13:581956 if (render_manager_.web_ui()) {
[email protected]e0112912011-02-02 22:54:351957 // When we're a Web UI, it will provide a page transition type for us (this
[email protected]420ae012009-04-24 05:16:321958 // is so the new tab page can specify AUTO_BOOKMARK for automatically
1959 // generated suggestions).
1960 //
[email protected]e0112912011-02-02 22:54:351961 // Note also that we hide the referrer for Web UI pages. We don't really
[email protected]60e448982009-05-06 04:21:161962 // want web sites to see a referrer of "chrome://blah" (and some
1963 // chrome: URLs might have search terms or other stuff we don't want to
[email protected]420ae012009-04-24 05:16:321964 // send to the site), so we send no referrer.
[email protected]bce1f1c2011-12-05 15:11:581965 OpenURLParams params(url, content::Referrer(), disposition,
[email protected]c63cedf22012-01-17 18:42:221966 render_manager_.web_ui()->GetLinkTransitionType(),
[email protected]4ad5d77d2011-12-03 02:00:481967 false /* is_renderer_initiated */);
1968 params.transferred_global_request_id = old_request_id;
1969 new_contents = OpenURL(params);
[email protected]c63cedf22012-01-17 18:42:221970 transition_type = render_manager_.web_ui()->GetLinkTransitionType();
[email protected]420ae012009-04-24 05:16:321971 } else {
[email protected]4ad5d77d2011-12-03 02:00:481972 OpenURLParams params(url, referrer, disposition,
1973 content::PAGE_TRANSITION_LINK, true /* is_renderer_initiated */);
1974 params.transferred_global_request_id = old_request_id;
1975 new_contents = OpenURL(params);
[email protected]ae5184d62011-10-06 19:25:581976 }
1977 if (new_contents) {
1978 // Notify observers.
[email protected]d8c660432011-12-22 20:51:251979 FOR_EACH_OBSERVER(WebContentsObserver, observers_,
[email protected]ae5184d62011-10-06 19:25:581980 DidOpenRequestedURL(new_contents,
1981 url,
1982 referrer,
1983 disposition,
1984 transition_type,
1985 source_frame_id));
[email protected]420ae012009-04-24 05:16:321986 }
1987}
1988
[email protected]420ae012009-04-24 05:16:321989void TabContents::RunJavaScriptMessage(
[email protected]992db4c2011-05-12 15:37:151990 const RenderViewHost* rvh,
[email protected]4f5ce842011-05-27 19:34:411991 const string16& message,
1992 const string16& default_prompt,
[email protected]420ae012009-04-24 05:16:321993 const GURL& frame_url,
[email protected]269f86d2011-12-07 02:43:471994 ui::JavascriptMessageType javascript_message_type,
[email protected]420ae012009-04-24 05:16:321995 IPC::Message* reply_msg,
1996 bool* did_suppress_message) {
[email protected]3ab9cb82011-06-03 18:02:071997 // Suppress JavaScript dialogs when requested. Also suppress messages when
1998 // showing an interstitial as it's shown over the previous page and we don't
1999 // want the hidden page's dialogs to interfere with the interstitial.
[email protected]8f55e802010-12-06 18:11:502000 bool suppress_this_message =
[email protected]992db4c2011-05-12 15:37:152001 rvh->is_swapped_out() ||
[email protected]0bfbf882011-12-22 18:19:272002 ShowingInterstitialPage() ||
[email protected]3ab9cb82011-06-03 18:02:072003 !delegate_ ||
2004 delegate_->ShouldSuppressDialogs();
[email protected]420ae012009-04-24 05:16:322005
2006 if (!suppress_this_message) {
[email protected]b627d9a2011-06-28 14:06:342007 content::JavaScriptDialogCreator::TitleType title_type;
2008 string16 title;
2009
2010 if (!frame_url.has_host()) {
2011 title_type = content::JavaScriptDialogCreator::DIALOG_TITLE_NONE;
2012 } else {
2013 title_type = content::JavaScriptDialogCreator::DIALOG_TITLE_FORMATTED_URL;
2014 title = net::FormatUrl(
2015 frame_url.GetOrigin(),
[email protected]597a867b2011-11-18 18:31:202016 content::GetContentClient()->browser()->GetAcceptLangs(
[email protected]627e0512011-12-21 22:55:302017 GetBrowserContext()));
[email protected]b627d9a2011-06-28 14:06:342018 }
2019
[email protected]2e5b90c2011-08-16 21:11:552020 dialog_creator_ = delegate_->GetJavaScriptDialogCreator();
2021 dialog_creator_->RunJavaScriptDialog(this,
2022 title_type,
2023 title,
[email protected]269f86d2011-12-07 02:43:472024 javascript_message_type,
[email protected]2e5b90c2011-08-16 21:11:552025 message,
2026 default_prompt,
2027 reply_msg,
2028 &suppress_this_message);
[email protected]420ae012009-04-24 05:16:322029 }
[email protected]3ab9cb82011-06-03 18:02:072030
2031 if (suppress_this_message) {
2032 // If we are suppressing messages, just reply as if the user immediately
2033 // pressed "Cancel".
2034 OnDialogClosed(reply_msg, false, string16());
2035 }
2036
2037 *did_suppress_message = suppress_this_message;
[email protected]420ae012009-04-24 05:16:322038}
2039
[email protected]992db4c2011-05-12 15:37:152040void TabContents::RunBeforeUnloadConfirm(const RenderViewHost* rvh,
[email protected]4f5ce842011-05-27 19:34:412041 const string16& message,
[email protected]420ae012009-04-24 05:16:322042 IPC::Message* reply_msg) {
[email protected]6934a702011-12-20 00:04:512043 if (delegate_)
2044 delegate_->WillRunBeforeUnloadConfirm();
[email protected]3ab9cb82011-06-03 18:02:072045
2046 bool suppress_this_message =
2047 rvh->is_swapped_out() ||
2048 !delegate_ ||
2049 delegate_->ShouldSuppressDialogs();
[email protected]992db4c2011-05-12 15:37:152050 if (suppress_this_message) {
[email protected]151a63d2011-12-20 22:32:522051 GetRenderViewHost()->JavaScriptDialogClosed(reply_msg, true, string16());
[email protected]8f55e802010-12-06 18:11:502052 return;
2053 }
[email protected]3ab9cb82011-06-03 18:02:072054
[email protected]7ab1e7d62009-10-14 23:32:012055 is_showing_before_unload_dialog_ = true;
[email protected]2e5b90c2011-08-16 21:11:552056 dialog_creator_ = delegate_->GetJavaScriptDialogCreator();
2057 dialog_creator_->RunBeforeUnloadDialog(this,
2058 message,
2059 reply_msg);
[email protected]420ae012009-04-24 05:16:322060}
2061
[email protected]420ae012009-04-24 05:16:322062WebPreferences TabContents::GetWebkitPrefs() {
[email protected]447021c2010-09-08 21:29:082063 WebPreferences web_prefs =
[email protected]181a95ee2011-07-12 19:26:362064 content::GetContentClient()->browser()->GetWebkitPrefs(
[email protected]151a63d2011-12-20 22:32:522065 GetRenderViewHost());
[email protected]447021c2010-09-08 21:29:082066
[email protected]b8299c12011-06-03 19:52:282067 // Force accelerated compositing and 2d canvas off for chrome:, about: and
[email protected]2ef216b2011-08-01 19:25:212068 // chrome-devtools: pages (unless it's specifically allowed).
2069 if ((GetURL().SchemeIs(chrome::kChromeDevToolsScheme) ||
[email protected]30b8e0ee2011-09-12 14:45:572070 // Allow accelerated compositing for keyboard and log in screen.
[email protected]b8299c12011-06-03 19:52:282071 GetURL().SchemeIs(chrome::kChromeUIScheme) ||
[email protected]cd4a5bd22011-09-13 06:46:302072 (GetURL().SchemeIs(chrome::kAboutScheme) &&
2073 GetURL().spec() != chrome::kAboutBlankURL)) &&
[email protected]2ef216b2011-08-01 19:25:212074 !web_prefs.allow_webui_compositing) {
[email protected]447021c2010-09-08 21:29:082075 web_prefs.accelerated_compositing_enabled = false;
[email protected]9beff752010-09-22 19:35:432076 web_prefs.accelerated_2d_canvas_enabled = false;
[email protected]447021c2010-09-08 21:29:082077 }
2078
2079 return web_prefs;
[email protected]420ae012009-04-24 05:16:322080}
2081
[email protected]7d472472011-01-22 01:30:252082void TabContents::OnUserGesture() {
[email protected]ddb85052011-05-18 14:40:272083 // Notify observers.
[email protected]d8c660432011-12-22 20:51:252084 FOR_EACH_OBSERVER(WebContentsObserver, observers_, DidGetUserGesture());
[email protected]686493142011-07-15 21:47:222085
[email protected]99907362012-01-11 05:41:402086 ResourceDispatcherHost* rdh = ResourceDispatcherHost::Get();
[email protected]b39e7a88b2012-01-10 21:43:172087 if (rdh) // NULL in unittests.
2088 rdh->OnUserGesture(this);
[email protected]7d472472011-01-22 01:30:252089}
2090
[email protected]fa1cf0b82010-01-15 21:49:442091void TabContents::OnIgnoredUIEvent() {
[email protected]31145092011-09-30 01:49:442092 // Notify observers.
[email protected]d8c660432011-12-22 20:51:252093 FOR_EACH_OBSERVER(WebContentsObserver, observers_, DidGetIgnoredUIEvent());
[email protected]fa1cf0b82010-01-15 21:49:442094}
2095
[email protected]420ae012009-04-24 05:16:322096void TabContents::RendererUnresponsive(RenderViewHost* rvh,
2097 bool is_during_unload) {
[email protected]992db4c2011-05-12 15:37:152098 // Don't show hung renderer dialog for a swapped out RVH.
[email protected]151a63d2011-12-20 22:32:522099 if (rvh != GetRenderViewHost())
[email protected]992db4c2011-05-12 15:37:152100 return;
2101
[email protected]e5fc1632011-08-08 07:51:532102 // Ignore renderer unresponsive event if debugger is attached to the tab
2103 // since the event may be a result of the renderer sitting on a breakpoint.
2104 // See http://crbug.com/65458
[email protected]0e12d7d2011-12-01 16:21:442105 DevToolsAgentHost* agent =
2106 content::DevToolsAgentHostRegistry::GetDevToolsAgentHost(rvh);
2107 if (agent &&
2108 DevToolsManagerImpl::GetInstance()->GetDevToolsClientHostFor(agent))
[email protected]e5fc1632011-08-08 07:51:532109 return;
2110
[email protected]420ae012009-04-24 05:16:322111 if (is_during_unload) {
2112 // Hang occurred while firing the beforeunload/unload handler.
2113 // Pretend the handler fired so tab closing continues as if it had.
[email protected]829e7612009-04-25 01:15:112114 rvh->set_sudden_termination_allowed(true);
[email protected]420ae012009-04-24 05:16:322115
2116 if (!render_manager_.ShouldCloseTabOnUnresponsiveRenderer())
2117 return;
2118
2119 // If the tab hangs in the beforeunload/unload handler there's really
2120 // nothing we can do to recover. Pretend the unload listeners have
2121 // all fired and close the tab. If the hang is in the beforeunload handler
2122 // then the user will not have the option of cancelling the close.
2123 Close(rvh);
2124 return;
2125 }
2126
[email protected]151a63d2011-12-20 22:32:522127 if (!GetRenderViewHost() || !GetRenderViewHost()->IsRenderViewLive())
[email protected]55452902011-06-01 21:57:472128 return;
2129
[email protected]6934a702011-12-20 00:04:512130 if (delegate_)
2131 delegate_->RendererUnresponsive(this);
[email protected]420ae012009-04-24 05:16:322132}
2133
2134void TabContents::RendererResponsive(RenderViewHost* render_view_host) {
[email protected]6934a702011-12-20 00:04:512135 if (delegate_)
2136 delegate_->RendererResponsive(this);
[email protected]420ae012009-04-24 05:16:322137}
2138
2139void TabContents::LoadStateChanged(const GURL& url,
[email protected]9c235f042011-08-10 22:28:212140 const net::LoadStateWithParam& load_state,
[email protected]094e5b22009-09-25 04:23:562141 uint64 upload_position,
2142 uint64 upload_size) {
[email protected]420ae012009-04-24 05:16:322143 load_state_ = load_state;
[email protected]094e5b22009-09-25 04:23:562144 upload_position_ = upload_position;
2145 upload_size_ = upload_size;
[email protected]04866c42011-05-03 20:03:502146 load_state_host_ = net::IDNToUnicode(url.host(),
[email protected]597a867b2011-11-18 18:31:202147 content::GetContentClient()->browser()->GetAcceptLangs(
[email protected]627e0512011-12-21 22:55:302148 GetBrowserContext()));
[email protected]9c235f042011-08-10 22:28:212149 if (load_state_.state == net::LOAD_STATE_READING_RESPONSE)
[email protected]420ae012009-04-24 05:16:322150 SetNotWaitingForResponse();
[email protected]d9083482012-01-06 00:38:462151 if (IsLoading()) {
2152 NotifyNavigationStateChanged(
2153 content::INVALIDATE_TYPE_LOAD | content::INVALIDATE_TYPE_TAB);
2154 }
[email protected]420ae012009-04-24 05:16:322155}
2156
[email protected]7d472472011-01-22 01:30:252157void TabContents::WorkerCrashed() {
[email protected]6934a702011-12-20 00:04:512158 if (delegate_)
2159 delegate_->WorkerCrashed(this);
[email protected]7d472472011-01-22 01:30:252160}
2161
[email protected]420ae012009-04-24 05:16:322162void TabContents::BeforeUnloadFiredFromRenderManager(
2163 bool proceed,
2164 bool* proceed_to_fire_unload) {
[email protected]6934a702011-12-20 00:04:512165 if (delegate_)
2166 delegate_->BeforeUnloadFired(this, proceed, proceed_to_fire_unload);
[email protected]420ae012009-04-24 05:16:322167}
2168
[email protected]3a3d47472010-07-15 21:03:542169void TabContents::DidStartLoadingFromRenderManager(
2170 RenderViewHost* render_view_host) {
2171 DidStartLoading();
2172}
2173
2174void TabContents::RenderViewGoneFromRenderManager(
2175 RenderViewHost* render_view_host) {
[email protected]443b80e2010-12-14 00:42:232176 DCHECK(crashed_status_ != base::TERMINATION_STATUS_STILL_RUNNING);
2177 RenderViewGone(render_view_host, crashed_status_, crashed_error_code_);
[email protected]3a3d47472010-07-15 21:03:542178}
2179
[email protected]420ae012009-04-24 05:16:322180void TabContents::UpdateRenderViewSizeForRenderManager() {
[email protected]8643e6d2012-01-18 20:26:102181 // TODO(brettw) this is a hack. See WebContentsView::SizeContents.
[email protected]0323ee42010-02-17 22:03:262182 gfx::Size size = view_->GetContainerSize();
2183 // 0x0 isn't a valid window size (minimal window size is 1x1) but it may be
2184 // here during container initialization and normal window size will be set
2185 // later. In case of tab duplication this resizing to 0x0 prevents setting
2186 // normal size later so just ignore it.
2187 if (!size.IsEmpty())
2188 view_->SizeContents(size);
[email protected]420ae012009-04-24 05:16:322189}
2190
[email protected]3a3d47472010-07-15 21:03:542191void TabContents::NotifySwappedFromRenderManager() {
2192 NotifySwapped();
2193}
2194
[email protected]d202a7c2012-01-04 07:53:472195NavigationControllerImpl& TabContents::GetControllerForRenderManager() {
[email protected]cdcb1dee2012-01-04 00:46:202196 return GetControllerImpl();
[email protected]3a3d47472010-07-15 21:03:542197}
2198
[email protected]d2353452012-01-19 19:53:562199WebUIImpl* TabContents::CreateWebUIForRenderManager(const GURL& url) {
2200 return static_cast<WebUIImpl*>(CreateWebUI(url));
[email protected]420ae012009-04-24 05:16:322201}
2202
[email protected]10f417c52011-12-28 21:04:232203NavigationEntry*
2204 TabContents::GetLastCommittedNavigationEntryForRenderManager() {
[email protected]420ae012009-04-24 05:16:322205 return controller_.GetLastCommittedEntry();
2206}
2207
2208bool TabContents::CreateRenderViewForRenderManager(
2209 RenderViewHost* render_view_host) {
[email protected]245f7d52011-11-28 15:36:442210 // Can be NULL during tests.
[email protected]420ae012009-04-24 05:16:322211 RenderWidgetHostView* rwh_view = view_->CreateViewForWidget(render_view_host);
[email protected]1a98a932009-11-17 00:12:522212
[email protected]420ae012009-04-24 05:16:322213 // Now that the RenderView has been created, we need to tell it its size.
[email protected]245f7d52011-11-28 15:36:442214 if (rwh_view)
2215 rwh_view->SetSize(view_->GetContainerSize());
[email protected]420ae012009-04-24 05:16:322216
[email protected]74ce1ad2011-12-16 21:51:462217 // Make sure we use the correct starting page_id in the new RenderView.
2218 UpdateMaxPageIDIfNecessary(render_view_host);
2219 int32 max_page_id =
2220 GetMaxPageIDForSiteInstance(render_view_host->site_instance());
2221
2222 if (!render_view_host->CreateRenderView(string16(), max_page_id))
[email protected]a4127722011-04-27 23:13:522223 return false;
2224
[email protected]e60c0232011-11-11 19:56:352225#if defined(OS_LINUX) || defined(OS_OPENBSD)
[email protected]f8233cc2011-05-31 20:24:502226 // Force a ViewMsg_Resize to be sent, needed to make plugins show up on
2227 // linux. See crbug.com/83941.
[email protected]245f7d52011-11-28 15:36:442228 if (rwh_view) {
2229 if (RenderWidgetHost* render_widget_host = rwh_view->GetRenderWidgetHost())
2230 render_widget_host->WasResized();
2231 }
[email protected]f8233cc2011-05-31 20:24:502232#endif
2233
[email protected]420ae012009-04-24 05:16:322234 return true;
2235}
2236
[email protected]3ab9cb82011-06-03 18:02:072237void TabContents::OnDialogClosed(IPC::Message* reply_msg,
2238 bool success,
2239 const string16& user_input) {
[email protected]beb440c2009-11-06 04:08:542240 if (is_showing_before_unload_dialog_ && !success) {
2241 // If a beforeunload dialog is canceled, we need to stop the throbber from
2242 // spinning, since we forced it to start spinning in Navigate.
2243 DidStopLoading();
2244
2245 tab_close_start_time_ = base::TimeTicks();
2246 }
2247 is_showing_before_unload_dialog_ = false;
[email protected]151a63d2011-12-20 22:32:522248 GetRenderViewHost()->JavaScriptDialogClosed(reply_msg, success, user_input);
[email protected]beb440c2009-11-06 04:08:542249}
2250
[email protected]0b08add2011-11-29 03:27:062251gfx::NativeWindow TabContents::GetDialogRootWindow() const {
[email protected]3ab9cb82011-06-03 18:02:072252 return view_->GetTopLevelNativeWindow();
[email protected]beb440c2009-11-06 04:08:542253}
2254
[email protected]a1e97f02011-06-30 14:04:342255void TabContents::OnDialogShown() {
2256 Activate();
[email protected]3a3d47472010-07-15 21:03:542257}
2258
[email protected]be1f56ab2011-12-22 06:55:312259void TabContents::SetEncoding(const std::string& encoding) {
[email protected]763ec4ca2011-04-29 15:48:122260 encoding_ = content::GetContentClient()->browser()->
2261 GetCanonicalEncodingNameByAliasName(encoding);
[email protected]aacd7cc2009-09-02 14:51:102262}
[email protected]f45d2a72010-03-08 23:28:352263
[email protected]33f74972010-12-08 16:40:362264void TabContents::CreateViewAndSetSizeForRVH(RenderViewHost* rvh) {
[email protected]d487beefe2011-12-21 05:41:212265 RenderWidgetHostView* rwh_view = GetView()->CreateViewForWidget(rvh);
[email protected]245f7d52011-11-28 15:36:442266 // Can be NULL during tests.
2267 if (rwh_view)
[email protected]d487beefe2011-12-21 05:41:212268 rwh_view->SetSize(GetView()->GetContainerSize());
[email protected]33f74972010-12-08 16:40:362269}