blob: e695633eec68b801ac856f38819c68ecd15878cc [file] [log] [blame]
[email protected]7e7414ae2010-01-26 20:19:291// Copyright (c) 2010 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]f3ec7742009-01-15 00:59:165#include "chrome/browser/tab_contents/tab_contents.h"
initial.commit09911bf2008-07-26 23:55:296
[email protected]b75b8292010-10-01 07:28:257#include <cmath>
8
[email protected]a92b8642009-05-05 23:38:569#include "app/l10n_util.h"
[email protected]9929da92009-05-05 02:05:1110#include "app/resource_bundle.h"
[email protected]39553442010-09-09 00:01:5511#if defined(OS_MACOSX)
12#include "app/surface/io_surface_support_mac.h"
13#endif
[email protected]614519812010-03-19 08:20:5614#include "app/text_elider.h"
[email protected]8cc8d492010-02-02 10:40:4915#include "base/auto_reset.h"
[email protected]420ae012009-04-24 05:16:3216#include "base/file_version_info.h"
[email protected]7e4468d52010-09-22 19:42:0017#include "base/histogram.h"
[email protected]7cf1b6ce2010-03-20 06:37:0118#include "base/i18n/rtl.h"
[email protected]420ae012009-04-24 05:16:3219#include "base/process_util.h"
[email protected]96d185d2009-04-24 03:28:5420#include "base/string16.h"
[email protected]996fd702009-09-04 19:12:3721#include "base/string_util.h"
[email protected]440b37b22010-08-30 05:31:4022#include "base/utf_string_conversions.h"
[email protected]96d185d2009-04-24 03:28:5423#include "base/time.h"
[email protected]6db0def92010-03-02 19:55:4524#include "chrome/browser/autocomplete_history_manager.h"
[email protected]21674df2009-10-28 19:51:2125#include "chrome/browser/autofill/autofill_manager.h"
[email protected]aad51d1c2010-08-05 08:38:0926#include "chrome/browser/blocked_plugin_manager.h"
[email protected]66ba4932009-06-04 19:22:1327#include "chrome/browser/blocked_popup_container.h"
[email protected]420ae012009-04-24 05:16:3228#include "chrome/browser/bookmarks/bookmark_model.h"
[email protected]96d185d2009-04-24 03:28:5429#include "chrome/browser/browser_process.h"
[email protected]cf68b092010-01-15 20:05:5530#include "chrome/browser/browser_shutdown.h"
initial.commit09911bf2008-07-26 23:55:2931#include "chrome/browser/cert_store.h"
[email protected]aacd7cc2009-09-02 14:51:1032#include "chrome/browser/character_encoding.h"
[email protected]96d185d2009-04-24 03:28:5433#include "chrome/browser/debugger/devtools_manager.h"
[email protected]c8f74942010-09-03 10:04:1434#include "chrome/browser/defaults.h"
[email protected]420ae012009-04-24 05:16:3235#include "chrome/browser/dom_operation_notification_details.h"
[email protected]96d185d2009-04-24 03:28:5436#include "chrome/browser/dom_ui/dom_ui.h"
37#include "chrome/browser/dom_ui/dom_ui_factory.h"
[email protected]bcef0dc02009-02-28 00:35:0238#include "chrome/browser/download/download_item_model.h"
[email protected]420ae012009-04-24 05:16:3239#include "chrome/browser/download/download_manager.h"
[email protected]41291322010-07-15 17:09:0140#include "chrome/browser/download/download_request_limiter.h"
[email protected]e7eaedde2009-09-25 20:09:4941#include "chrome/browser/external_protocol_handler.h"
[email protected]92c6f9b92009-10-24 04:35:0842#include "chrome/browser/extensions/extensions_service.h"
[email protected]ec0b6c42010-08-26 03:16:5843#include "chrome/browser/history/history_types.h"
[email protected]523623c2010-05-19 16:03:4244#include "chrome/browser/history/top_sites.h"
[email protected]b75b8292010-10-01 07:28:2545#include "chrome/browser/host_zoom_map.h"
[email protected]0189bc722009-08-28 21:56:4846#include "chrome/browser/favicon_service.h"
[email protected]ba70d082010-09-10 16:54:4947#include "chrome/browser/file_select_helper.h"
[email protected]e5d2f7132010-04-09 18:13:5348#include "chrome/browser/find_bar_state.h"
[email protected]f7578f52010-08-30 22:22:4949#include "chrome/browser/google/google_util.h"
[email protected]79580c62010-02-02 02:36:2550#include "chrome/browser/host_content_settings_map.h"
[email protected]8897c382009-05-06 17:53:2651#include "chrome/browser/hung_renderer_dialog.h"
[email protected]6ee12c42010-09-14 09:36:0752#include "chrome/browser/in_process_webkit/session_storage_namespace.h"
[email protected]12f74a92010-02-05 22:32:1453#include "chrome/browser/message_box_handler.h"
[email protected]420ae012009-04-24 05:16:3254#include "chrome/browser/load_from_memory_cache_details.h"
55#include "chrome/browser/load_notification_details.h"
[email protected]84abba62009-10-07 17:01:4456#include "chrome/browser/metrics/metric_event_duration_details.h"
[email protected]ea0e80892009-08-22 00:36:0557#include "chrome/browser/modal_html_dialog_delegate.h"
[email protected]c8865482009-07-23 20:40:1058#include "chrome/browser/omnibox_search_hint.h"
[email protected]fdd61c62009-04-22 19:22:5759#include "chrome/browser/password_manager/password_manager.h"
[email protected]14a000d2010-04-29 21:44:2460#include "chrome/browser/platform_util.h"
[email protected]fdd61c62009-04-22 19:22:5761#include "chrome/browser/plugin_installer.h"
[email protected]37858e52010-08-26 00:22:0262#include "chrome/browser/prefs/pref_service.h"
[email protected]12802702010-07-09 19:43:0963#include "chrome/browser/printing/print_view_manager.h"
[email protected]ce560f82009-06-03 09:39:4464#include "chrome/browser/profile.h"
[email protected]1db6ff152009-10-12 15:32:0765#include "chrome/browser/renderer_host/render_process_host.h"
[email protected]8cb5d5b2010-02-09 11:36:1666#include "chrome/browser/renderer_host/render_view_host.h"
[email protected]96d185d2009-04-24 03:28:5467#include "chrome/browser/renderer_host/render_widget_host_view.h"
[email protected]fd694982009-07-03 17:32:3768#include "chrome/browser/renderer_host/resource_request_details.h"
[email protected]1db6ff152009-10-12 15:32:0769#include "chrome/browser/renderer_host/site_instance.h"
[email protected]96d185d2009-04-24 03:28:5470#include "chrome/browser/renderer_host/web_cache_manager.h"
[email protected]93623c5d2009-12-10 21:40:3271#include "chrome/browser/renderer_preferences_util.h"
[email protected]8b62334b2010-08-31 22:37:1172#include "chrome/browser/search_engines/template_url.h"
[email protected]152b8ba32010-03-29 19:40:1673#include "chrome/browser/search_engines/template_url_fetcher.h"
[email protected]0b5b85c2010-10-11 23:00:1274#include "chrome/browser/search_engines/template_url_fetcher_ui_callbacks.h"
[email protected]152b8ba32010-03-29 19:40:1675#include "chrome/browser/search_engines/template_url_model.h"
[email protected]c37e3b62010-01-22 00:15:1776#include "chrome/browser/sessions/session_types.h"
[email protected]bd1ad682009-05-15 22:19:1777#include "chrome/browser/tab_contents/infobar_delegate.h"
[email protected]7e383692009-06-12 19:14:5478#include "chrome/browser/tab_contents/interstitial_page.h"
[email protected]f3ec7742009-01-15 00:59:1679#include "chrome/browser/tab_contents/navigation_entry.h"
[email protected]de34a962009-06-26 23:22:4380#include "chrome/browser/tab_contents/provisional_load_details.h"
[email protected]f3ec7742009-01-15 00:59:1681#include "chrome/browser/tab_contents/tab_contents_delegate.h"
[email protected]1f18184a2010-07-21 19:34:4982#include "chrome/browser/tab_contents/tab_contents_ssl_helper.h"
[email protected]fdd61c62009-04-22 19:22:5783#include "chrome/browser/tab_contents/tab_contents_view.h"
[email protected]58dca552009-06-17 00:35:0284#include "chrome/browser/tab_contents/thumbnail_generator.h"
[email protected]152b8ba32010-03-29 19:40:1685#include "chrome/browser/translate/page_translated_details.h"
[email protected]54ec6472010-04-09 19:39:5886#include "chrome/common/bindings_policy.h"
[email protected]35f7d212009-04-29 21:19:2787#include "chrome/common/chrome_switches.h"
[email protected]3b355642010-02-05 16:01:4988#include "chrome/common/extensions/extension.h"
[email protected]5d246db22009-10-27 06:17:5789#include "chrome/common/extensions/extension_action.h"
[email protected]807871f2010-09-16 01:04:4890#include "chrome/common/extensions/extension_icon_set.h"
[email protected]942690b132010-05-11 06:42:1491#include "chrome/common/extensions/extension_resource.h"
[email protected]12802702010-07-09 19:43:0992#include "chrome/common/extensions/url_pattern.h"
93#include "chrome/common/navigation_types.h"
94#include "chrome/common/net/url_request_context_getter.h"
[email protected]bfd04a62009-02-01 18:16:5695#include "chrome/common/notification_service.h"
initial.commit09911bf2008-07-26 23:55:2996#include "chrome/common/pref_names.h"
[email protected]420ae012009-04-24 05:16:3297#include "chrome/common/render_messages.h"
[email protected]939856a2010-08-24 20:29:0298#include "chrome/common/render_messages_params.h"
[email protected]1ee614862009-07-06 20:29:1899#include "chrome/common/renderer_preferences.h"
[email protected]96d185d2009-04-24 03:28:54100#include "chrome/common/url_constants.h"
[email protected]ea68c06a2010-04-23 17:25:37101#include "grit/chromium_strings.h"
[email protected]8897c382009-05-06 17:53:26102#include "grit/generated_resources.h"
[email protected]420ae012009-04-24 05:16:32103#include "grit/locale_settings.h"
[email protected]fd626782010-01-22 05:26:06104#include "grit/platform_locale_settings.h"
[email protected]ea68c06a2010-04-23 17:25:37105#include "grit/theme_resources.h"
[email protected]420ae012009-04-24 05:16:32106#include "net/base/mime_util.h"
107#include "net/base/net_errors.h"
[email protected]d686e812009-06-03 19:10:29108#include "net/base/net_util.h"
[email protected]420ae012009-04-24 05:16:32109#include "net/base/registry_controlled_domain.h"
[email protected]b75b8292010-10-01 07:28:25110#include "third_party/WebKit/WebKit/chromium/public/WebView.h"
[email protected]1ee614862009-07-06 20:29:18111#include "webkit/glue/webpreferences.h"
[email protected]d5e311b2010-07-20 17:15:03112#include "webkit/glue/password_form.h"
[email protected]3e45ba92009-02-20 21:09:00113
[email protected]420ae012009-04-24 05:16:32114// Cross-Site Navigations
115//
116// If a TabContents is told to navigate to a different web site (as determined
117// by SiteInstance), it will replace its current RenderViewHost with a new
118// RenderViewHost dedicated to the new SiteInstance. This works as follows:
119//
120// - Navigate determines whether the destination is cross-site, and if so,
121// it creates a pending_render_view_host_ and moves into the PENDING
122// RendererState.
123// - The pending RVH is "suspended," so that no navigation messages are sent to
124// its renderer until the onbeforeunload JavaScript handler has a chance to
125// run in the current RVH.
126// - The pending RVH tells CrossSiteRequestManager (a thread-safe singleton)
127// that it has a pending cross-site request. ResourceDispatcherHost will
128// check for this when the response arrives.
129// - The current RVH runs its onbeforeunload handler. If it returns false, we
130// cancel all the pending logic and go back to NORMAL. Otherwise we allow
131// the pending RVH to send the navigation request to its renderer.
132// - ResourceDispatcherHost receives a ResourceRequest on the IO thread. It
133// checks CrossSiteRequestManager to see that the RVH responsible has a
134// pending cross-site request, and then installs a CrossSiteEventHandler.
135// - When RDH receives a response, the BufferedEventHandler determines whether
136// it is a download. If so, it sends a message to the new renderer causing
137// it to cancel the request, and the download proceeds in the download
138// thread. For now, we stay in a PENDING state (with a pending RVH) until
[email protected]57c6a652009-05-04 07:58:34139// the next DidNavigate event for this TabContents. This isn't ideal, but it
[email protected]420ae012009-04-24 05:16:32140// doesn't affect any functionality.
141// - After RDH receives a response and determines that it is safe and not a
142// download, it pauses the response to first run the old page's onunload
143// handler. It does this by asynchronously calling the OnCrossSiteResponse
[email protected]57c6a652009-05-04 07:58:34144// method of TabContents on the UI thread, which sends a ClosePage message
[email protected]420ae012009-04-24 05:16:32145// to the current RVH.
146// - Once the onunload handler is finished, a ClosePage_ACK message is sent to
147// the ResourceDispatcherHost, who unpauses the response. Data is then sent
148// to the pending RVH.
149// - The pending renderer sends a FrameNavigate message that invokes the
150// DidNavigate method. This replaces the current RVH with the
151// pending RVH and goes back to the NORMAL RendererState.
152
153namespace {
154
155// Amount of time we wait between when a key event is received and the renderer
156// is queried for its state and pushed to the NavigationEntry.
157const int kQueryStateDelay = 5000;
158
[email protected]6ebdc9b2010-09-27 16:55:57159const int kSyncWaitDelay = 40;
160
[email protected]420ae012009-04-24 05:16:32161// If another javascript message box is displayed within
162// kJavascriptMessageExpectedDelay of a previous javascript message box being
163// dismissed, display an option to suppress future message boxes from this
164// contents.
165const int kJavascriptMessageExpectedDelay = 1000;
166
[email protected]420ae012009-04-24 05:16:32167// The list of prefs we want to observe.
[email protected]57ecc4b2010-08-11 03:02:51168const char* kPrefsToObserve[] = {
[email protected]420ae012009-04-24 05:16:32169 prefs::kAlternateErrorPagesEnabled,
170 prefs::kWebKitJavaEnabled,
171 prefs::kWebKitJavascriptEnabled,
172 prefs::kWebKitLoadsImagesAutomatically,
173 prefs::kWebKitPluginsEnabled,
174 prefs::kWebKitUsesUniversalDetector,
175 prefs::kWebKitSerifFontFamily,
176 prefs::kWebKitSansSerifFontFamily,
177 prefs::kWebKitFixedFontFamily,
178 prefs::kWebKitDefaultFontSize,
179 prefs::kWebKitDefaultFixedFontSize,
[email protected]1661a3c02010-05-20 16:32:36180 prefs::kWebkitTabsToLinks,
[email protected]420ae012009-04-24 05:16:32181 prefs::kDefaultCharset
182 // kWebKitStandardFontIsSerif needs to be added
183 // if we let users pick which font to use, serif or sans-serif when
184 // no font is specified or a CSS generic family (serif or sans-serif)
185 // is not specified.
186};
187
188const int kPrefsToObserveLength = arraysize(kPrefsToObserve);
189
[email protected]420ae012009-04-24 05:16:32190// Returns true if the entry's transition type is FORM_SUBMIT.
191bool IsFormSubmit(const NavigationEntry* entry) {
192 return (PageTransition::StripQualifier(entry->transition_type()) ==
193 PageTransition::FORM_SUBMIT);
194}
195
196#if defined(OS_WIN)
197
198BOOL CALLBACK InvalidateWindow(HWND hwnd, LPARAM lparam) {
199 // Note: erase is required to properly paint some widgets borders. This can
200 // be seen with textfields.
201 InvalidateRect(hwnd, NULL, TRUE);
202 return TRUE;
203}
204#endif
205
[email protected]5e369672009-11-03 23:48:30206ViewMsg_Navigate_Params::NavigationType GetNavigationType(
[email protected]1ccb3568d2010-02-19 10:51:16207 Profile* profile, const NavigationEntry& entry,
208 NavigationController::ReloadType reload_type) {
209 switch (reload_type) {
210 case NavigationController::RELOAD:
211 return ViewMsg_Navigate_Params::RELOAD;
212 case NavigationController::RELOAD_IGNORING_CACHE:
213 return ViewMsg_Navigate_Params::RELOAD_IGNORING_CACHE;
214 case NavigationController::NO_RELOAD:
215 break; // Fall through to rest of function.
216 }
[email protected]5e369672009-11-03 23:48:30217
218 if (entry.restore_type() == NavigationEntry::RESTORE_LAST_SESSION &&
219 profile->DidLastSessionExitCleanly())
220 return ViewMsg_Navigate_Params::RESTORE;
221
222 return ViewMsg_Navigate_Params::NORMAL;
223}
224
[email protected]876bc832010-09-07 16:29:54225void MakeNavigateParams(const NavigationEntry& entry,
226 const NavigationController& controller,
[email protected]1ccb3568d2010-02-19 10:51:16227 NavigationController::ReloadType reload_type,
228 ViewMsg_Navigate_Params* params) {
[email protected]056de2d2009-06-26 16:41:34229 params->page_id = entry.page_id();
[email protected]876bc832010-09-07 16:29:54230 params->pending_history_list_offset = controller.GetIndexOfEntry(&entry);
[email protected]3cc72b12010-03-18 23:03:00231 params->current_history_list_offset = controller.last_committed_entry_index();
232 params->current_history_list_length = controller.entry_count();
[email protected]056de2d2009-06-26 16:41:34233 params->url = entry.url();
234 params->referrer = entry.referrer();
235 params->transition = entry.transition_type();
236 params->state = entry.content_state();
[email protected]3cc72b12010-03-18 23:03:00237 params->navigation_type =
238 GetNavigationType(controller.profile(), entry, reload_type);
[email protected]056de2d2009-06-26 16:41:34239 params->request_time = base::Time::Now();
240}
241
[email protected]851b1eb2010-08-09 13:32:29242class DisabledPluginInfoBar : public ConfirmInfoBarDelegate {
243 public:
244 DisabledPluginInfoBar(TabContents* tab_contents,
245 const string16& name,
246 const GURL& update_url)
247 : ConfirmInfoBarDelegate(tab_contents),
248 tab_contents_(tab_contents),
249 name_(name),
250 update_url_(update_url) {
251 tab_contents->AddInfoBar(this);
252 }
253
254 virtual int GetButtons() const {
255 return BUTTON_OK | BUTTON_CANCEL | BUTTON_OK_DEFAULT;
256 }
257
[email protected]e23d3a32010-08-13 19:39:58258 virtual string16 GetButtonLabel(InfoBarButton button) const {
[email protected]851b1eb2010-08-09 13:32:29259 if (button == BUTTON_CANCEL)
[email protected]e23d3a32010-08-13 19:39:58260 return l10n_util::GetStringUTF16(IDS_PLUGIN_ENABLE_TEMPORARILY);
[email protected]851b1eb2010-08-09 13:32:29261 if (button == BUTTON_OK)
[email protected]e23d3a32010-08-13 19:39:58262 return l10n_util::GetStringUTF16(IDS_PLUGIN_UPDATE);
[email protected]851b1eb2010-08-09 13:32:29263 return ConfirmInfoBarDelegate::GetButtonLabel(button);
264 }
265
[email protected]e23d3a32010-08-13 19:39:58266 virtual string16 GetMessageText() const {
267 return l10n_util::GetStringFUTF16(IDS_PLUGIN_OUTDATED_PROMPT, name_);
[email protected]851b1eb2010-08-09 13:32:29268 }
269
[email protected]e23d3a32010-08-13 19:39:58270 virtual string16 GetLinkText() {
271 return l10n_util::GetStringUTF16(IDS_LEARN_MORE);
[email protected]851b1eb2010-08-09 13:32:29272 }
273
274 virtual SkBitmap* GetIcon() const {
275 return ResourceBundle::GetSharedInstance().GetBitmapNamed(
276 IDR_INFOBAR_PLUGIN_INSTALL);
277 }
278
279 virtual bool Accept() {
280 tab_contents_->OpenURL(update_url_, GURL(),
[email protected]57b66d02010-09-30 11:24:51281 NEW_FOREGROUND_TAB, PageTransition::LINK);
[email protected]851b1eb2010-08-09 13:32:29282 return false;
283 }
284
285 virtual bool Cancel() {
286 tab_contents_->OpenURL(GURL(chrome::kChromeUIPluginsURL), GURL(),
[email protected]57b66d02010-09-30 11:24:51287 NEW_FOREGROUND_TAB, PageTransition::LINK);
[email protected]851b1eb2010-08-09 13:32:29288 return false;
289 }
290
291 virtual bool LinkClicked(WindowOpenDisposition disposition) {
292 // TODO(bauerb): Navigate to a help page explaining why we disabled
293 // the plugin, once we have one.
294 return false;
295 }
296
297 private:
298 TabContents* tab_contents_;
299 string16 name_;
300 GURL update_url_;
301};
302
[email protected]420ae012009-04-24 05:16:32303} // namespace
304
305// -----------------------------------------------------------------------------
306
[email protected]fdd61c62009-04-22 19:22:57307// static
308int TabContents::find_request_id_counter_ = -1;
309
[email protected]420ae012009-04-24 05:16:32310
[email protected]420ae012009-04-24 05:16:32311TabContents::TabContents(Profile* profile,
312 SiteInstance* site_instance,
313 int routing_id,
[email protected]6ee12c42010-09-14 09:36:07314 const TabContents* base_tab_contents,
315 SessionStorageNamespace* session_storage_namespace)
[email protected]b680ad22009-04-15 23:19:42316 : delegate_(NULL),
[email protected]6ee12c42010-09-14 09:36:07317 ALLOW_THIS_IN_INITIALIZER_LIST(controller_(
318 this, profile, session_storage_namespace)),
[email protected]66ba4932009-06-04 19:22:13319 ALLOW_THIS_IN_INITIALIZER_LIST(view_(
[email protected]d82ed61e2009-06-16 02:46:22320 TabContentsView::Create(this))),
321 ALLOW_THIS_IN_INITIALIZER_LIST(render_manager_(this, this)),
[email protected]fdd61c62009-04-22 19:22:57322 property_bag_(),
323 registrar_(),
[email protected]12802702010-07-09 19:43:09324 ALLOW_THIS_IN_INITIALIZER_LIST(printing_(
325 new printing::PrintViewManager(*this))),
[email protected]fdd61c62009-04-22 19:22:57326 save_package_(),
[email protected]6db0def92010-03-02 19:55:45327 autocomplete_history_manager_(),
[email protected]21674df2009-10-28 19:51:21328 autofill_manager_(),
[email protected]fdd61c62009-04-22 19:22:57329 password_manager_(),
330 plugin_installer_(),
[email protected]6f821dd2010-02-23 00:54:06331 bookmark_drag_(NULL),
[email protected]d82ed61e2009-06-16 02:46:22332 ALLOW_THIS_IN_INITIALIZER_LIST(fav_icon_helper_(this)),
[email protected]d5f942ba2008-09-26 19:30:34333 is_loading_(false),
initial.commit09911bf2008-07-26 23:55:29334 is_crashed_(false),
[email protected]d5f942ba2008-09-26 19:30:34335 waiting_for_response_(false),
[email protected]d5f942ba2008-09-26 19:30:34336 max_page_id_(-1),
[email protected]fdd61c62009-04-22 19:22:57337 current_load_start_(),
338 load_state_(net::LOAD_STATE_IDLE),
339 load_state_host_(),
[email protected]094e5b22009-09-25 04:23:56340 upload_size_(0),
341 upload_position_(0),
[email protected]fdd61c62009-04-22 19:22:57342 received_page_title_(false),
343 is_starred_(false),
344 contents_mime_type_(),
345 encoding_(),
[email protected]332af7732009-03-11 13:21:35346 blocked_popups_(NULL),
[email protected]8cc8d492010-02-02 10:40:49347 dont_notify_render_view_(false),
[email protected]f17a0ee2010-05-17 17:38:47348 displayed_insecure_content_(false),
[email protected]fdd61c62009-04-22 19:22:57349 infobar_delegates_(),
[email protected]fdd61c62009-04-22 19:22:57350 find_ui_active_(false),
351 find_op_aborted_(false),
352 current_find_request_id_(find_request_id_counter_++),
[email protected]e491f1c2009-05-22 20:28:12353 last_search_case_sensitive_(false),
[email protected]e491f1c2009-05-22 20:28:12354 last_search_result_(),
[email protected]98aa0b52010-05-06 17:03:08355 extension_app_(NULL),
[email protected]fdd61c62009-04-22 19:22:57356 capturing_contents_(false),
357 is_being_destroyed_(false),
358 notify_disconnection_(false),
359 history_requests_(),
360#if defined(OS_WIN)
361 message_box_active_(CreateEvent(NULL, TRUE, FALSE, NULL)),
362#endif
363 last_javascript_message_dismissal_(),
[email protected]c2e74fe82009-09-03 17:57:44364 suppress_javascript_messages_(false),
[email protected]7ab1e7d62009-10-14 23:32:01365 is_showing_before_unload_dialog_(false),
[email protected]7ff431e2010-01-07 18:18:54366 renderer_preferences_(),
[email protected]1a242c32010-02-02 21:20:54367 opener_dom_ui_type_(DOMUIFactory::kNoDOMUI),
[email protected]777a7b62010-05-11 13:28:16368 language_state_(&controller_),
[email protected]ebf40a72010-07-22 01:46:38369 closed_by_user_gesture_(false),
[email protected]b75b8292010-10-01 07:28:25370 minimum_zoom_percent_(
371 static_cast<int>(WebKit::WebView::minTextSizeMultiplier * 100)),
372 maximum_zoom_percent_(
373 static_cast<int>(WebKit::WebView::maxTextSizeMultiplier * 100)),
[email protected]b75b8292010-10-01 07:28:25374 temporary_zoom_settings_(false) {
[email protected]7ff431e2010-01-07 18:18:54375 renderer_preferences_util::UpdateFromSystemSettings(
376 &renderer_preferences_, profile);
377
[email protected]9fb83e82010-07-02 18:24:55378 content_settings_delegate_.reset(
379 new TabSpecificContentSettings(this, profile));
380
[email protected]16779842009-07-08 23:45:29381#if defined(OS_CHROMEOS)
[email protected]58dca552009-06-17 00:35:02382 // Make sure the thumbnailer is started before starting the render manager.
383 // The thumbnailer will want to listen for RVH creations, one of which will
384 // happen in RVHManager::Init.
385 ThumbnailGenerator* generator = g_browser_process->GetThumbnailGenerator();
386 if (generator)
387 generator->StartThumbnailing();
388#endif
389
[email protected]12636df2009-09-28 22:32:21390 render_manager_.Init(profile, site_instance, routing_id);
[email protected]420ae012009-04-24 05:16:32391
[email protected]34ac70502009-09-25 17:07:23392 // We have the initial size of the view be based on the size of the passed in
393 // tab contents (normally a tab from the same window).
394 view_->CreateView(base_tab_contents ?
395 base_tab_contents->view()->GetContainerSize() : gfx::Size());
[email protected]420ae012009-04-24 05:16:32396
397 // Register for notifications about all interested prefs change.
398 PrefService* prefs = profile->GetPrefs();
[email protected]2fb7dc982010-09-29 12:24:28399 pref_change_registrar_.Init(prefs);
[email protected]420ae012009-04-24 05:16:32400 if (prefs) {
401 for (int i = 0; i < kPrefsToObserveLength; ++i)
[email protected]2fb7dc982010-09-29 12:24:28402 pref_change_registrar_.Add(kPrefsToObserve[i], this);
[email protected]420ae012009-04-24 05:16:32403 }
404
405 // Register for notifications about URL starredness changing on any profile.
406 registrar_.Add(this, NotificationType::URLS_STARRED,
407 NotificationService::AllSources());
408 registrar_.Add(this, NotificationType::BOOKMARK_MODEL_LOADED,
409 NotificationService::AllSources());
410 registrar_.Add(this, NotificationType::RENDER_WIDGET_HOST_DESTROYED,
411 NotificationService::AllSources());
[email protected]d3ba77272009-09-03 00:06:09412#if defined(OS_LINUX)
413 registrar_.Add(this, NotificationType::BROWSER_THEME_CHANGED,
414 NotificationService::AllSources());
415#endif
[email protected]420ae012009-04-24 05:16:32416
[email protected]6c32ce72010-03-08 05:18:06417 registrar_.Add(this, NotificationType::USER_STYLE_SHEET_UPDATED,
418 NotificationService::AllSources());
419
[email protected]79580c62010-02-02 02:36:25420 // Register for notifications about content setting changes.
421 registrar_.Add(this, NotificationType::CONTENT_SETTINGS_CHANGED,
422 NotificationService::AllSources());
423
[email protected]a888b29e62010-04-01 13:38:57424 // Listen for extension changes so we can update extension_for_current_page_.
425 registrar_.Add(this, NotificationType::EXTENSION_LOADED,
426 NotificationService::AllSources());
427 registrar_.Add(this, NotificationType::EXTENSION_UNLOADED,
428 NotificationService::AllSources());
429 registrar_.Add(this, NotificationType::EXTENSION_UNLOADED_DISABLED,
430 NotificationService::AllSources());
431
[email protected]88152052010-10-01 04:05:18432 // Listen for Google URL changes
433 registrar_.Add(this, NotificationType::GOOGLE_URL_UPDATED,
434 NotificationService::AllSources());
435
[email protected]c8865482009-07-23 20:40:10436 // Set-up the showing of the omnibox search infobar if applicable.
437 if (OmniboxSearchHint::IsEnabled(profile))
438 omnibox_search_hint_.reset(new OmniboxSearchHint(this));
[email protected]332af7732009-03-11 13:21:35439}
initial.commit09911bf2008-07-26 23:55:29440
441TabContents::~TabContents() {
[email protected]420ae012009-04-24 05:16:32442 is_being_destroyed_ = true;
443
[email protected]bfe4c1582009-10-02 18:11:09444 // We don't want any notifications while we're running our destructor.
[email protected]420ae012009-04-24 05:16:32445 registrar_.RemoveAll();
[email protected]2fb7dc982010-09-29 12:24:28446 pref_change_registrar_.RemoveAll();
[email protected]420ae012009-04-24 05:16:32447
[email protected]420ae012009-04-24 05:16:32448 NotifyDisconnected();
[email protected]e7b8d832009-11-20 22:41:00449 hung_renderer_dialog::HideForTabContents(this);
[email protected]420ae012009-04-24 05:16:32450
[email protected]420ae012009-04-24 05:16:32451 // First cleanly close all child windows.
452 // TODO(mpcomplete): handle case if MaybeCloseChildWindows() already asked
453 // some of these to close. CloseWindows is async, so it might get called
454 // twice before it runs.
[email protected]8cc8d492010-02-02 10:40:49455 CloseConstrainedWindows();
[email protected]420ae012009-04-24 05:16:32456
[email protected]8cc8d492010-02-02 10:40:49457 // Close all blocked popups.
[email protected]66ba4932009-06-04 19:22:13458 if (blocked_popups_)
459 blocked_popups_->Destroy();
460
[email protected]420ae012009-04-24 05:16:32461 // Notify any observer that have a reference on this tab contents.
462 NotificationService::current()->Notify(
463 NotificationType::TAB_CONTENTS_DESTROYED,
464 Source<TabContents>(this),
465 NotificationService::NoDetails());
466
[email protected]1e5e74f2009-05-27 20:55:12467 // Notify any lasting InfobarDelegates that have not yet been removed that
468 // whatever infobar they were handling in this TabContents has closed,
469 // because the TabContents is going away entirely.
470 // This must happen after the TAB_CONTENTS_DESTROYED notification as the
471 // notification may trigger infobars calls that access their delegate. (and
472 // some implementations of InfoBarDelegate do delete themselves on
473 // InfoBarClosed()).
474 for (int i = 0; i < infobar_delegate_count(); ++i) {
475 InfoBarDelegate* delegate = GetInfoBarDelegateAt(i);
476 delegate->InfoBarClosed();
477 }
478 infobar_delegates_.clear();
479
[email protected]420ae012009-04-24 05:16:32480 // TODO(brettw) this should be moved to the view.
481#if defined(OS_WIN)
482 // If we still have a window handle, destroy it. GetNativeView can return
483 // NULL if this contents was part of a window that closed.
484 if (GetNativeView())
485 ::DestroyWindow(GetNativeView());
486#endif
[email protected]7ab1e7d62009-10-14 23:32:01487
488 // OnCloseStarted isn't called in unit tests.
489 if (!tab_close_start_time_.is_null()) {
490 UMA_HISTOGRAM_TIMES("Tab.Close",
491 base::TimeTicks::Now() - tab_close_start_time_);
492 }
initial.commit09911bf2008-07-26 23:55:29493}
494
[email protected]d5f942ba2008-09-26 19:30:34495// static
496void TabContents::RegisterUserPrefs(PrefService* prefs) {
[email protected]420ae012009-04-24 05:16:32497 prefs->RegisterBooleanPref(prefs::kAlternateErrorPagesEnabled, true);
498
499 WebPreferences pref_defaults;
500 prefs->RegisterBooleanPref(prefs::kWebKitJavascriptEnabled,
501 pref_defaults.javascript_enabled);
502 prefs->RegisterBooleanPref(prefs::kWebKitWebSecurityEnabled,
503 pref_defaults.web_security_enabled);
504 prefs->RegisterBooleanPref(
505 prefs::kWebKitJavascriptCanOpenWindowsAutomatically, true);
506 prefs->RegisterBooleanPref(prefs::kWebKitLoadsImagesAutomatically,
507 pref_defaults.loads_images_automatically);
508 prefs->RegisterBooleanPref(prefs::kWebKitPluginsEnabled,
509 pref_defaults.plugins_enabled);
510 prefs->RegisterBooleanPref(prefs::kWebKitDomPasteEnabled,
511 pref_defaults.dom_paste_enabled);
512 prefs->RegisterBooleanPref(prefs::kWebKitShrinksStandaloneImagesToFit,
513 pref_defaults.shrinks_standalone_images_to_fit);
[email protected]c4e98902010-06-01 10:20:14514 prefs->RegisterDictionaryPref(prefs::kWebKitInspectorSettings);
[email protected]420ae012009-04-24 05:16:32515 prefs->RegisterBooleanPref(prefs::kWebKitTextAreasAreResizable,
516 pref_defaults.text_areas_are_resizable);
517 prefs->RegisterBooleanPref(prefs::kWebKitJavaEnabled,
518 pref_defaults.java_enabled);
[email protected]1661a3c02010-05-20 16:32:36519 prefs->RegisterBooleanPref(prefs::kWebkitTabsToLinks,
520 pref_defaults.tabs_to_links);
[email protected]420ae012009-04-24 05:16:32521
522 prefs->RegisterLocalizedStringPref(prefs::kAcceptLanguages,
523 IDS_ACCEPT_LANGUAGES);
524 prefs->RegisterLocalizedStringPref(prefs::kDefaultCharset,
525 IDS_DEFAULT_ENCODING);
526 prefs->RegisterLocalizedBooleanPref(prefs::kWebKitStandardFontIsSerif,
527 IDS_STANDARD_FONT_IS_SERIF);
528 prefs->RegisterLocalizedStringPref(prefs::kWebKitFixedFontFamily,
529 IDS_FIXED_FONT_FAMILY);
530 prefs->RegisterLocalizedStringPref(prefs::kWebKitSerifFontFamily,
531 IDS_SERIF_FONT_FAMILY);
532 prefs->RegisterLocalizedStringPref(prefs::kWebKitSansSerifFontFamily,
533 IDS_SANS_SERIF_FONT_FAMILY);
534 prefs->RegisterLocalizedStringPref(prefs::kWebKitCursiveFontFamily,
535 IDS_CURSIVE_FONT_FAMILY);
536 prefs->RegisterLocalizedStringPref(prefs::kWebKitFantasyFontFamily,
537 IDS_FANTASY_FONT_FAMILY);
538 prefs->RegisterLocalizedIntegerPref(prefs::kWebKitDefaultFontSize,
539 IDS_DEFAULT_FONT_SIZE);
540 prefs->RegisterLocalizedIntegerPref(prefs::kWebKitDefaultFixedFontSize,
541 IDS_DEFAULT_FIXED_FONT_SIZE);
542 prefs->RegisterLocalizedIntegerPref(prefs::kWebKitMinimumFontSize,
543 IDS_MINIMUM_FONT_SIZE);
544 prefs->RegisterLocalizedIntegerPref(prefs::kWebKitMinimumLogicalFontSize,
545 IDS_MINIMUM_LOGICAL_FONT_SIZE);
546 prefs->RegisterLocalizedBooleanPref(prefs::kWebKitUsesUniversalDetector,
547 IDS_USES_UNIVERSAL_DETECTOR);
548 prefs->RegisterLocalizedStringPref(prefs::kStaticEncodings,
549 IDS_STATIC_ENCODING_LIST);
initial.commit09911bf2008-07-26 23:55:29550}
551
[email protected]13367f72009-07-08 16:39:02552// Returns true if contains content rendered by an extension.
553bool TabContents::HostsExtension() const {
554 return GetURL().SchemeIs(chrome::kExtensionScheme);
[email protected]d5f942ba2008-09-26 19:30:34555}
556
[email protected]cf28ec52010-04-09 22:56:34557AutoFillManager* TabContents::GetAutoFillManager() {
558 if (autofill_manager_.get() == NULL)
559 autofill_manager_.reset(new AutoFillManager(this));
560 return autofill_manager_.get();
561}
562
[email protected]6e95706d2009-04-23 22:55:01563PasswordManager* TabContents::GetPasswordManager() {
564 if (password_manager_.get() == NULL)
565 password_manager_.reset(new PasswordManager(this));
566 return password_manager_.get();
567}
568
569PluginInstaller* TabContents::GetPluginInstaller() {
570 if (plugin_installer_.get() == NULL)
571 plugin_installer_.reset(new PluginInstaller(this));
572 return plugin_installer_.get();
573}
574
[email protected]1f18184a2010-07-21 19:34:49575TabContentsSSLHelper* TabContents::GetSSLHelper() {
576 if (ssl_helper_.get() == NULL)
577 ssl_helper_.reset(new TabContentsSSLHelper(this));
578 return ssl_helper_.get();
579}
580
[email protected]8cb5d5b2010-02-09 11:36:16581RenderProcessHost* TabContents::GetRenderProcessHost() const {
582 return render_manager_.current_host()->process();
583}
584
[email protected]98aa0b52010-05-06 17:03:08585void TabContents::SetExtensionApp(Extension* extension) {
[email protected]867a73e12010-03-19 20:45:46586 DCHECK(!extension || extension->GetFullLaunchURL().is_valid());
[email protected]98aa0b52010-05-06 17:03:08587 extension_app_ = extension;
[email protected]fca656c2010-02-10 20:30:10588
[email protected]98aa0b52010-05-06 17:03:08589 UpdateExtensionAppIcon(extension_app_);
[email protected]a888b29e62010-04-01 13:38:57590
[email protected]fca656c2010-02-10 20:30:10591 NotificationService::current()->Notify(
592 NotificationType::TAB_CONTENTS_APPLICATION_EXTENSION_CHANGED,
593 Source<TabContents>(this),
594 NotificationService::NoDetails());
[email protected]3b355642010-02-05 16:01:49595}
596
[email protected]98aa0b52010-05-06 17:03:08597void TabContents::SetExtensionAppById(const std::string& extension_app_id) {
598 if (extension_app_id.empty())
[email protected]911f8152010-03-18 16:46:40599 return;
600
601 ExtensionsService* extension_service = profile()->GetExtensionsService();
602 if (extension_service && extension_service->is_ready()) {
603 Extension* extension =
[email protected]98aa0b52010-05-06 17:03:08604 extension_service->GetExtensionById(extension_app_id, false);
[email protected]911f8152010-03-18 16:46:40605 if (extension)
[email protected]98aa0b52010-05-06 17:03:08606 SetExtensionApp(extension);
[email protected]911f8152010-03-18 16:46:40607 }
608}
609
[email protected]98aa0b52010-05-06 17:03:08610SkBitmap* TabContents::GetExtensionAppIcon() {
[email protected]98aa0b52010-05-06 17:03:08611 if (extension_app_icon_.empty())
[email protected]8eb043b2010-04-30 07:19:51612 return NULL;
613
[email protected]98aa0b52010-05-06 17:03:08614 return &extension_app_icon_;
[email protected]8eb043b2010-04-30 07:19:51615}
616
[email protected]d5f942ba2008-09-26 19:30:34617const GURL& TabContents::GetURL() const {
618 // We may not have a navigation entry yet
[email protected]ce3fa3c2009-04-20 19:55:57619 NavigationEntry* entry = controller_.GetActiveEntry();
[email protected]ebe89e062009-08-13 23:16:54620 return entry ? entry->virtual_url() : GURL::EmptyGURL();
[email protected]d5f942ba2008-09-26 19:30:34621}
622
[email protected]96d185d2009-04-24 03:28:54623const string16& TabContents::GetTitle() const {
[email protected]4c6092c5b2009-06-06 00:23:55624 // Transient entries take precedence. They are used for interstitial pages
625 // that are shown on top of existing pages.
626 NavigationEntry* entry = controller_.GetTransientEntry();
627 if (entry)
628 return entry->GetTitleForDisplay(&controller_);
629
[email protected]96d185d2009-04-24 03:28:54630 DOMUI* our_dom_ui = render_manager_.pending_dom_ui() ?
631 render_manager_.pending_dom_ui() : render_manager_.dom_ui();
632 if (our_dom_ui) {
633 // Don't override the title in view source mode.
[email protected]4c6092c5b2009-06-06 00:23:55634 entry = controller_.GetActiveEntry();
[email protected]96d185d2009-04-24 03:28:54635 if (!(entry && entry->IsViewSourceMode())) {
636 // Give the DOM UI the chance to override our title.
637 const string16& title = our_dom_ui->overridden_title();
638 if (!title.empty())
639 return title;
640 }
641 }
642
643 // We use the title for the last committed entry rather than a pending
644 // navigation entry. For example, when the user types in a URL, we want to
645 // keep the old page's title until the new load has committed and we get a new
646 // title.
[email protected]96d185d2009-04-24 03:28:54647 entry = controller_.GetLastCommittedEntry();
648 if (entry)
649 return entry->GetTitleForDisplay(&controller_);
[email protected]96d185d2009-04-24 03:28:54650 return EmptyString16();
651}
652
[email protected]bbbc1ef2010-02-12 18:03:41653// static
654string16 TabContents::GetDefaultTitle() {
655 return l10n_util::GetStringUTF16(IDS_DEFAULT_TAB_TITLE);
656}
657
[email protected]d5f942ba2008-09-26 19:30:34658int32 TabContents::GetMaxPageID() {
659 if (GetSiteInstance())
660 return GetSiteInstance()->max_page_id();
661 else
662 return max_page_id_;
663}
664
665void TabContents::UpdateMaxPageID(int32 page_id) {
666 // Ensure both the SiteInstance and RenderProcessHost update their max page
[email protected]57c6a652009-05-04 07:58:34667 // IDs in sync. Only TabContents will also have site instances, except during
[email protected]d5f942ba2008-09-26 19:30:34668 // testing.
669 if (GetSiteInstance())
670 GetSiteInstance()->UpdateMaxPageID(page_id);
[email protected]8cb5d5b2010-02-09 11:36:16671 GetRenderProcessHost()->UpdateMaxPageID(page_id);
[email protected]d5f942ba2008-09-26 19:30:34672}
673
[email protected]96d185d2009-04-24 03:28:54674SiteInstance* TabContents::GetSiteInstance() const {
675 return render_manager_.current_host()->site_instance();
676}
677
[email protected]96d185d2009-04-24 03:28:54678bool TabContents::ShouldDisplayURL() {
[email protected]8ab24cc2009-11-13 20:56:15679 // Don't hide the url in view source mode and with interstitials.
[email protected]96d185d2009-04-24 03:28:54680 NavigationEntry* entry = controller_.GetActiveEntry();
[email protected]8ab24cc2009-11-13 20:56:15681 if (entry && (entry->IsViewSourceMode() ||
682 entry->page_type() == NavigationEntry::INTERSTITIAL_PAGE)) {
[email protected]96d185d2009-04-24 03:28:54683 return true;
[email protected]8ab24cc2009-11-13 20:56:15684 }
[email protected]83e3895b2009-06-11 00:07:16685
[email protected]96d185d2009-04-24 03:28:54686 DOMUI* dom_ui = GetDOMUIForCurrentState();
687 if (dom_ui)
688 return !dom_ui->should_hide_url();
689 return true;
690}
691
[email protected]d5f942ba2008-09-26 19:30:34692SkBitmap TabContents::GetFavIcon() const {
693 // Like GetTitle(), we also want to use the favicon for the last committed
694 // entry rather than a pending navigation entry.
[email protected]ce3fa3c2009-04-20 19:55:57695 NavigationEntry* entry = controller_.GetTransientEntry();
[email protected]cbab76d2008-10-13 22:42:47696 if (entry)
697 return entry->favicon().bitmap();
698
[email protected]ce3fa3c2009-04-20 19:55:57699 entry = controller_.GetLastCommittedEntry();
[email protected]d5f942ba2008-09-26 19:30:34700 if (entry)
701 return entry->favicon().bitmap();
[email protected]d5f942ba2008-09-26 19:30:34702 return SkBitmap();
703}
704
[email protected]0b303cc2009-09-28 22:35:15705bool TabContents::FavIconIsValid() const {
706 NavigationEntry* entry = controller_.GetTransientEntry();
707 if (entry)
708 return entry->favicon().is_valid();
709
710 entry = controller_.GetLastCommittedEntry();
711 if (entry)
712 return entry->favicon().is_valid();
713
714 return false;
715}
716
[email protected]96d185d2009-04-24 03:28:54717bool TabContents::ShouldDisplayFavIcon() {
718 // Always display a throbber during pending loads.
719 if (controller_.GetLastCommittedEntry() && controller_.pending_entry())
720 return true;
721
722 DOMUI* dom_ui = GetDOMUIForCurrentState();
723 if (dom_ui)
724 return !dom_ui->hide_favicon();
725 return true;
726}
727
[email protected]96d185d2009-04-24 03:28:54728std::wstring TabContents::GetStatusText() const {
729 if (!is_loading() || load_state_ == net::LOAD_STATE_IDLE)
730 return std::wstring();
731
732 switch (load_state_) {
733 case net::LOAD_STATE_WAITING_FOR_CACHE:
734 return l10n_util::GetString(IDS_LOAD_STATE_WAITING_FOR_CACHE);
[email protected]8a1f3312010-05-25 19:25:04735 case net::LOAD_STATE_ESTABLISHING_PROXY_TUNNEL:
736 return l10n_util::GetString(IDS_LOAD_STATE_ESTABLISHING_PROXY_TUNNEL);
[email protected]96d185d2009-04-24 03:28:54737 case net::LOAD_STATE_RESOLVING_PROXY_FOR_URL:
738 return l10n_util::GetString(IDS_LOAD_STATE_RESOLVING_PROXY_FOR_URL);
739 case net::LOAD_STATE_RESOLVING_HOST:
740 return l10n_util::GetString(IDS_LOAD_STATE_RESOLVING_HOST);
741 case net::LOAD_STATE_CONNECTING:
742 return l10n_util::GetString(IDS_LOAD_STATE_CONNECTING);
[email protected]375e3112010-05-27 20:32:06743 case net::LOAD_STATE_SSL_HANDSHAKE:
744 return l10n_util::GetString(IDS_LOAD_STATE_SSL_HANDSHAKE);
[email protected]96d185d2009-04-24 03:28:54745 case net::LOAD_STATE_SENDING_REQUEST:
[email protected]094e5b22009-09-25 04:23:56746 if (upload_size_)
747 return l10n_util::GetStringF(
748 IDS_LOAD_STATE_SENDING_REQUEST_WITH_PROGRESS,
749 static_cast<int>((100 * upload_position_) / upload_size_));
750 else
751 return l10n_util::GetString(IDS_LOAD_STATE_SENDING_REQUEST);
[email protected]96d185d2009-04-24 03:28:54752 case net::LOAD_STATE_WAITING_FOR_RESPONSE:
753 return l10n_util::GetStringF(IDS_LOAD_STATE_WAITING_FOR_RESPONSE,
754 load_state_host_);
755 // Ignore net::LOAD_STATE_READING_RESPONSE and net::LOAD_STATE_IDLE
756 case net::LOAD_STATE_IDLE:
757 case net::LOAD_STATE_READING_RESPONSE:
758 break;
759 }
760
761 return std::wstring();
762}
763
[email protected]d5f942ba2008-09-26 19:30:34764void TabContents::SetIsCrashed(bool state) {
765 if (state == is_crashed_)
766 return;
767
768 is_crashed_ = state;
[email protected]c9cd2222009-05-06 05:16:50769 NotifyNavigationStateChanged(INVALIDATE_TAB);
[email protected]d5f942ba2008-09-26 19:30:34770}
771
[email protected]744ef172009-10-16 21:53:46772void TabContents::PageActionStateChanged() {
773 NotifyNavigationStateChanged(TabContents::INVALIDATE_PAGE_ACTIONS);
[email protected]d7eaf572009-07-01 21:57:00774}
[email protected]ce5c4502009-05-06 16:46:11775
[email protected]d5f942ba2008-09-26 19:30:34776void TabContents::NotifyNavigationStateChanged(unsigned changed_flags) {
777 if (delegate_)
778 delegate_->NavigationStateChanged(this, changed_flags);
779}
780
[email protected]96d185d2009-04-24 03:28:54781void TabContents::DidBecomeSelected() {
782 controller_.SetActive(true);
[email protected]8cb5d5b2010-02-09 11:36:16783 RenderWidgetHostView* rwhv = GetRenderWidgetHostView();
784 if (rwhv) {
785 rwhv->DidBecomeSelected();
[email protected]789e9152009-08-04 21:59:43786#if defined(OS_MACOSX)
[email protected]8cb5d5b2010-02-09 11:36:16787 rwhv->SetActive(true);
[email protected]789e9152009-08-04 21:59:43788#endif
789 }
[email protected]96d185d2009-04-24 03:28:54790
[email protected]8cb5d5b2010-02-09 11:36:16791 WebCacheManager::GetInstance()->ObserveActivity(GetRenderProcessHost()->id());
[email protected]96d185d2009-04-24 03:28:54792}
793
794void TabContents::WasHidden() {
795 if (!capturing_contents()) {
796 // |render_view_host()| can be NULL if the user middle clicks a link to open
797 // a tab in then background, then closes the tab before selecting it. This
798 // is because closing the tab calls TabContents::Destroy(), which removes
799 // the |render_view_host()|; then when we actually destroy the window,
800 // OnWindowPosChanged() notices and calls HideContents() (which calls us).
[email protected]8cb5d5b2010-02-09 11:36:16801 RenderWidgetHostView* rwhv = GetRenderWidgetHostView();
802 if (rwhv)
803 rwhv->WasHidden();
[email protected]96d185d2009-04-24 03:28:54804 }
805
806 NotificationService::current()->Notify(
807 NotificationType::TAB_CONTENTS_HIDDEN,
808 Source<TabContents>(this),
809 NotificationService::NoDetails());
810}
811
[email protected]d5f942ba2008-09-26 19:30:34812void TabContents::Activate() {
813 if (delegate_)
814 delegate_->ActivateContents(this);
815}
816
[email protected]ea42e7782010-08-23 23:58:12817void TabContents::Deactivate() {
818 if (delegate_)
819 delegate_->DeactivateContents(this);
820}
821
[email protected]96d185d2009-04-24 03:28:54822void TabContents::ShowContents() {
[email protected]8cb5d5b2010-02-09 11:36:16823 RenderWidgetHostView* rwhv = GetRenderWidgetHostView();
824 if (rwhv)
825 rwhv->DidBecomeSelected();
[email protected]96d185d2009-04-24 03:28:54826}
827
828void TabContents::HideContents() {
829 // TODO(pkasting): http://b/1239839 Right now we purposefully don't call
830 // our superclass HideContents(), because some callers want to be very picky
831 // about the order in which these get called. In addition to making the code
832 // here practically impossible to understand, this also means we end up
833 // calling TabContents::WasHidden() twice if callers call both versions of
[email protected]57c6a652009-05-04 07:58:34834 // HideContents() on a TabContents.
[email protected]96d185d2009-04-24 03:28:54835 WasHidden();
836}
837
[email protected]c0588052008-10-27 23:01:50838void TabContents::OpenURL(const GURL& url, const GURL& referrer,
[email protected]d5f942ba2008-09-26 19:30:34839 WindowOpenDisposition disposition,
840 PageTransition::Type transition) {
841 if (delegate_)
[email protected]c0588052008-10-27 23:01:50842 delegate_->OpenURLFromTab(this, url, referrer, disposition, transition);
[email protected]d5f942ba2008-09-26 19:30:34843}
844
[email protected]1ccb3568d2010-02-19 10:51:16845bool TabContents::NavigateToPendingEntry(
846 NavigationController::ReloadType reload_type) {
[email protected]876bc832010-09-07 16:29:54847 return NavigateToEntry(*controller_.pending_entry(), reload_type);
848}
[email protected]96d185d2009-04-24 03:28:54849
[email protected]876bc832010-09-07 16:29:54850bool TabContents::NavigateToEntry(
851 const NavigationEntry& entry,
852 NavigationController::ReloadType reload_type) {
[email protected]96d185d2009-04-24 03:28:54853 RenderViewHost* dest_render_view_host = render_manager_.Navigate(entry);
854 if (!dest_render_view_host)
855 return false; // Unable to create the desired render view host.
856
[email protected]770dd8b2010-05-24 18:11:39857 if (delegate_ && delegate_->ShouldEnablePreferredSizeNotifications()) {
858 dest_render_view_host->EnablePreferredSizeChangedMode(
859 kPreferredSizeWidth | kPreferredSizeHeightThisIsSlow);
860 }
[email protected]9fb325e2010-05-06 18:23:24861
[email protected]0352e5472010-04-29 00:11:40862 // For security, we should never send non-DOM-UI URLs (other than about:blank)
863 // to a DOM UI renderer. Double check that here.
[email protected]54ec6472010-04-09 19:39:58864 int enabled_bindings = dest_render_view_host->enabled_bindings();
[email protected]0352e5472010-04-29 00:11:40865 bool is_allowed_in_dom_ui_renderer =
[email protected]583d45c12010-08-31 02:48:12866 DOMUIFactory::UseDOMUIForURL(profile(), entry.url()) ||
[email protected]0352e5472010-04-29 00:11:40867 entry.url() == GURL(chrome::kAboutBlankURL);
[email protected]54ec6472010-04-09 19:39:58868 CHECK(!BindingsPolicy::is_dom_ui_enabled(enabled_bindings) ||
[email protected]0352e5472010-04-29 00:11:40869 is_allowed_in_dom_ui_renderer);
[email protected]54ec6472010-04-09 19:39:58870
[email protected]96d185d2009-04-24 03:28:54871 // Tell DevTools agent that it is attached prior to the navigation.
[email protected]d9f9b792009-06-24 13:17:12872 DevToolsManager* devtools_manager = DevToolsManager::GetInstance();
[email protected]7e8e6b62009-05-08 11:28:32873 if (devtools_manager) { // NULL in unit tests.
[email protected]3cc72b12010-03-18 23:03:00874 devtools_manager->OnNavigatingToPendingEntry(render_view_host(),
875 dest_render_view_host,
876 entry.url());
[email protected]7e8e6b62009-05-08 11:28:32877 }
[email protected]96d185d2009-04-24 03:28:54878
879 // Used for page load time metrics.
880 current_load_start_ = base::TimeTicks::Now();
881
882 // Navigate in the desired RenderViewHost.
[email protected]056de2d2009-06-26 16:41:34883 ViewMsg_Navigate_Params navigate_params;
[email protected]876bc832010-09-07 16:29:54884 MakeNavigateParams(entry, controller_, reload_type, &navigate_params);
[email protected]056de2d2009-06-26 16:41:34885 dest_render_view_host->Navigate(navigate_params);
[email protected]96d185d2009-04-24 03:28:54886
887 if (entry.page_id() == -1) {
888 // HACK!! This code suppresses javascript: URLs from being added to
889 // session history, which is what we want to do for javascript: URLs that
890 // do not generate content. What we really need is a message from the
891 // renderer telling us that a new page was not created. The same message
892 // could be used for mailto: URLs and the like.
893 if (entry.url().SchemeIs(chrome::kJavaScriptScheme))
894 return false;
895 }
896
897 // Clear any provisional password saves - this stops password infobars
898 // showing up on pages the user navigates to while the right page is
899 // loading.
900 GetPasswordManager()->ClearProvisionalSave();
901
[email protected]1ccb3568d2010-02-19 10:51:16902 if (reload_type != NavigationController::NO_RELOAD &&
903 !profile()->IsOffTheRecord()) {
[email protected]0189bc722009-08-28 21:56:48904 FaviconService* favicon_service =
905 profile()->GetFaviconService(Profile::IMPLICIT_ACCESS);
906 if (favicon_service)
907 favicon_service->SetFaviconOutOfDateForPage(entry.url());
[email protected]96d185d2009-04-24 03:28:54908 }
909
[email protected]d5f942ba2008-09-26 19:30:34910 return true;
911}
912
[email protected]96d185d2009-04-24 03:28:54913void TabContents::Stop() {
914 render_manager_.Stop();
[email protected]12802702010-07-09 19:43:09915 printing_->Stop();
[email protected]96d185d2009-04-24 03:28:54916}
917
[email protected]96d185d2009-04-24 03:28:54918void TabContents::DisassociateFromPopupCount() {
919 render_view_host()->DisassociateFromPopupCount();
920}
921
922TabContents* TabContents::Clone() {
923 // We create a new SiteInstance so that the new tab won't share processes
924 // with the old one. This can be changed in the future if we need it to share
925 // processes for some reason.
[email protected]420ae012009-04-24 05:16:32926 TabContents* tc = new TabContents(profile(),
[email protected]96d185d2009-04-24 03:28:54927 SiteInstance::CreateSiteInstance(profile()),
[email protected]6ee12c42010-09-14 09:36:07928 MSG_ROUTING_NONE, this, NULL);
[email protected]96d185d2009-04-24 03:28:54929 tc->controller().CopyStateFrom(controller_);
[email protected]98aa0b52010-05-06 17:03:08930 tc->extension_app_ = extension_app_;
[email protected]98aa0b52010-05-06 17:03:08931 tc->extension_app_icon_ = extension_app_icon_;
[email protected]96d185d2009-04-24 03:28:54932 return tc;
933}
934
[email protected]4d677202009-07-19 07:37:12935void TabContents::ShowPageInfo(const GURL& url,
936 const NavigationEntry::SSLStatus& ssl,
937 bool show_history) {
938 if (!delegate_)
939 return;
940
[email protected]bb678332009-07-21 00:15:50941 delegate_->ShowPageInfo(profile(), url, ssl, show_history);
[email protected]4d677202009-07-19 07:37:12942}
943
initial.commit09911bf2008-07-26 23:55:29944ConstrainedWindow* TabContents::CreateConstrainedDialog(
[email protected]e8382172009-06-19 22:16:28945 ConstrainedWindowDelegate* delegate) {
initial.commit09911bf2008-07-26 23:55:29946 ConstrainedWindow* window =
[email protected]e8382172009-06-19 22:16:28947 ConstrainedWindow::CreateConstrainedDialog(this, delegate);
initial.commit09911bf2008-07-26 23:55:29948 child_windows_.push_back(window);
[email protected]fa1cf0b82010-01-15 21:49:44949
950 if (child_windows_.size() == 1) {
951 window->ShowConstrainedWindow();
952 BlockTabContent(true);
953 }
954
initial.commit09911bf2008-07-26 23:55:29955 return window;
956}
957
[email protected]fa1cf0b82010-01-15 21:49:44958void TabContents::BlockTabContent(bool blocked) {
[email protected]8dccd7cb2010-02-25 05:19:55959 RenderWidgetHostView* rwhv = GetRenderWidgetHostView();
960 if (rwhv)
961 rwhv->SetVisuallyDeemphasized(blocked);
[email protected]fa1cf0b82010-01-15 21:49:44962 render_view_host()->set_ignore_input_events(blocked);
963 if (delegate_)
964 delegate_->SetTabContentBlocked(this, blocked);
965}
966
initial.commit09911bf2008-07-26 23:55:29967void TabContents::AddNewContents(TabContents* new_contents,
968 WindowOpenDisposition disposition,
969 const gfx::Rect& initial_pos,
[email protected]7e7414ae2010-01-26 20:19:29970 bool user_gesture) {
initial.commit09911bf2008-07-26 23:55:29971 if (!delegate_)
972 return;
973
[email protected]35f7d212009-04-29 21:19:27974 if ((disposition == NEW_POPUP) && !user_gesture &&
975 !CommandLine::ForCurrentProcess()->HasSwitch(
976 switches::kDisablePopupBlocking)) {
[email protected]2c4410d2009-05-06 23:46:22977 // Unrequested popups from normal pages are constrained unless they're in
[email protected]b6c874582009-05-08 19:38:31978 // the whitelist. The popup owner will handle checking this.
[email protected]7e7414ae2010-01-26 20:19:29979 delegate_->GetConstrainingContents(this)->AddPopup(
980 new_contents, initial_pos);
[email protected]b6c874582009-05-08 19:38:31981 } else {
[email protected]0aa55312008-10-17 21:53:08982 new_contents->DisassociateFromPopupCount();
initial.commit09911bf2008-07-26 23:55:29983 delegate_->AddNewContents(this, new_contents, disposition, initial_pos,
984 user_gesture);
[email protected]7f37dd92009-09-15 16:35:49985 NotificationService::current()->Notify(
986 NotificationType::TAB_ADDED,
987 Source<TabContentsDelegate>(delegate_),
988 Details<TabContents>(this));
initial.commit09911bf2008-07-26 23:55:29989 }
initial.commit09911bf2008-07-26 23:55:29990
[email protected]8cc8d492010-02-02 10:40:49991 // TODO(pkasting): Why is this necessary?
992 PopupNotificationVisibilityChanged(blocked_popups_ != NULL);
initial.commit09911bf2008-07-26 23:55:29993}
994
[email protected]bcd9dc42010-01-23 16:38:18995bool TabContents::ExecuteCode(int request_id, const std::string& extension_id,
[email protected]20ad2692009-11-20 18:27:20996 bool is_js_code, const std::string& code_string,
997 bool all_frames) {
[email protected]ebd0eae72010-02-16 23:50:51998 RenderViewHost* host = render_view_host();
999 if (!host)
1000 return false;
1001
1002 return host->Send(new ViewMsg_ExecuteCode(host->routing_id(),
[email protected]be7e5cb2010-10-04 12:53:171003 ViewMsg_ExecuteCode_Params(request_id, extension_id,
[email protected]ebd0eae72010-02-16 23:50:511004 is_js_code, code_string, all_frames)));
[email protected]912256b32009-09-18 09:47:351005}
1006
[email protected]96d185d2009-04-24 03:28:541007void TabContents::PopupNotificationVisibilityChanged(bool visible) {
[email protected]8cc8d492010-02-02 10:40:491008 if (is_being_destroyed_)
1009 return;
[email protected]9fb83e82010-07-02 18:24:551010 content_settings_delegate_->SetPopupsBlocked(visible);
[email protected]8cc8d492010-02-02 10:40:491011 if (!dont_notify_render_view_)
[email protected]e8345242010-05-06 03:00:401012 render_view_host()->AllowScriptToClose(!visible);
[email protected]96d185d2009-04-24 03:28:541013}
1014
[email protected]5c9e97a2009-09-09 23:48:301015gfx::NativeView TabContents::GetContentNativeView() const {
[email protected]96d185d2009-04-24 03:28:541016 return view_->GetContentNativeView();
1017}
1018
1019gfx::NativeView TabContents::GetNativeView() const {
1020 return view_->GetNativeView();
1021}
1022
1023void TabContents::GetContainerBounds(gfx::Rect *out) const {
1024 view_->GetContainerBounds(out);
1025}
1026
1027void TabContents::Focus() {
1028 view_->Focus();
1029}
1030
[email protected]90daadb42009-06-08 21:27:281031void TabContents::FocusThroughTabTraversal(bool reverse) {
[email protected]7e383692009-06-12 19:14:541032 if (showing_interstitial_page()) {
1033 render_manager_.interstitial_page()->FocusThroughTabTraversal(reverse);
1034 return;
1035 }
[email protected]96d185d2009-04-24 03:28:541036 render_view_host()->SetInitialFocus(reverse);
1037}
1038
1039bool TabContents::FocusLocationBarByDefault() {
1040 DOMUI* dom_ui = GetDOMUIForCurrentState();
1041 if (dom_ui)
1042 return dom_ui->focus_location_bar_by_default();
[email protected]3e3f0eb2009-06-22 18:33:431043 NavigationEntry* entry = controller_.GetActiveEntry();
[email protected]e0d481582009-09-15 21:06:251044 if (entry && entry->url() == GURL(chrome::kAboutBlankURL))
[email protected]3e3f0eb2009-06-22 18:33:431045 return true;
[email protected]96d185d2009-04-24 03:28:541046 return false;
1047}
1048
[email protected]a26dc362010-04-23 01:48:581049void TabContents::SetFocusToLocationBar(bool select_all) {
[email protected]a11aaf22010-03-30 00:03:381050 if (delegate())
[email protected]a26dc362010-04-23 01:48:581051 delegate()->SetFocusToLocationBar(select_all);
[email protected]a11aaf22010-03-30 00:03:381052}
1053
[email protected]616ed5a2008-11-21 22:27:241054void TabContents::AddInfoBar(InfoBarDelegate* delegate) {
[email protected]f7019302010-03-26 19:58:321055 if (delegate_ && !delegate_->infobars_enabled()) {
1056 delegate->InfoBarClosed();
1057 return;
1058 }
1059
[email protected]616ed5a2008-11-21 22:27:241060 // Look through the existing InfoBarDelegates we have for a match. If we've
1061 // already got one that matches, then we don't add the new one.
[email protected]f86a07022008-11-25 01:06:051062 for (int i = 0; i < infobar_delegate_count(); ++i) {
[email protected]6d27a7b2009-12-18 23:25:451063 if (GetInfoBarDelegateAt(i)->EqualsDelegate(delegate)) {
1064 // Tell the new infobar to close so that it can clean itself up.
1065 delegate->InfoBarClosed();
[email protected]616ed5a2008-11-21 22:27:241066 return;
[email protected]6d27a7b2009-12-18 23:25:451067 }
[email protected]616ed5a2008-11-21 22:27:241068 }
1069
1070 infobar_delegates_.push_back(delegate);
[email protected]bfd04a62009-02-01 18:16:561071 NotificationService::current()->Notify(
1072 NotificationType::TAB_CONTENTS_INFOBAR_ADDED,
1073 Source<TabContents>(this),
1074 Details<InfoBarDelegate>(delegate));
[email protected]616ed5a2008-11-21 22:27:241075
1076 // Add ourselves as an observer for navigations the first time a delegate is
1077 // added. We use this notification to expire InfoBars that need to expire on
1078 // page transitions.
1079 if (infobar_delegates_.size() == 1) {
[email protected]bfd04a62009-02-01 18:16:561080 registrar_.Add(this, NotificationType::NAV_ENTRY_COMMITTED,
[email protected]ce3fa3c2009-04-20 19:55:571081 Source<NavigationController>(&controller_));
[email protected]616ed5a2008-11-21 22:27:241082 }
1083}
1084
1085void TabContents::RemoveInfoBar(InfoBarDelegate* delegate) {
[email protected]f7019302010-03-26 19:58:321086 if (delegate_ && !delegate_->infobars_enabled()) {
1087 return;
1088 }
1089
[email protected]616ed5a2008-11-21 22:27:241090 std::vector<InfoBarDelegate*>::iterator it =
1091 find(infobar_delegates_.begin(), infobar_delegates_.end(), delegate);
1092 if (it != infobar_delegates_.end()) {
1093 InfoBarDelegate* delegate = *it;
[email protected]bfd04a62009-02-01 18:16:561094 NotificationService::current()->Notify(
1095 NotificationType::TAB_CONTENTS_INFOBAR_REMOVED,
1096 Source<TabContents>(this),
1097 Details<InfoBarDelegate>(delegate));
[email protected]616ed5a2008-11-21 22:27:241098
[email protected]cdadf6f2010-08-20 16:36:081099 // Just to be safe, make sure the delegate was not removed by an observer.
1100 it = find(infobar_delegates_.begin(), infobar_delegates_.end(), delegate);
1101 if (it != infobar_delegates_.end()) {
1102 infobar_delegates_.erase(it);
1103 // Remove ourselves as an observer if we are tracking no more InfoBars.
1104 if (infobar_delegates_.empty()) {
1105 registrar_.Remove(this, NotificationType::NAV_ENTRY_COMMITTED,
1106 Source<NavigationController>(&controller_));
1107 }
1108 } else {
1109 // If you hit this NOTREACHED, please comment in bug
1110 // http://crbug.com/50428 how you got there.
1111 NOTREACHED();
[email protected]6a02963e2009-01-06 16:58:031112 }
[email protected]616ed5a2008-11-21 22:27:241113 }
1114}
[email protected]3edd9522009-03-04 22:19:411115
[email protected]f81821c2009-08-07 01:29:471116void TabContents::ReplaceInfoBar(InfoBarDelegate* old_delegate,
1117 InfoBarDelegate* new_delegate) {
[email protected]f7019302010-03-26 19:58:321118 if (delegate_ && !delegate_->infobars_enabled()) {
1119 new_delegate->InfoBarClosed();
1120 return;
1121 }
1122
[email protected]f81821c2009-08-07 01:29:471123 std::vector<InfoBarDelegate*>::iterator it =
1124 find(infobar_delegates_.begin(), infobar_delegates_.end(), old_delegate);
1125 DCHECK(it != infobar_delegates_.end());
1126
1127 // Notify the container about the change of plans.
1128 scoped_ptr<std::pair<InfoBarDelegate*, InfoBarDelegate*> > details(
1129 new std::pair<InfoBarDelegate*, InfoBarDelegate*>(
1130 old_delegate, new_delegate));
1131 NotificationService::current()->Notify(
1132 NotificationType::TAB_CONTENTS_INFOBAR_REPLACED,
1133 Source<TabContents>(this),
1134 Details<std::pair<InfoBarDelegate*, InfoBarDelegate*> >(details.get()));
1135
[email protected]cdadf6f2010-08-20 16:36:081136 // Just to be safe, make sure the delegate was not removed by an observer.
1137 it = find(infobar_delegates_.begin(), infobar_delegates_.end(), old_delegate);
1138 if (it != infobar_delegates_.end()) {
1139 // Remove the old one.
1140 infobar_delegates_.erase(it);
1141 } else {
1142 // If you hit this NOTREACHED, please comment in bug
1143 // http://crbug.com/50428 how you got there.
1144 NOTREACHED();
1145 }
[email protected]f81821c2009-08-07 01:29:471146
1147 // Add the new one.
[email protected]cdadf6f2010-08-20 16:36:081148 DCHECK(find(infobar_delegates_.begin(),
1149 infobar_delegates_.end(), new_delegate) ==
1150 infobar_delegates_.end());
[email protected]f81821c2009-08-07 01:29:471151 infobar_delegates_.push_back(new_delegate);
1152}
1153
[email protected]20ede072009-10-06 00:28:351154bool TabContents::ShouldShowBookmarkBar() {
[email protected]aa9196f2009-10-22 16:20:271155 if (showing_interstitial_page())
1156 return false;
1157
[email protected]c8f74942010-09-03 10:04:141158 // Do not show bookmarks bar if bookmarks aren't enabled.
1159 if (!browser_defaults::bookmarks_enabled)
1160 return false;
1161
[email protected]96d185d2009-04-24 03:28:541162 // See GetDOMUIForCurrentState() comment for more info. This case is very
1163 // similar, but for non-first loads, we want to use the committed entry. This
1164 // is so the bookmarks bar disappears at the same time the page does.
1165 if (controller_.GetLastCommittedEntry()) {
1166 // Not the first load, always use the committed DOM UI.
1167 if (render_manager_.dom_ui())
1168 return render_manager_.dom_ui()->force_bookmark_bar_visible();
1169 return false; // Default.
1170 }
1171
1172 // When it's the first load, we know either the pending one or the committed
1173 // one will have the DOM UI in it (see GetDOMUIForCurrentState), and only one
1174 // of them will be valid, so we can just check both.
1175 if (render_manager_.pending_dom_ui())
1176 return render_manager_.pending_dom_ui()->force_bookmark_bar_visible();
1177 if (render_manager_.dom_ui())
1178 return render_manager_.dom_ui()->force_bookmark_bar_visible();
1179 return false; // Default.
1180}
1181
[email protected]3edd9522009-03-04 22:19:411182void TabContents::ToolbarSizeChanged(bool is_animating) {
1183 TabContentsDelegate* d = delegate();
1184 if (d)
1185 d->ToolbarSizeChanged(this, is_animating);
1186}
[email protected]616ed5a2008-11-21 22:27:241187
[email protected]fc6fb7fb2009-11-07 02:35:041188bool TabContents::CanDownload(int request_id) {
1189 TabContentsDelegate* d = delegate();
1190 if (d)
1191 return d->CanDownload(request_id);
1192 return true;
1193}
1194
[email protected]d5f942ba2008-09-26 19:30:341195void TabContents::OnStartDownload(DownloadItem* download) {
1196 DCHECK(download);
[email protected]d5f942ba2008-09-26 19:30:341197
1198 // Download in a constrained popup is shown in the tab that opened it.
[email protected]b6c874582009-05-08 19:38:311199 TabContents* tab_contents = delegate()->GetConstrainingContents(this);
[email protected]d5f942ba2008-09-26 19:30:341200
[email protected]5b928b62010-08-03 11:46:511201 if (tab_contents && tab_contents->delegate())
1202 tab_contents->delegate()->OnStartDownload(download, this);
[email protected]3edd9522009-03-04 22:19:411203}
[email protected]3edd9522009-03-04 22:19:411204
[email protected]d5f942ba2008-09-26 19:30:341205void TabContents::WillClose(ConstrainedWindow* window) {
1206 ConstrainedWindowList::iterator it =
1207 find(child_windows_.begin(), child_windows_.end(), window);
[email protected]fa1cf0b82010-01-15 21:49:441208 bool removed_topmost_window = it == child_windows_.begin();
[email protected]d5f942ba2008-09-26 19:30:341209 if (it != child_windows_.end())
1210 child_windows_.erase(it);
[email protected]55098792010-03-24 18:20:371211 if (child_windows_.size() > 0) {
1212 if (removed_topmost_window) {
1213 child_windows_[0]->ShowConstrainedWindow();
1214 }
[email protected]fa1cf0b82010-01-15 21:49:441215 BlockTabContent(true);
1216 } else {
1217 BlockTabContent(false);
1218 }
[email protected]66ba4932009-06-04 19:22:131219}
[email protected]d5f942ba2008-09-26 19:30:341220
[email protected]66ba4932009-06-04 19:22:131221void TabContents::WillCloseBlockedPopupContainer(
1222 BlockedPopupContainer* container) {
1223 DCHECK(blocked_popups_ == container);
1224 blocked_popups_ = NULL;
[email protected]8cc8d492010-02-02 10:40:491225 PopupNotificationVisibilityChanged(false);
[email protected]d5f942ba2008-09-26 19:30:341226}
1227
[email protected]d5f942ba2008-09-26 19:30:341228void TabContents::DidMoveOrResize(ConstrainedWindow* window) {
[email protected]332af7732009-03-11 13:21:351229#if defined(OS_WIN)
[email protected]92edc472009-02-10 20:32:061230 UpdateWindow(GetNativeView());
[email protected]332af7732009-03-11 13:21:351231#endif
[email protected]d5f942ba2008-09-26 19:30:341232}
1233
[email protected]c1dc9f132009-11-20 23:13:211234void TabContents::StartFinding(string16 search_string,
[email protected]e491f1c2009-05-22 20:28:121235 bool forward_direction,
1236 bool case_sensitive) {
[email protected]c1dc9f132009-11-20 23:13:211237 // If search_string is empty, it means FindNext was pressed with a keyboard
[email protected]6e95706d2009-04-23 22:55:011238 // shortcut so unless we have something to search for we return early.
[email protected]c1dc9f132009-11-20 23:13:211239 if (search_string.empty() && find_text_.empty()) {
[email protected]e5d2f7132010-04-09 18:13:531240 string16 last_search_prepopulate_text =
1241 FindBarState::GetLastPrepopulateText(profile());
1242
[email protected]87fae512009-12-11 02:20:211243 // Try the last thing we searched for on this tab, then the last thing
1244 // searched for on any tab.
1245 if (!previous_find_text_.empty())
1246 search_string = previous_find_text_;
[email protected]e5d2f7132010-04-09 18:13:531247 else if (!last_search_prepopulate_text.empty())
1248 search_string = last_search_prepopulate_text;
[email protected]87fae512009-12-11 02:20:211249 else
[email protected]e491f1c2009-05-22 20:28:121250 return;
[email protected]e491f1c2009-05-22 20:28:121251 }
[email protected]6e95706d2009-04-23 22:55:011252
[email protected]101c90e2009-10-26 21:14:441253 // Keep track of the previous search.
1254 previous_find_text_ = find_text_;
1255
[email protected]6e95706d2009-04-23 22:55:011256 // This is a FindNext operation if we are searching for the same text again,
1257 // or if the passed in search text is empty (FindNext keyboard shortcut). The
1258 // exception to this is if the Find was aborted (then we don't want FindNext
1259 // because the highlighting has been cleared and we need it to reappear). We
1260 // therefore treat FindNext after an aborted Find operation as a full fledged
1261 // Find.
[email protected]c1dc9f132009-11-20 23:13:211262 bool find_next = (find_text_ == search_string || search_string.empty()) &&
[email protected]e491f1c2009-05-22 20:28:121263 (last_search_case_sensitive_ == case_sensitive) &&
[email protected]6e95706d2009-04-23 22:55:011264 !find_op_aborted_;
1265 if (!find_next)
1266 current_find_request_id_ = find_request_id_counter_++;
1267
[email protected]c1dc9f132009-11-20 23:13:211268 if (!search_string.empty())
1269 find_text_ = search_string;
[email protected]e491f1c2009-05-22 20:28:121270 last_search_case_sensitive_ = case_sensitive;
[email protected]6e95706d2009-04-23 22:55:011271
1272 find_op_aborted_ = false;
1273
1274 // Keep track of what the last search was across the tabs.
[email protected]e5d2f7132010-04-09 18:13:531275 FindBarState* find_bar_state = profile()->GetFindBarState();
1276 find_bar_state->set_last_prepopulate_text(find_text_);
[email protected]6e95706d2009-04-23 22:55:011277 render_view_host()->StartFinding(current_find_request_id_,
1278 find_text_,
1279 forward_direction,
[email protected]e491f1c2009-05-22 20:28:121280 case_sensitive,
[email protected]6e95706d2009-04-23 22:55:011281 find_next);
1282}
1283
[email protected]5bc8fe92010-03-11 18:19:001284void TabContents::StopFinding(
1285 FindBarController::SelectionAction selection_action) {
[email protected]d6e8d332010-06-04 22:26:011286 if (selection_action == FindBarController::kClearSelection) {
1287 // kClearSelection means the find string has been cleared by the user, but
1288 // the UI has not been dismissed. In that case we want to clear the
1289 // previously remembered search (http://crbug.com/42639).
1290 previous_find_text_ = string16();
1291 } else {
[email protected]2d2dffc2009-06-09 21:41:001292 find_ui_active_ = false;
[email protected]d6e8d332010-06-04 22:26:011293 if (!find_text_.empty())
1294 previous_find_text_ = find_text_;
1295 }
[email protected]101c90e2009-10-26 21:14:441296 find_text_.clear();
[email protected]6e95706d2009-04-23 22:55:011297 find_op_aborted_ = true;
[email protected]e491f1c2009-05-22 20:28:121298 last_search_result_ = FindNotificationDetails();
[email protected]5bc8fe92010-03-11 18:19:001299 render_view_host()->StopFinding(selection_action);
[email protected]6e95706d2009-04-23 22:55:011300}
1301
[email protected]420ae012009-04-24 05:16:321302void TabContents::OnSavePage() {
1303 // If we can not save the page, try to download it.
1304 if (!SavePackage::IsSavableContents(contents_mime_type())) {
1305 DownloadManager* dlm = profile()->GetDownloadManager();
1306 const GURL& current_page_url = GetURL();
1307 if (dlm && current_page_url.is_valid())
[email protected]d82ed61e2009-06-16 02:46:221308 dlm->DownloadUrl(current_page_url, GURL(), "", this);
[email protected]420ae012009-04-24 05:16:321309 return;
1310 }
1311
1312 Stop();
1313
1314 // Create the save package and possibly prompt the user for the name to save
1315 // the page as. The user prompt is an asynchronous operation that runs on
1316 // another thread.
[email protected]d82ed61e2009-06-16 02:46:221317 save_package_ = new SavePackage(this);
[email protected]420ae012009-04-24 05:16:321318 save_package_->GetSaveInfo();
1319}
1320
1321// Used in automated testing to bypass prompting the user for file names.
1322// Instead, the names and paths are hard coded rather than running them through
1323// file name sanitation and extension / mime checking.
[email protected]828cabe2009-09-26 22:47:111324bool TabContents::SavePage(const FilePath& main_file, const FilePath& dir_path,
[email protected]420ae012009-04-24 05:16:321325 SavePackage::SavePackageType save_type) {
1326 // Stop the page from navigating.
1327 Stop();
1328
[email protected]828cabe2009-09-26 22:47:111329 save_package_ = new SavePackage(this, save_type, main_file, dir_path);
[email protected]cdf6cc82009-08-04 21:48:591330 return save_package_->Init();
[email protected]420ae012009-04-24 05:16:321331}
1332
[email protected]89d6e6e2009-12-03 23:06:511333void TabContents::EmailPageLocation() {
1334 std::string title = EscapeQueryParamValue(UTF16ToUTF8(GetTitle()), false);
1335 std::string page_url = EscapeQueryParamValue(GetURL().spec(), false);
1336 std::string mailto = std::string("mailto:?subject=Fwd:%20") +
1337 title + "&body=%0A%0A" + page_url;
1338 platform_util::OpenExternal(GURL(mailto));
1339}
1340
[email protected]420ae012009-04-24 05:16:321341void TabContents::PrintPreview() {
1342 // We don't show the print preview yet, only the print dialog.
1343 PrintNow();
1344}
1345
1346bool TabContents::PrintNow() {
1347 // We can't print interstitial page for now.
1348 if (showing_interstitial_page())
1349 return false;
1350
1351 return render_view_host()->PrintPages();
1352}
1353
[email protected]82270452009-06-19 15:58:011354void TabContents::PrintingDone(int document_cookie, bool success) {
1355 render_view_host()->PrintingDone(document_cookie, success);
1356}
1357
[email protected]420ae012009-04-24 05:16:321358bool TabContents::IsActiveEntry(int32 page_id) {
1359 NavigationEntry* active_entry = controller_.GetActiveEntry();
1360 return (active_entry != NULL &&
1361 active_entry->site_instance() == GetSiteInstance() &&
1362 active_entry->page_id() == page_id);
1363}
1364
[email protected]b2fe07d12010-02-09 14:38:081365void TabContents::SetOverrideEncoding(const std::string& encoding) {
[email protected]8cb5d5b2010-02-09 11:36:161366 set_encoding(encoding);
1367 render_view_host()->SetPageEncoding(encoding);
1368}
1369
[email protected]b2fe07d12010-02-09 14:38:081370void TabContents::ResetOverrideEncoding() {
[email protected]8cb5d5b2010-02-09 11:36:161371 reset_encoding();
1372 render_view_host()->ResetPageEncodingToDefault();
1373}
1374
1375void TabContents::WindowMoveOrResizeStarted() {
1376 render_view_host()->WindowMoveOrResizeStarted();
1377}
1378
[email protected]3f8eb7f2009-10-02 23:58:051379void TabContents::LogNewTabTime(const std::string& event_name) {
1380 // Not all new tab pages get timed. In those cases, we don't have a
1381 // new_tab_start_time_.
1382 if (new_tab_start_time_.is_null())
1383 return;
1384
1385 base::TimeDelta duration = base::TimeTicks::Now() - new_tab_start_time_;
[email protected]84abba62009-10-07 17:01:441386 MetricEventDurationDetails details(event_name,
1387 static_cast<int>(duration.InMilliseconds()));
1388
[email protected]7ab1e7d62009-10-14 23:32:011389 if (event_name == "Tab.NewTabScriptStart") {
1390 UMA_HISTOGRAM_TIMES("Tab.NewTabScriptStart", duration);
1391 } else if (event_name == "Tab.NewTabDOMContentLoaded") {
1392 UMA_HISTOGRAM_TIMES("Tab.NewTabDOMContentLoaded", duration);
1393 } else if (event_name == "Tab.NewTabOnload") {
1394 UMA_HISTOGRAM_TIMES("Tab.NewTabOnload", duration);
[email protected]3f8eb7f2009-10-02 23:58:051395 // The new tab page has finished loading; reset it.
1396 new_tab_start_time_ = base::TimeTicks();
[email protected]84abba62009-10-07 17:01:441397 } else {
1398 NOTREACHED();
[email protected]3f8eb7f2009-10-02 23:58:051399 }
[email protected]84abba62009-10-07 17:01:441400 NotificationService::current()->Notify(
1401 NotificationType::METRIC_EVENT_DURATION,
1402 Source<TabContents>(this),
1403 Details<MetricEventDurationDetails>(&details));
[email protected]3f8eb7f2009-10-02 23:58:051404}
1405
[email protected]7ab1e7d62009-10-14 23:32:011406void TabContents::OnCloseStarted() {
1407 if (tab_close_start_time_.is_null())
1408 tab_close_start_time_ = base::TimeTicks::Now();
1409}
1410
[email protected]46624bf2010-06-09 16:04:191411bool TabContents::ShouldAcceptDragAndDrop() const {
1412#if defined(OS_CHROMEOS)
1413 // ChromeOS panels (pop-ups) do not take drag-n-drop.
1414 // See http://crosbug.com/2413
[email protected]b83af492010-10-09 03:21:201415 if (delegate() && delegate()->IsPopup(this))
1416 return false;
1417 return true;
[email protected]46624bf2010-06-09 16:04:191418#else
1419 return true;
1420#endif
1421}
1422
[email protected]ec0b6c42010-08-26 03:16:581423void TabContents::UpdateHistoryForNavigation(
1424 scoped_refptr<history::HistoryAddPageArgs> add_page_args) {
1425 if (profile()->IsOffTheRecord())
1426 return;
1427
1428 // Add to history service.
1429 HistoryService* hs = profile()->GetHistoryService(Profile::IMPLICIT_ACCESS);
1430 if (hs)
1431 hs->AddPage(*add_page_args);
1432}
1433
1434void TabContents::UpdateHistoryPageTitle(const NavigationEntry& entry) {
1435 if (profile()->IsOffTheRecord())
1436 return;
1437
1438 HistoryService* hs = profile()->GetHistoryService(Profile::IMPLICIT_ACCESS);
1439 if (hs)
1440 hs->SetPageTitle(entry.virtual_url(), entry.title());
1441}
1442
[email protected]b75b8292010-10-01 07:28:251443int TabContents::GetZoomPercent(bool* enable_increment,
1444 bool* enable_decrement) {
1445 *enable_decrement = *enable_increment = false;
1446 HostZoomMap* zoom_map = profile()->GetHostZoomMap();
1447 if (!zoom_map)
1448 return 100;
1449
1450 double zoom_level;
1451 if (temporary_zoom_settings_) {
1452 zoom_level = zoom_map->GetTemporaryZoomLevel(
1453 GetRenderProcessHost()->id(), render_view_host()->routing_id());
1454 } else {
1455 zoom_level = zoom_map->GetZoomLevel(GetURL());
1456 }
1457
[email protected]b75b8292010-10-01 07:28:251458 int percent = static_cast<int>(
1459 WebKit::WebView::zoomLevelToZoomFactor(zoom_level) * 100);
[email protected]b75b8292010-10-01 07:28:251460 *enable_decrement = percent > minimum_zoom_percent_;
1461 *enable_increment = percent < maximum_zoom_percent_;
1462 return percent;
1463}
1464
[email protected]96d185d2009-04-24 03:28:541465// Notifies the RenderWidgetHost instance about the fact that the page is
1466// loading, or done loading and calls the base implementation.
1467void TabContents::SetIsLoading(bool is_loading,
1468 LoadNotificationDetails* details) {
1469 if (is_loading == is_loading_)
1470 return;
1471
1472 if (!is_loading) {
1473 load_state_ = net::LOAD_STATE_IDLE;
1474 load_state_host_.clear();
[email protected]094e5b22009-09-25 04:23:561475 upload_size_ = 0;
1476 upload_position_ = 0;
[email protected]96d185d2009-04-24 03:28:541477 }
1478
1479 render_manager_.SetIsLoading(is_loading);
1480
1481 is_loading_ = is_loading;
1482 waiting_for_response_ = is_loading;
1483
[email protected]6ebdc9b2010-09-27 16:55:571484 if (delegate_)
1485 delegate_->LoadingStateChanged(this);
[email protected]329581b2009-04-28 06:52:351486 NotifyNavigationStateChanged(INVALIDATE_LOAD);
[email protected]96d185d2009-04-24 03:28:541487
1488 NotificationType type = is_loading ? NotificationType::LOAD_START :
1489 NotificationType::LOAD_STOP;
[email protected]ce5c4502009-05-06 16:46:111490 NotificationDetails det = NotificationService::NoDetails();
[email protected]96d185d2009-04-24 03:28:541491 if (details)
1492 det = Details<LoadNotificationDetails>(details);
1493 NotificationService::current()->Notify(type,
1494 Source<NavigationController>(&controller_),
1495 det);
1496}
1497
[email protected]b6c874582009-05-08 19:38:311498void TabContents::AddPopup(TabContents* new_contents,
[email protected]7e7414ae2010-01-26 20:19:291499 const gfx::Rect& initial_pos) {
[email protected]57eda82a2010-05-05 21:28:061500 // A page can't spawn popups (or do anything else, either) until its load
1501 // commits, so when we reach here, the popup was spawned by the
1502 // NavigationController's last committed entry, not the active entry. For
1503 // example, if a page opens a popup in an onunload() handler, then the active
1504 // entry is the page to be loaded as we navigate away from the unloading
1505 // page. For this reason, we can't use GetURL() to get the opener URL,
1506 // because it returns the active entry.
1507 NavigationEntry* entry = controller_.GetLastCommittedEntry();
1508 GURL creator = entry ? entry->virtual_url() : GURL::EmptyGURL();
1509
1510 if (creator.is_valid() &&
[email protected]8cc8d492010-02-02 10:40:491511 profile()->GetHostContentSettingsMap()->GetContentSetting(
[email protected]ca352452010-08-06 11:14:091512 creator, CONTENT_SETTINGS_TYPE_POPUPS, "") == CONTENT_SETTING_ALLOW) {
[email protected]8cc8d492010-02-02 10:40:491513 AddNewContents(new_contents, NEW_POPUP, initial_pos, true);
1514 } else {
1515 if (!blocked_popups_)
1516 blocked_popups_ = new BlockedPopupContainer(this);
1517 blocked_popups_->AddTabContents(new_contents, initial_pos);
[email protected]55126132010-08-19 14:53:281518 content_settings_delegate_->OnContentBlocked(CONTENT_SETTINGS_TYPE_POPUPS,
1519 std::string());
[email protected]8cc8d492010-02-02 10:40:491520 }
[email protected]b9681312008-11-07 00:08:261521}
[email protected]616ed5a2008-11-21 22:27:241522
[email protected]616ed5a2008-11-21 22:27:241523void TabContents::ExpireInfoBars(
1524 const NavigationController::LoadCommittedDetails& details) {
1525 // Only hide InfoBars when the user has done something that makes the main
1526 // frame load. We don't want various automatic or subframe navigations making
1527 // it disappear.
1528 if (!details.is_user_initiated_main_frame_load())
1529 return;
1530
[email protected]f86a07022008-11-25 01:06:051531 for (int i = infobar_delegate_count() - 1; i >= 0; --i) {
[email protected]616ed5a2008-11-21 22:27:241532 InfoBarDelegate* delegate = GetInfoBarDelegateAt(i);
[email protected]cdadf6f2010-08-20 16:36:081533 if (!delegate) {
1534 // If you hit this NOTREACHED, please comment in bug
1535 // http://crbug.com/50428 how you got there.
1536 NOTREACHED();
1537 continue;
1538 }
1539
[email protected]f86a07022008-11-25 01:06:051540 if (delegate->ShouldExpire(details))
[email protected]616ed5a2008-11-21 22:27:241541 RemoveInfoBar(delegate);
[email protected]616ed5a2008-11-21 22:27:241542 }
1543}
[email protected]fdd61c62009-04-22 19:22:571544
[email protected]96d185d2009-04-24 03:28:541545DOMUI* TabContents::GetDOMUIForCurrentState() {
1546 // When there is a pending navigation entry, we want to use the pending DOMUI
1547 // that goes along with it to control the basic flags. For example, we want to
1548 // show the pending URL in the URL bar, so we want the display_url flag to
1549 // be from the pending entry.
1550 //
1551 // The confusion comes because there are multiple possibilities for the
1552 // initial load in a tab as a side effect of the way the RenderViewHostManager
1553 // works.
1554 //
1555 // - For the very first tab the load looks "normal". The new tab DOM UI is
1556 // the pending one, and we want it to apply here.
1557 //
1558 // - For subsequent new tabs, they'll get a new SiteInstance which will then
1559 // get switched to the one previously associated with the new tab pages.
1560 // This switching will cause the manager to commit the RVH/DOMUI. So we'll
1561 // have a committed DOM UI in this case.
1562 //
1563 // This condition handles all of these cases:
1564 //
1565 // - First load in first tab: no committed nav entry + pending nav entry +
1566 // pending dom ui:
1567 // -> Use pending DOM UI if any.
1568 //
1569 // - First load in second tab: no committed nav entry + pending nav entry +
1570 // no pending DOM UI:
1571 // -> Use the committed DOM UI if any.
1572 //
1573 // - Second navigation in any tab: committed nav entry + pending nav entry:
1574 // -> Use pending DOM UI if any.
1575 //
1576 // - Normal state with no load: committed nav entry + no pending nav entry:
1577 // -> Use committed DOM UI.
1578 if (controller_.pending_entry() &&
1579 (controller_.GetLastCommittedEntry() ||
1580 render_manager_.pending_dom_ui()))
1581 return render_manager_.pending_dom_ui();
1582 return render_manager_.dom_ui();
1583}
[email protected]420ae012009-04-24 05:16:321584
1585void TabContents::DidNavigateMainFramePostCommit(
1586 const NavigationController::LoadCommittedDetails& details,
1587 const ViewHostMsg_FrameNavigate_Params& params) {
[email protected]c2e74fe82009-09-03 17:57:441588 if (opener_dom_ui_type_ != DOMUIFactory::kNoDOMUI) {
1589 // If this is a window.open navigation, use the same DOMUI as the renderer
1590 // that opened the window, as long as both renderers have the same
1591 // privileges.
[email protected]583d45c12010-08-31 02:48:121592 if (opener_dom_ui_type_ ==
1593 DOMUIFactory::GetDOMUIType(profile(), GetURL())) {
[email protected]c2e74fe82009-09-03 17:57:441594 DOMUI* dom_ui = DOMUIFactory::CreateDOMUIForURL(this, GetURL());
1595 // dom_ui might be NULL if the URL refers to a non-existent extension.
1596 if (dom_ui) {
1597 render_manager_.SetDOMUIPostCommit(dom_ui);
1598 dom_ui->RenderViewCreated(render_view_host());
1599 }
1600 }
1601 opener_dom_ui_type_ = DOMUIFactory::kNoDOMUI;
1602 }
1603
[email protected]420ae012009-04-24 05:16:321604 if (details.is_user_initiated_main_frame_load()) {
1605 // Clear the status bubble. This is a workaround for a bug where WebKit
1606 // doesn't let us know that the cursor left an element during a
1607 // transition (this is also why the mouse cursor remains as a hand after
1608 // clicking on a link); see bugs 1184641 and 980803. We don't want to
1609 // clear the bubble when a user navigates to a named anchor in the same
1610 // page.
1611 UpdateTargetURL(details.entry->page_id(), GURL());
1612
1613 // UpdateHelpersForDidNavigate will handle the case where the password_form
1614 // origin is valid.
1615 // TODO(brettw) bug 1343111: Password manager stuff in here needs to be
1616 // cleaned up and covered by tests.
1617 if (!params.password_form.origin.is_valid())
1618 GetPasswordManager()->DidNavigate();
1619 }
1620
1621 // The keyword generator uses the navigation entries, so must be called after
1622 // the commit.
1623 GenerateKeywordIfNecessary(params);
1624
1625 // Allow the new page to set the title again.
1626 received_page_title_ = false;
1627
1628 // Get the favicon, either from history or request it from the net.
1629 fav_icon_helper_.FetchFavIcon(details.entry->url());
1630
[email protected]0de80162010-02-03 04:52:351631 // Clear all page actions, blocked content notifications and browser actions
1632 // for this tab, unless this is an in-page navigation.
[email protected]a6e82fc2010-02-24 22:28:141633 if (!details.is_in_page) {
[email protected]92c6f9b92009-10-24 04:35:081634 ExtensionsService* service = profile()->GetExtensionsService();
1635 if (service) {
1636 for (size_t i = 0; i < service->extensions()->size(); ++i) {
[email protected]5d246db22009-10-27 06:17:571637 ExtensionAction* browser_action =
[email protected]92c6f9b92009-10-24 04:35:081638 service->extensions()->at(i)->browser_action();
[email protected]56ce6e52009-10-27 00:10:521639 if (browser_action) {
1640 browser_action->ClearAllValuesForTab(controller().session_id().id());
1641 NotificationService::current()->Notify(
1642 NotificationType::EXTENSION_BROWSER_ACTION_UPDATED,
[email protected]5d246db22009-10-27 06:17:571643 Source<ExtensionAction>(browser_action),
[email protected]56ce6e52009-10-27 00:10:521644 NotificationService::NoDetails());
1645 }
[email protected]92c6f9b92009-10-24 04:35:081646
[email protected]5d246db22009-10-27 06:17:571647 ExtensionAction* page_action =
[email protected]56ce6e52009-10-27 00:10:521648 service->extensions()->at(i)->page_action();
1649 if (page_action) {
1650 page_action->ClearAllValuesForTab(controller().session_id().id());
1651 PageActionStateChanged();
1652 }
[email protected]92c6f9b92009-10-24 04:35:081653 }
[email protected]aece2c7f2009-08-27 20:43:171654 }
[email protected]0de80162010-02-03 04:52:351655
1656 // Close blocked popups.
1657 if (blocked_popups_) {
[email protected]0fbd70332010-06-01 19:28:341658 AutoReset<bool> auto_reset(&dont_notify_render_view_, true);
[email protected]0de80162010-02-03 04:52:351659 blocked_popups_->Destroy();
[email protected]da7b5262010-02-25 21:12:461660 blocked_popups_ = NULL;
[email protected]0de80162010-02-03 04:52:351661 }
1662
1663 // Clear "blocked" flags.
[email protected]da4f8a12010-08-19 08:33:411664 content_settings_delegate_->ClearBlockedContentSettingsExceptForCookies();
[email protected]9fb83e82010-07-02 18:24:551665 content_settings_delegate_->GeolocationDidNavigate(details);
[email protected]f17a0ee2010-05-17 17:38:471666
1667 // Once the main frame is navigated, we're no longer considered to have
1668 // displayed insecure content.
1669 displayed_insecure_content_ = false;
[email protected]aece2c7f2009-08-27 20:43:171670 }
[email protected]ce5c4502009-05-06 16:46:111671
[email protected]8cc8d492010-02-02 10:40:491672 // Close constrained windows if necessary.
1673 if (!net::RegistryControlledDomainService::SameDomainOrHost(
1674 details.previous_url, details.entry->url()))
1675 CloseConstrainedWindows();
1676
[email protected]420ae012009-04-24 05:16:321677 // Update the starred state.
1678 UpdateStarredStateForCurrentURL();
[email protected]c07c9752010-03-12 05:57:531679
1680 // Clear the cache of forms in AutoFill.
1681 if (autofill_manager_.get())
1682 autofill_manager_->Reset();
[email protected]420ae012009-04-24 05:16:321683}
1684
1685void TabContents::DidNavigateAnyFramePostCommit(
1686 RenderViewHost* render_view_host,
1687 const NavigationController::LoadCommittedDetails& details,
1688 const ViewHostMsg_FrameNavigate_Params& params) {
1689 // If we navigate, start showing messages again. This does nothing to prevent
1690 // a malicious script from spamming messages, since the script could just
1691 // reload the page to stop blocking.
1692 suppress_javascript_messages_ = false;
1693
[email protected]420ae012009-04-24 05:16:321694 // Notify the password manager of the navigation or form submit.
1695 // TODO(brettw) bug 1343111: Password manager stuff in here needs to be
1696 // cleaned up and covered by tests.
1697 if (params.password_form.origin.is_valid())
1698 GetPasswordManager()->ProvisionallySavePassword(params.password_form);
[email protected]3b1c1812010-02-12 21:53:551699
1700 // Let the LanguageState clear its state.
[email protected]80fc6112010-08-13 20:10:581701 language_state_.DidNavigate(details);
[email protected]420ae012009-04-24 05:16:321702}
1703
[email protected]8cc8d492010-02-02 10:40:491704void TabContents::CloseConstrainedWindows() {
1705 // Clear out any constrained windows since we are leaving this page entirely.
[email protected]420ae012009-04-24 05:16:321706 // We use indices instead of iterators in case CloseWindow does something
1707 // that may invalidate an iterator.
1708 int size = static_cast<int>(child_windows_.size());
1709 for (int i = size - 1; i >= 0; --i) {
1710 ConstrainedWindow* window = child_windows_[i];
[email protected]fa1cf0b82010-01-15 21:49:441711 if (window) {
[email protected]420ae012009-04-24 05:16:321712 window->CloseConstrainedWindow();
[email protected]fa1cf0b82010-01-15 21:49:441713 BlockTabContent(false);
1714 }
[email protected]420ae012009-04-24 05:16:321715 }
1716}
1717
1718void TabContents::UpdateStarredStateForCurrentURL() {
1719 BookmarkModel* model = profile()->GetBookmarkModel();
1720 const bool old_state = is_starred_;
1721 is_starred_ = (model && model->IsBookmarked(GetURL()));
1722
1723 if (is_starred_ != old_state && delegate())
1724 delegate()->URLStarredChanged(this, is_starred_);
1725}
1726
1727void TabContents::UpdateAlternateErrorPageURL() {
1728 GURL url = GetAlternateErrorPageURL();
1729 render_view_host()->SetAlternateErrorPageURL(url);
1730}
1731
1732void TabContents::UpdateWebPreferences() {
1733 render_view_host()->UpdateWebPreferences(GetWebkitPrefs());
1734}
1735
1736void TabContents::UpdateMaxPageIDIfNecessary(SiteInstance* site_instance,
1737 RenderViewHost* rvh) {
1738 // If we are creating a RVH for a restored controller, then we might
1739 // have more page IDs than the SiteInstance's current max page ID. We must
1740 // make sure that the max page ID is larger than any restored page ID.
1741 // Note that it is ok for conflicting page IDs to exist in another tab
1742 // (i.e., NavigationController), but if any page ID is larger than the max,
1743 // the back/forward list will get confused.
1744 int max_restored_page_id = controller_.max_restored_page_id();
1745 if (max_restored_page_id > 0) {
1746 int curr_max_page_id = site_instance->max_page_id();
1747 if (max_restored_page_id > curr_max_page_id) {
1748 // Need to update the site instance immediately.
1749 site_instance->UpdateMaxPageID(max_restored_page_id);
1750
1751 // Also tell the renderer to update its internal representation. We
1752 // need to reserve enough IDs to make all restored page IDs less than
1753 // the max.
1754 if (curr_max_page_id < 0)
1755 curr_max_page_id = 0;
1756 rvh->ReservePageIDRange(max_restored_page_id - curr_max_page_id);
1757 }
1758 }
1759}
1760
[email protected]ec0b6c42010-08-26 03:16:581761scoped_refptr<history::HistoryAddPageArgs>
1762TabContents::CreateHistoryAddPageArgs(
[email protected]ebe89e062009-08-13 23:16:541763 const GURL& virtual_url,
[email protected]befd8d822009-07-01 04:51:471764 const NavigationController::LoadCommittedDetails& details,
[email protected]420ae012009-04-24 05:16:321765 const ViewHostMsg_FrameNavigate_Params& params) {
[email protected]ec0b6c42010-08-26 03:16:581766 scoped_refptr<history::HistoryAddPageArgs> add_page_args(
1767 new history::HistoryAddPageArgs(
1768 params.url, base::Time::Now(), this, params.page_id, params.referrer,
1769 params.redirects, params.transition, history::SOURCE_BROWSED,
1770 details.did_replace_entry));
1771 if (PageTransition::IsMainFrame(params.transition) &&
1772 virtual_url != params.url) {
1773 // Hack on the "virtual" URL so that it will appear in history. For some
1774 // types of URLs, we will display a magic URL that is different from where
1775 // the page is actually navigated. We want the user to see in history what
1776 // they saw in the URL bar, so we add the virtual URL as a redirect. This
1777 // only applies to the main frame, as the virtual URL doesn't apply to
1778 // sub-frames.
1779 add_page_args->url = virtual_url;
1780 if (!add_page_args->redirects.empty())
1781 add_page_args->redirects.back() = virtual_url;
[email protected]420ae012009-04-24 05:16:321782 }
[email protected]ec0b6c42010-08-26 03:16:581783 return add_page_args;
[email protected]420ae012009-04-24 05:16:321784}
1785
1786bool TabContents::UpdateTitleForEntry(NavigationEntry* entry,
1787 const std::wstring& title) {
1788 // For file URLs without a title, use the pathname instead. In the case of a
1789 // synthesized title, we don't want the update to count toward the "one set
1790 // per page of the title to history."
[email protected]e53668962010-06-23 15:35:251791 string16 final_title;
[email protected]420ae012009-04-24 05:16:321792 bool explicit_set;
1793 if (entry->url().SchemeIsFile() && title.empty()) {
[email protected]e53668962010-06-23 15:35:251794 final_title = UTF8ToUTF16(entry->url().ExtractFileName());
[email protected]420ae012009-04-24 05:16:321795 explicit_set = false; // Don't count synthetic titles toward the set limit.
1796 } else {
[email protected]e53668962010-06-23 15:35:251797 TrimWhitespace(WideToUTF16Hack(title), TRIM_ALL, &final_title);
[email protected]420ae012009-04-24 05:16:321798 explicit_set = true;
1799 }
1800
[email protected]e53668962010-06-23 15:35:251801 if (final_title == entry->title())
[email protected]420ae012009-04-24 05:16:321802 return false; // Nothing changed, don't bother.
1803
[email protected]e53668962010-06-23 15:35:251804 entry->set_title(final_title);
[email protected]420ae012009-04-24 05:16:321805
[email protected]ec0b6c42010-08-26 03:16:581806 if (!received_page_title_) {
1807 UpdateHistoryPageTitle(*entry);
[email protected]420ae012009-04-24 05:16:321808 received_page_title_ = explicit_set;
1809 }
1810
1811 // Lastly, set the title for the view.
[email protected]e53668962010-06-23 15:35:251812 view_->SetPageTitle(UTF16ToWideHack(final_title));
[email protected]420ae012009-04-24 05:16:321813
[email protected]cbc0e1b2010-04-12 18:33:041814 NotificationService::current()->Notify(
1815 NotificationType::TAB_CONTENTS_TITLE_UPDATED,
1816 Source<TabContents>(this),
1817 NotificationService::NoDetails());
1818
[email protected]420ae012009-04-24 05:16:321819 return true;
1820}
1821
1822void TabContents::NotifySwapped() {
1823 // After sending out a swap notification, we need to send a disconnect
1824 // notification so that clients that pick up a pointer to |this| can NULL the
1825 // pointer. See Bug 1230284.
1826 notify_disconnection_ = true;
1827 NotificationService::current()->Notify(
[email protected]57c6a652009-05-04 07:58:341828 NotificationType::TAB_CONTENTS_SWAPPED,
[email protected]d82ed61e2009-06-16 02:46:221829 Source<TabContents>(this),
[email protected]420ae012009-04-24 05:16:321830 NotificationService::NoDetails());
1831}
1832
1833void TabContents::NotifyConnected() {
1834 notify_disconnection_ = true;
1835 NotificationService::current()->Notify(
[email protected]57c6a652009-05-04 07:58:341836 NotificationType::TAB_CONTENTS_CONNECTED,
[email protected]d82ed61e2009-06-16 02:46:221837 Source<TabContents>(this),
[email protected]420ae012009-04-24 05:16:321838 NotificationService::NoDetails());
1839}
1840
1841void TabContents::NotifyDisconnected() {
1842 if (!notify_disconnection_)
1843 return;
1844
1845 notify_disconnection_ = false;
1846 NotificationService::current()->Notify(
[email protected]57c6a652009-05-04 07:58:341847 NotificationType::TAB_CONTENTS_DISCONNECTED,
[email protected]d82ed61e2009-06-16 02:46:221848 Source<TabContents>(this),
[email protected]420ae012009-04-24 05:16:321849 NotificationService::NoDetails());
1850}
1851
1852void TabContents::GenerateKeywordIfNecessary(
1853 const ViewHostMsg_FrameNavigate_Params& params) {
1854 if (!params.searchable_form_url.is_valid())
1855 return;
1856
1857 if (profile()->IsOffTheRecord())
1858 return;
1859
1860 int last_index = controller_.last_committed_entry_index();
1861 // When there was no previous page, the last index will be 0. This is
1862 // normally due to a form submit that opened in a new tab.
1863 // TODO(brettw) bug 916126: we should support keywords when form submits
1864 // happen in new tabs.
1865 if (last_index <= 0)
1866 return;
1867 const NavigationEntry* previous_entry =
1868 controller_.GetEntryAtIndex(last_index - 1);
1869 if (IsFormSubmit(previous_entry)) {
1870 // Only generate a keyword if the previous page wasn't itself a form
1871 // submit.
1872 return;
1873 }
1874
1875 GURL keyword_url = previous_entry->user_typed_url().is_valid() ?
1876 previous_entry->user_typed_url() : previous_entry->url();
1877 std::wstring keyword =
1878 TemplateURLModel::GenerateKeyword(keyword_url, true); // autodetected
1879 if (keyword.empty())
1880 return;
1881
1882 TemplateURLModel* url_model = profile()->GetTemplateURLModel();
1883 if (!url_model)
1884 return;
1885
1886 if (!url_model->loaded()) {
1887 url_model->Load();
1888 return;
1889 }
1890
1891 const TemplateURL* current_url;
[email protected]ddd231e2010-06-29 20:35:191892 GURL url = params.searchable_form_url;
[email protected]420ae012009-04-24 05:16:321893 if (!url_model->CanReplaceKeyword(keyword, url, &current_url))
1894 return;
1895
1896 if (current_url) {
1897 if (current_url->originating_url().is_valid()) {
1898 // The existing keyword was generated from an OpenSearch description
1899 // document, don't regenerate.
1900 return;
1901 }
1902 url_model->Remove(current_url);
1903 }
1904 TemplateURL* new_url = new TemplateURL();
1905 new_url->set_keyword(keyword);
1906 new_url->set_short_name(keyword);
[email protected]ddd231e2010-06-29 20:35:191907 new_url->SetURL(url.spec(), 0, 0);
[email protected]420ae012009-04-24 05:16:321908 new_url->add_input_encoding(params.searchable_form_encoding);
1909 DCHECK(controller_.GetLastCommittedEntry());
1910 const GURL& favicon_url =
1911 controller_.GetLastCommittedEntry()->favicon().url();
1912 if (favicon_url.is_valid()) {
1913 new_url->SetFavIconURL(favicon_url);
1914 } else {
1915 // The favicon url isn't valid. This means there really isn't a favicon,
1916 // or the favicon url wasn't obtained before the load started. This assumes
1917 // the later.
1918 // TODO(sky): Need a way to set the favicon that doesn't involve generating
1919 // its url.
1920 new_url->SetFavIconURL(TemplateURL::GenerateFaviconURL(params.referrer));
1921 }
1922 new_url->set_safe_for_autoreplace(true);
1923 url_model->Add(new_url);
1924}
1925
[email protected]bf5c2ff392009-07-08 16:24:331926void TabContents::OnUserGesture() {
1927 // See comment in RenderViewHostDelegate::OnUserGesture as to why we do this.
[email protected]41291322010-07-15 17:09:011928 DownloadRequestLimiter* limiter =
1929 g_browser_process->download_request_limiter();
1930 if (limiter)
1931 limiter->OnUserGesture(this);
[email protected]d070ec62010-07-27 21:28:261932 ExternalProtocolHandler::PermitLaunchUrl();
[email protected]bf5c2ff392009-07-08 16:24:331933}
1934
1935void TabContents::OnFindReply(int request_id,
1936 int number_of_matches,
1937 const gfx::Rect& selection_rect,
1938 int active_match_ordinal,
1939 bool final_update) {
[email protected]3ce7ced2009-07-24 18:52:421940 // Ignore responses for requests that have been aborted.
1941 if (find_op_aborted_)
1942 return;
1943
[email protected]bf5c2ff392009-07-08 16:24:331944 // Ignore responses for requests other than the one we have most recently
1945 // issued. That way we won't act on stale results when the user has
1946 // already typed in another query.
1947 if (request_id != current_find_request_id_)
1948 return;
1949
1950 if (number_of_matches == -1)
1951 number_of_matches = last_search_result_.number_of_matches();
1952 if (active_match_ordinal == -1)
1953 active_match_ordinal = last_search_result_.active_match_ordinal();
1954
1955 gfx::Rect selection = selection_rect;
1956 if (selection.IsEmpty())
1957 selection = last_search_result_.selection_rect();
1958
1959 // Notify the UI, automation and any other observers that a find result was
1960 // found.
1961 last_search_result_ = FindNotificationDetails(request_id, number_of_matches,
1962 selection, active_match_ordinal,
1963 final_update);
1964 NotificationService::current()->Notify(
1965 NotificationType::FIND_RESULT_AVAILABLE,
1966 Source<TabContents>(this),
1967 Details<FindNotificationDetails>(&last_search_result_));
1968}
1969
1970void TabContents::GoToEntryAtOffset(int offset) {
[email protected]876bc832010-09-07 16:29:541971 if (!delegate_ || delegate_->OnGoToEntryOffset(offset)) {
1972 NavigationEntry* entry = controller_.GetEntryAtOffset(offset);
1973 if (!entry)
1974 return;
1975 // Note that we don't call NavigationController::GotToOffset() as we don't
1976 // want to create a pending navigation entry (it might end up lingering
1977 // http://crbug.com/51680).
[email protected]784688a62010-09-13 07:06:521978 entry->set_transition_type(entry->transition_type() |
1979 PageTransition::FORWARD_BACK);
[email protected]876bc832010-09-07 16:29:541980 NavigateToEntry(*entry, NavigationController::NO_RELOAD);
1981 }
[email protected]bf5c2ff392009-07-08 16:24:331982}
1983
[email protected]bf5c2ff392009-07-08 16:24:331984void TabContents::OnMissingPluginStatus(int status) {
1985#if defined(OS_WIN)
1986// TODO(PORT): pull in when plug-ins work
1987 GetPluginInstaller()->OnMissingPluginStatus(status);
1988#endif
1989}
1990
1991void TabContents::OnCrashedPlugin(const FilePath& plugin_path) {
[email protected]bf5c2ff392009-07-08 16:24:331992 DCHECK(!plugin_path.value().empty());
1993
1994 std::wstring plugin_name = plugin_path.ToWStringHack();
[email protected]d32d46182009-07-23 00:09:351995#if defined(OS_WIN) || defined(OS_MACOSX)
[email protected]bf5c2ff392009-07-08 16:24:331996 scoped_ptr<FileVersionInfo> version_info(
1997 FileVersionInfo::CreateFileVersionInfo(plugin_path));
1998 if (version_info.get()) {
1999 const std::wstring& product_name = version_info->product_name();
[email protected]996fd702009-09-04 19:12:372000 if (!product_name.empty()) {
[email protected]bf5c2ff392009-07-08 16:24:332001 plugin_name = product_name;
[email protected]996fd702009-09-04 19:12:372002#if defined(OS_MACOSX)
2003 // Many plugins on the Mac have .plugin in the actual name, which looks
2004 // terrible, so look for that and strip it off if present.
2005 const std::wstring plugin_extension(L".plugin");
2006 if (EndsWith(plugin_name, plugin_extension, true))
2007 plugin_name.erase(plugin_name.length() - plugin_extension.length());
2008#endif // OS_MACOSX
2009 }
[email protected]bf5c2ff392009-07-08 16:24:332010 }
[email protected]4a560ed2009-07-13 23:35:262011#else
2012 NOTIMPLEMENTED() << " convert plugin path to plugin name";
2013#endif
[email protected]2ae8a922010-06-28 20:27:532014 SkBitmap* crash_icon = ResourceBundle::GetSharedInstance().GetBitmapNamed(
2015 IDR_INFOBAR_PLUGIN_CRASHED);
[email protected]bf5c2ff392009-07-08 16:24:332016 AddInfoBar(new SimpleAlertInfoBarDelegate(
[email protected]e23d3a32010-08-13 19:39:582017 this, l10n_util::GetStringFUTF16(IDS_PLUGIN_CRASHED_PROMPT,
2018 WideToUTF16Hack(plugin_name)),
[email protected]2ae8a922010-06-28 20:27:532019 crash_icon, true));
[email protected]bf5c2ff392009-07-08 16:24:332020}
2021
2022void TabContents::OnCrashedWorker() {
2023 AddInfoBar(new SimpleAlertInfoBarDelegate(
[email protected]e23d3a32010-08-13 19:39:582024 this, l10n_util::GetStringUTF16(IDS_WEBWORKER_CRASHED_PROMPT),
[email protected]938e1f92010-04-01 18:09:422025 NULL, true));
[email protected]bf5c2ff392009-07-08 16:24:332026}
2027
2028void TabContents::OnDidGetApplicationInfo(
2029 int32 page_id,
2030 const webkit_glue::WebApplicationInfo& info) {
[email protected]ed5431872009-11-17 08:39:512031 web_app_info_ = info;
[email protected]bf5c2ff392009-07-08 16:24:332032
[email protected]ed5431872009-11-17 08:39:512033 if (delegate())
2034 delegate()->OnDidGetApplicationInfo(this, page_id);
[email protected]bf5c2ff392009-07-08 16:24:332035}
2036
[email protected]851b1eb2010-08-09 13:32:292037void TabContents::OnDisabledOutdatedPlugin(const string16& name,
2038 const GURL& update_url) {
2039 new DisabledPluginInfoBar(this, name, update_url);
2040}
2041
[email protected]a2cf65eb2010-01-18 08:20:382042void TabContents::OnPageContents(const GURL& url,
2043 int renderer_process_id,
2044 int32 page_id,
[email protected]e5106202010-06-11 21:12:362045 const string16& contents,
[email protected]1c57b7b2010-07-12 17:38:102046 const std::string& language,
2047 bool page_translatable) {
[email protected]a2cf65eb2010-01-18 08:20:382048 // Don't index any https pages. People generally don't want their bank
2049 // accounts, etc. indexed on their computer, especially since some of these
2050 // things are not marked cachable.
2051 // TODO(brettw) we may want to consider more elaborate heuristics such as
2052 // the cachability of the page. We may also want to consider subframes (this
2053 // test will still index subframes if the subframe is SSL).
[email protected]ccd40a52010-05-11 16:15:272054 // TODO(zelidrag) bug chromium-os:2808 - figure out if we want to reenable
2055 // content indexing for chromeos in some future releases.
2056#if !defined(OS_CHROMEOS)
[email protected]a2cf65eb2010-01-18 08:20:382057 if (!url.SchemeIsSecure()) {
2058 Profile* p = profile();
2059 if (p && !p->IsOffTheRecord()) {
2060 HistoryService* hs = p->GetHistoryService(Profile::IMPLICIT_ACCESS);
2061 if (hs)
2062 hs->SetPageContents(url, contents);
2063 }
2064 }
[email protected]ccd40a52010-05-11 16:15:272065#endif
[email protected]a8a81292010-01-21 00:32:452066
[email protected]1c57b7b2010-07-12 17:38:102067 language_state_.LanguageDetermined(language, page_translatable);
[email protected]a8a81292010-01-21 00:32:452068
2069 std::string lang = language;
2070 NotificationService::current()->Notify(
2071 NotificationType::TAB_LANGUAGE_DETERMINED,
[email protected]7e0831b2010-02-01 08:45:152072 Source<TabContents>(this),
[email protected]a8a81292010-01-21 00:32:452073 Details<std::string>(&lang));
[email protected]a2cf65eb2010-01-18 08:20:382074}
2075
[email protected]7e0831b2010-02-01 08:45:152076void TabContents::OnPageTranslated(int32 page_id,
2077 const std::string& original_lang,
[email protected]152b8ba32010-03-29 19:40:162078 const std::string& translated_lang,
2079 TranslateErrors::Type error_type) {
[email protected]3b1c1812010-02-12 21:53:552080 language_state_.set_current_language(translated_lang);
2081 language_state_.set_translation_pending(false);
[email protected]152b8ba32010-03-29 19:40:162082 PageTranslatedDetails details(original_lang, translated_lang, error_type);
[email protected]7e0831b2010-02-01 08:45:152083 NotificationService::current()->Notify(
2084 NotificationType::PAGE_TRANSLATED,
2085 Source<TabContents>(this),
[email protected]152b8ba32010-03-29 19:40:162086 Details<PageTranslatedDetails>(&details));
[email protected]7e0831b2010-02-01 08:45:152087}
2088
[email protected]15d9c0c2010-09-10 22:36:262089void TabContents::OnSetSuggestResult(int32 page_id, const std::string& result) {
2090 if (delegate())
2091 delegate()->OnSetSuggestResult(page_id, result);
2092}
2093
[email protected]bf5c2ff392009-07-08 16:24:332094void TabContents::DidStartProvisionalLoadForFrame(
2095 RenderViewHost* render_view_host,
[email protected]dabb0d12010-10-05 12:50:072096 long long frame_id,
[email protected]bf5c2ff392009-07-08 16:24:332097 bool is_main_frame,
2098 const GURL& url) {
2099 ProvisionalLoadDetails details(is_main_frame,
2100 controller_.IsURLInPageNavigation(url),
[email protected]dabb0d12010-10-05 12:50:072101 url, std::string(), false, frame_id);
[email protected]bf5c2ff392009-07-08 16:24:332102 NotificationService::current()->Notify(
2103 NotificationType::FRAME_PROVISIONAL_LOAD_START,
2104 Source<NavigationController>(&controller_),
2105 Details<ProvisionalLoadDetails>(&details));
[email protected]4f8452d12010-09-02 16:13:142106 if (is_main_frame) {
[email protected]da4f8a12010-08-19 08:33:412107 content_settings_delegate_->ClearCookieSpecificContentSettings();
[email protected]4f8452d12010-09-02 16:13:142108 content_settings_delegate_->ClearGeolocationContentSettings();
2109 }
[email protected]bf5c2ff392009-07-08 16:24:332110}
2111
2112void TabContents::DidStartReceivingResourceResponse(
[email protected]3dbb80b2010-02-09 22:41:202113 const ResourceRequestDetails& details) {
[email protected]bf5c2ff392009-07-08 16:24:332114 NotificationService::current()->Notify(
2115 NotificationType::RESOURCE_RESPONSE_STARTED,
2116 Source<NavigationController>(&controller()),
[email protected]3dbb80b2010-02-09 22:41:202117 Details<const ResourceRequestDetails>(&details));
[email protected]bf5c2ff392009-07-08 16:24:332118}
2119
[email protected]3dbb80b2010-02-09 22:41:202120void TabContents::DidRedirectResource(
2121 const ResourceRedirectDetails& details) {
[email protected]bf5c2ff392009-07-08 16:24:332122 NotificationService::current()->Notify(
2123 NotificationType::RESOURCE_RECEIVED_REDIRECT,
2124 Source<NavigationController>(&controller()),
[email protected]3dbb80b2010-02-09 22:41:202125 Details<const ResourceRequestDetails>(&details));
[email protected]bf5c2ff392009-07-08 16:24:332126}
2127
2128void TabContents::DidLoadResourceFromMemoryCache(
2129 const GURL& url,
2130 const std::string& frame_origin,
2131 const std::string& main_frame_origin,
2132 const std::string& security_info) {
2133 // Send out a notification that we loaded a resource from our memory cache.
[email protected]c88d24f12010-09-02 02:07:442134 int cert_id = 0, cert_status = 0, security_bits = -1, connection_status = 0;
[email protected]bf5c2ff392009-07-08 16:24:332135 SSLManager::DeserializeSecurityInfo(security_info,
2136 &cert_id, &cert_status,
[email protected]fc7de492010-07-12 14:49:042137 &security_bits,
2138 &connection_status);
[email protected]bf5c2ff392009-07-08 16:24:332139 LoadFromMemoryCacheDetails details(url, frame_origin, main_frame_origin,
[email protected]8cb5d5b2010-02-09 11:36:162140 GetRenderProcessHost()->id(), cert_id,
2141 cert_status);
[email protected]bf5c2ff392009-07-08 16:24:332142
2143 NotificationService::current()->Notify(
2144 NotificationType::LOAD_FROM_MEMORY_CACHE,
2145 Source<NavigationController>(&controller_),
2146 Details<LoadFromMemoryCacheDetails>(&details));
2147}
2148
[email protected]e3d60e5d2009-09-25 21:08:292149void TabContents::DidDisplayInsecureContent() {
[email protected]f17a0ee2010-05-17 17:38:472150 displayed_insecure_content_ = true;
2151 SSLManager::NotifySSLInternalStateChanged();
[email protected]e3d60e5d2009-09-25 21:08:292152}
2153
2154void TabContents::DidRunInsecureContent(const std::string& security_origin) {
[email protected]09843b5f2009-09-26 08:30:592155 controller_.ssl_manager()->DidRunInsecureContent(security_origin);
[email protected]e3d60e5d2009-09-25 21:08:292156}
2157
[email protected]bf5c2ff392009-07-08 16:24:332158void TabContents::DidFailProvisionalLoadWithError(
2159 RenderViewHost* render_view_host,
[email protected]dabb0d12010-10-05 12:50:072160 long long frame_id,
[email protected]bf5c2ff392009-07-08 16:24:332161 bool is_main_frame,
2162 int error_code,
2163 const GURL& url,
2164 bool showing_repost_interstitial) {
2165 if (net::ERR_ABORTED == error_code) {
2166 // EVIL HACK ALERT! Ignore failed loads when we're showing interstitials.
2167 // This means that the interstitial won't be torn down properly, which is
2168 // bad. But if we have an interstitial, go back to another tab type, and
2169 // then load the same interstitial again, we could end up getting the first
2170 // interstitial's "failed" message (as a result of the cancel) when we're on
2171 // the second one.
2172 //
2173 // We can't tell this apart, so we think we're tearing down the current page
2174 // which will cause a crash later one. There is also some code in
2175 // RenderViewHostManager::RendererAbortedProvisionalLoad that is commented
2176 // out because of this problem.
2177 //
2178 // http://code.google.com/p/chromium/issues/detail?id=2855
2179 // Because this will not tear down the interstitial properly, if "back" is
2180 // back to another tab type, the interstitial will still be somewhat alive
2181 // in the previous tab type. If you navigate somewhere that activates the
2182 // tab with the interstitial again, you'll see a flash before the new load
2183 // commits of the interstitial page.
2184 if (showing_interstitial_page()) {
2185 LOG(WARNING) << "Discarding message during interstitial.";
2186 return;
2187 }
2188
2189 // This will discard our pending entry if we cancelled the load (e.g., if we
2190 // decided to download the file instead of load it). Only discard the
2191 // pending entry if the URLs match, otherwise the user initiated a navigate
2192 // before the page loaded so that the discard would discard the wrong entry.
2193 NavigationEntry* pending_entry = controller_.pending_entry();
2194 if (pending_entry && pending_entry->url() == url) {
2195 controller_.DiscardNonCommittedEntries();
2196 // Update the URL display.
2197 NotifyNavigationStateChanged(TabContents::INVALIDATE_URL);
2198 }
2199
2200 render_manager_.RendererAbortedProvisionalLoad(render_view_host);
2201 }
2202
2203 // Send out a notification that we failed a provisional load with an error.
2204 ProvisionalLoadDetails details(is_main_frame,
2205 controller_.IsURLInPageNavigation(url),
[email protected]dabb0d12010-10-05 12:50:072206 url, std::string(), false, frame_id);
[email protected]bf5c2ff392009-07-08 16:24:332207 details.set_error_code(error_code);
2208
2209 NotificationService::current()->Notify(
2210 NotificationType::FAIL_PROVISIONAL_LOAD_WITH_ERROR,
2211 Source<NavigationController>(&controller_),
2212 Details<ProvisionalLoadDetails>(&details));
2213}
2214
2215void TabContents::DocumentLoadedInFrame() {
2216 controller_.DocumentLoadedInFrame();
2217}
2218
[email protected]dcd5b332010-08-11 08:55:182219void TabContents::OnContentSettingsAccessed(bool content_was_blocked) {
[email protected]614c0e12010-03-25 10:12:562220 if (delegate_)
[email protected]20ad6a92010-04-21 14:07:242221 delegate_->OnContentSettingsChange(this);
[email protected]614c0e12010-03-25 10:12:562222}
2223
[email protected]8d3347f2009-07-09 22:00:212224RenderViewHostDelegate::View* TabContents::GetViewDelegate() {
[email protected]420ae012009-04-24 05:16:322225 return view_.get();
2226}
2227
[email protected]8d3347f2009-07-09 22:00:212228RenderViewHostDelegate::RendererManagement*
2229TabContents::GetRendererManagementDelegate() {
2230 return &render_manager_;
2231}
2232
[email protected]bf5c2ff392009-07-08 16:24:332233RenderViewHostDelegate::BrowserIntegration*
[email protected]8d3347f2009-07-09 22:00:212234 TabContents::GetBrowserIntegrationDelegate() {
2235 return this;
[email protected]bf5c2ff392009-07-08 16:24:332236}
2237
[email protected]8d3347f2009-07-09 22:00:212238RenderViewHostDelegate::Resource* TabContents::GetResourceDelegate() {
2239 return this;
[email protected]bf5c2ff392009-07-08 16:24:332240}
2241
[email protected]46ba9082010-06-22 10:00:582242RenderViewHostDelegate::ContentSettings*
2243TabContents::GetContentSettingsDelegate() {
[email protected]9fb83e82010-07-02 18:24:552244 return content_settings_delegate_.get();
[email protected]46ba9082010-06-22 10:00:582245}
2246
[email protected]8d3347f2009-07-09 22:00:212247RenderViewHostDelegate::Save* TabContents::GetSaveDelegate() {
[email protected]420ae012009-04-24 05:16:322248 return save_package_.get(); // May be NULL, but we can return NULL.
2249}
2250
[email protected]8d3347f2009-07-09 22:00:212251RenderViewHostDelegate::Printing* TabContents::GetPrintingDelegate() {
[email protected]12802702010-07-09 19:43:092252 return printing_.get();
[email protected]8d3347f2009-07-09 22:00:212253}
2254
2255RenderViewHostDelegate::FavIcon* TabContents::GetFavIconDelegate() {
2256 return &fav_icon_helper_;
2257}
2258
[email protected]e8dbd674b2010-03-11 18:34:402259RenderViewHostDelegate::Autocomplete* TabContents::GetAutocompleteDelegate() {
[email protected]6db0def92010-03-02 19:55:452260 if (autocomplete_history_manager_.get() == NULL)
2261 autocomplete_history_manager_.reset(new AutocompleteHistoryManager(this));
2262 return autocomplete_history_manager_.get();
[email protected]bf5c2ff392009-07-08 16:24:332263}
2264
[email protected]21674df2009-10-28 19:51:212265RenderViewHostDelegate::AutoFill* TabContents::GetAutoFillDelegate() {
[email protected]cf28ec52010-04-09 22:56:342266 return GetAutoFillManager();
[email protected]21674df2009-10-28 19:51:212267}
2268
[email protected]aad51d1c2010-08-05 08:38:092269RenderViewHostDelegate::BlockedPlugin* TabContents::GetBlockedPluginDelegate() {
2270 if (blocked_plugin_manager_.get() == NULL)
2271 blocked_plugin_manager_.reset(new BlockedPluginManager(this));
2272 return blocked_plugin_manager_.get();
2273}
2274
[email protected]1f18184a2010-07-21 19:34:492275RenderViewHostDelegate::SSL* TabContents::GetSSLDelegate() {
2276 return GetSSLHelper();
2277}
2278
[email protected]b5977a0c2010-08-24 19:46:262279RenderViewHostDelegate::FileSelect* TabContents::GetFileSelectDelegate() {
2280 if (file_select_helper_.get() == NULL)
[email protected]ba70d082010-09-10 16:54:492281 file_select_helper_.reset(new FileSelectHelper(profile()));
[email protected]b5977a0c2010-08-24 19:46:262282 return file_select_helper_.get();
2283}
2284
[email protected]fd571bb2010-03-19 01:23:542285AutomationResourceRoutingDelegate*
2286TabContents::GetAutomationResourceRoutingDelegate() {
2287 return delegate();
2288}
2289
[email protected]ced90ae12010-02-20 02:06:162290RenderViewHostDelegate::BookmarkDrag* TabContents::GetBookmarkDragDelegate() {
2291 return bookmark_drag_;
2292}
2293
2294void TabContents::SetBookmarkDragDelegate(
2295 RenderViewHostDelegate::BookmarkDrag* bookmark_drag) {
2296 bookmark_drag_ = bookmark_drag;
2297}
2298
[email protected]9fb83e82010-07-02 18:24:552299TabSpecificContentSettings* TabContents::GetTabSpecificContentSettings() const {
2300 return content_settings_delegate_.get();
2301}
2302
[email protected]93623c5d2009-12-10 21:40:322303RendererPreferences TabContents::GetRendererPrefs(Profile* profile) const {
[email protected]840b1512009-07-21 16:53:462304 return renderer_preferences_;
[email protected]80d96fa2009-06-10 22:34:512305}
2306
[email protected]57c6a652009-05-04 07:58:342307TabContents* TabContents::GetAsTabContents() {
2308 return this;
2309}
2310
[email protected]7b291f92009-08-14 05:43:532311ViewType::Type TabContents::GetRenderViewType() const {
2312 return ViewType::TAB_CONTENTS;
2313}
2314
2315int TabContents::GetBrowserWindowID() const {
2316 return controller().window_id().id();
2317}
2318
[email protected]420ae012009-04-24 05:16:322319void TabContents::RenderViewCreated(RenderViewHost* render_view_host) {
[email protected]2e4633c2009-07-09 16:58:062320 NotificationService::current()->Notify(
2321 NotificationType::RENDER_VIEW_HOST_CREATED_FOR_TAB,
2322 Source<TabContents>(this),
2323 Details<RenderViewHost>(render_view_host));
[email protected]420ae012009-04-24 05:16:322324 NavigationEntry* entry = controller_.GetActiveEntry();
2325 if (!entry)
2326 return;
2327
2328 // When we're creating views, we're still doing initial setup, so we always
2329 // use the pending DOM UI rather than any possibly existing committed one.
2330 if (render_manager_.pending_dom_ui()) {
2331 render_manager_.pending_dom_ui()->RenderViewCreated(render_view_host);
2332 }
2333
2334 if (entry->IsViewSourceMode()) {
2335 // Put the renderer in view source mode.
2336 render_view_host->Send(
2337 new ViewMsg_EnableViewSourceMode(render_view_host->routing_id()));
2338 }
[email protected]0666aef2009-05-13 19:48:082339
2340 view()->RenderViewCreated(render_view_host);
[email protected]420ae012009-04-24 05:16:322341}
2342
2343void TabContents::RenderViewReady(RenderViewHost* rvh) {
2344 if (rvh != render_view_host()) {
2345 // Don't notify the world, since this came from a renderer in the
2346 // background.
2347 return;
2348 }
2349
2350 NotifyConnected();
[email protected]9d8a4642009-07-29 17:25:302351 bool was_crashed = is_crashed();
[email protected]420ae012009-04-24 05:16:322352 SetIsCrashed(false);
[email protected]9d8a4642009-07-29 17:25:302353
2354 // Restore the focus to the tab (otherwise the focus will be on the top
2355 // window).
[email protected]484ae5912010-09-29 19:16:142356 if (was_crashed && !FocusLocationBarByDefault() &&
2357 (!delegate_ || delegate_->ShouldFocusPageAfterCrash())) {
[email protected]9d8a4642009-07-29 17:25:302358 Focus();
[email protected]484ae5912010-09-29 19:16:142359 }
[email protected]420ae012009-04-24 05:16:322360}
2361
2362void TabContents::RenderViewGone(RenderViewHost* rvh) {
2363 // Ask the print preview if this renderer was valuable.
[email protected]12802702010-07-09 19:43:092364 if (!printing_->OnRenderViewGone(rvh))
[email protected]420ae012009-04-24 05:16:322365 return;
2366 if (rvh != render_view_host()) {
2367 // The pending page's RenderViewHost is gone.
2368 return;
2369 }
2370
2371 SetIsLoading(false, NULL);
2372 NotifyDisconnected();
2373 SetIsCrashed(true);
2374
[email protected]ff9efc62010-02-18 22:10:542375 // Remove all infobars.
[email protected]e5430c92010-02-18 22:39:212376 for (int i = infobar_delegate_count() - 1; i >=0 ; --i)
[email protected]ff9efc62010-02-18 22:10:542377 RemoveInfoBar(GetInfoBarDelegateAt(i));
2378
[email protected]8e537302009-06-10 21:19:582379 // Tell the view that we've crashed so it can prepare the sad tab page.
[email protected]cf68b092010-01-15 20:05:552380 // Only do this if we're not in browser shutdown, so that TabContents
2381 // objects that are not in a browser (e.g., HTML dialogs) and thus are
2382 // visible do not flash a sad tab page.
2383 if (browser_shutdown::GetShutdownType() == browser_shutdown::NOT_VALID)
2384 view_->OnTabCrashed();
[email protected]420ae012009-04-24 05:16:322385
2386 // Hide any visible hung renderer warning for this web contents' process.
[email protected]e7b8d832009-11-20 22:41:002387 hung_renderer_dialog::HideForTabContents(this);
[email protected]420ae012009-04-24 05:16:322388}
2389
[email protected]2e4633c2009-07-09 16:58:062390void TabContents::RenderViewDeleted(RenderViewHost* rvh) {
2391 NotificationService::current()->Notify(
2392 NotificationType::RENDER_VIEW_HOST_DELETED,
2393 Source<TabContents>(this),
2394 Details<RenderViewHost>(rvh));
[email protected]fb7b79f72009-11-06 18:00:482395 render_manager_.RenderViewDeleted(rvh);
[email protected]2e4633c2009-07-09 16:58:062396}
2397
[email protected]420ae012009-04-24 05:16:322398void TabContents::DidNavigate(RenderViewHost* rvh,
2399 const ViewHostMsg_FrameNavigate_Params& params) {
[email protected]8030f012009-09-25 18:09:372400 int extra_invalidate_flags = 0;
2401
2402 if (PageTransition::IsMainFrame(params.transition)) {
[email protected]20ede072009-10-06 00:28:352403 bool was_bookmark_bar_visible = ShouldShowBookmarkBar();
[email protected]8030f012009-09-25 18:09:372404
[email protected]420ae012009-04-24 05:16:322405 render_manager_.DidNavigateMainFrame(rvh);
2406
[email protected]20ede072009-10-06 00:28:352407 if (was_bookmark_bar_visible != ShouldShowBookmarkBar())
[email protected]8030f012009-09-25 18:09:372408 extra_invalidate_flags |= INVALIDATE_BOOKMARK_BAR;
[email protected]8030f012009-09-25 18:09:372409 }
2410
[email protected]420ae012009-04-24 05:16:322411 // Update the site of the SiteInstance if it doesn't have one yet.
2412 if (!GetSiteInstance()->has_site())
2413 GetSiteInstance()->SetSite(params.url);
2414
2415 // Need to update MIME type here because it's referred to in
2416 // UpdateNavigationCommands() called by RendererDidNavigate() to
2417 // determine whether or not to enable the encoding menu.
2418 // It's updated only for the main frame. For a subframe,
2419 // RenderView::UpdateURL does not set params.contents_mime_type.
2420 // (see http://code.google.com/p/chromium/issues/detail?id=2929 )
2421 // TODO(jungshik): Add a test for the encoding menu to avoid
2422 // regressing it again.
2423 if (PageTransition::IsMainFrame(params.transition))
2424 contents_mime_type_ = params.contents_mime_type;
2425
2426 NavigationController::LoadCommittedDetails details;
[email protected]8030f012009-09-25 18:09:372427 bool did_navigate = controller_.RendererDidNavigate(
2428 params, extra_invalidate_flags, &details);
[email protected]3e90d4a2009-07-03 17:38:392429
[email protected]a9c0bfe2010-09-17 08:35:222430 // Send notification about committed provisional loads. This notification is
2431 // different from the NAV_ENTRY_COMMITTED notification which doesn't include
2432 // the actual URL navigated to and isn't sent for AUTO_SUBFRAME navigations.
2433 if (details.type != NavigationType::NAV_IGNORE) {
[email protected]dabb0d12010-10-05 12:50:072434 // For AUTO_SUBFRAME navigations, an event for the main frame is generated
2435 // that is not recorded in the navigation history. For the purpose of
2436 // tracking navigation events, we treat this event as a sub frame navigation
2437 // event.
2438 bool is_main_frame = did_navigate ? details.is_main_frame : false;
2439 ProvisionalLoadDetails load_details(
2440 is_main_frame, details.is_in_page, params.url, std::string(), false,
2441 params.frame_id);
[email protected]a9c0bfe2010-09-17 08:35:222442 load_details.set_transition_type(params.transition);
2443 // Whether or not a page transition was triggered by going backward or
2444 // forward in the history is only stored in the navigation controller's
2445 // entry list.
2446 if (did_navigate &&
2447 (controller_.GetActiveEntry()->transition_type() &
2448 PageTransition::FORWARD_BACK)) {
2449 load_details.set_transition_type(
2450 params.transition | PageTransition::FORWARD_BACK);
2451 }
2452 NotificationService::current()->Notify(
2453 NotificationType::FRAME_PROVISIONAL_LOAD_COMMITTED,
2454 Source<NavigationController>(&controller_),
2455 Details<ProvisionalLoadDetails>(&load_details));
[email protected]a9c0bfe2010-09-17 08:35:222456 }
2457
[email protected]3e90d4a2009-07-03 17:38:392458 // Update history. Note that this needs to happen after the entry is complete,
2459 // which WillNavigate[Main,Sub]Frame will do before this function is called.
[email protected]ec0b6c42010-08-26 03:16:582460 if (params.should_update_history) {
[email protected]3e90d4a2009-07-03 17:38:392461 // Most of the time, the displayURL matches the loaded URL, but for about:
[email protected]ec0b6c42010-08-26 03:16:582462 // URLs, we use a data: URL as the real value. We actually want to save the
2463 // about: URL to the history db and keep the data: URL hidden. This is what
2464 // the TabContents' URL getter does.
2465 scoped_refptr<history::HistoryAddPageArgs> add_page_args(
2466 CreateHistoryAddPageArgs(GetURL(), details, params));
2467 if (!delegate() ||
2468 delegate()->ShouldAddNavigationToHistory(*add_page_args,
2469 details.type)) {
2470 UpdateHistoryForNavigation(add_page_args);
2471 }
[email protected]3e90d4a2009-07-03 17:38:392472 }
2473
[email protected]76543b92009-08-31 17:27:452474 if (!did_navigate)
2475 return; // No navigation happened.
[email protected]420ae012009-04-24 05:16:322476
2477 // DO NOT ADD MORE STUFF TO THIS FUNCTION! Your component should either listen
2478 // for the appropriate notification (best) or you can add it to
2479 // DidNavigateMainFramePostCommit / DidNavigateAnyFramePostCommit (only if
2480 // necessary, please).
2481
2482 // Run post-commit tasks.
2483 if (details.is_main_frame)
2484 DidNavigateMainFramePostCommit(details, params);
2485 DidNavigateAnyFramePostCommit(rvh, details, params);
2486}
2487
2488void TabContents::UpdateState(RenderViewHost* rvh,
2489 int32 page_id,
2490 const std::string& state) {
2491 DCHECK(rvh == render_view_host());
2492
2493 // We must be prepared to handle state updates for any page, these occur
2494 // when the user is scrolling and entering form data, as well as when we're
2495 // leaving a page, in which case our state may have already been moved to
2496 // the next page. The navigation controller will look up the appropriate
2497 // NavigationEntry and update it when it is notified via the delegate.
2498
2499 int entry_index = controller_.GetEntryIndexWithPageID(
2500 GetSiteInstance(), page_id);
2501 if (entry_index < 0)
2502 return;
2503 NavigationEntry* entry = controller_.GetEntryAtIndex(entry_index);
2504
2505 if (state == entry->content_state())
2506 return; // Nothing to update.
2507 entry->set_content_state(state);
2508 controller_.NotifyEntryChanged(entry, entry_index);
2509}
2510
2511void TabContents::UpdateTitle(RenderViewHost* rvh,
2512 int32 page_id, const std::wstring& title) {
2513 // If we have a title, that's a pretty good indication that we've started
2514 // getting useful data.
2515 SetNotWaitingForResponse();
2516
2517 DCHECK(rvh == render_view_host());
[email protected]371cc8b2010-09-01 16:03:482518 NavigationEntry* entry = controller_.GetEntryWithPageID(rvh->site_instance(),
[email protected]ec0b6c42010-08-26 03:16:582519 page_id);
[email protected]420ae012009-04-24 05:16:322520 if (!entry || !UpdateTitleForEntry(entry, title))
2521 return;
2522
2523 // Broadcast notifications when the UI should be updated.
2524 if (entry == controller_.GetEntryAtOffset(0))
[email protected]f1cd5e82009-10-23 17:19:032525 NotifyNavigationStateChanged(INVALIDATE_TITLE);
[email protected]420ae012009-04-24 05:16:322526}
2527
[email protected]420ae012009-04-24 05:16:322528void TabContents::UpdateEncoding(RenderViewHost* render_view_host,
[email protected]41fc0322009-09-04 22:23:402529 const std::string& encoding) {
[email protected]420ae012009-04-24 05:16:322530 set_encoding(encoding);
2531}
2532
2533void TabContents::UpdateTargetURL(int32 page_id, const GURL& url) {
2534 if (delegate())
2535 delegate()->UpdateTargetURL(this, url);
2536}
2537
2538void TabContents::UpdateThumbnail(const GURL& url,
2539 const SkBitmap& bitmap,
2540 const ThumbnailScore& score) {
2541 // Tell History about this thumbnail
[email protected]2ec53b52010-09-21 03:24:492542 if (history::TopSites::IsEnabled()) {
[email protected]72d0fc72009-07-09 17:30:492543 if (!profile()->IsOffTheRecord())
[email protected]523623c2010-05-19 16:03:422544 profile()->GetTopSites()->SetPageThumbnail(url, bitmap, score);
[email protected]449478302009-06-09 20:04:282545 } else {
2546 HistoryService* hs;
2547 if (!profile()->IsOffTheRecord() &&
2548 (hs = profile()->GetHistoryService(Profile::IMPLICIT_ACCESS))) {
2549 hs->SetPageThumbnail(url, bitmap, score);
2550 }
[email protected]420ae012009-04-24 05:16:322551 }
2552}
2553
[email protected]c4e98902010-06-01 10:20:142554void TabContents::UpdateInspectorSetting(const std::string& key,
2555 const std::string& value) {
2556 DictionaryValue* inspector_settings =
2557 profile()->GetPrefs()->GetMutableDictionary(
2558 prefs::kWebKitInspectorSettings);
[email protected]8b6e84a2010-08-14 03:32:172559 inspector_settings->SetWithoutPathExpansion(key,
[email protected]628cf5a52010-06-07 14:25:332560 Value::CreateStringValue(value));
[email protected]0df30122009-06-03 12:13:082561}
2562
[email protected]45aafc92010-06-07 14:18:532563void TabContents::ClearInspectorSettings() {
2564 DictionaryValue* inspector_settings =
2565 profile()->GetPrefs()->GetMutableDictionary(
2566 prefs::kWebKitInspectorSettings);
2567 inspector_settings->Clear();
2568}
2569
[email protected]420ae012009-04-24 05:16:322570void TabContents::Close(RenderViewHost* rvh) {
[email protected]07707302009-11-06 00:50:292571 // The UI may be in an event-tracking loop, such as between the
2572 // mouse-down and mouse-up in text selection or a button click.
2573 // Defer the close until after tracking is complete, so that we
2574 // don't free objects out from under the UI.
2575 // TODO(shess): This could probably be integrated with the
2576 // IsDoingDrag() test below. Punting for now because I need more
2577 // research to understand how this impacts platforms other than Mac.
2578 // TODO(shess): This could get more fine-grained. For instance,
2579 // closing a tab in another window while selecting text in the
2580 // current window's Omnibox should be just fine.
2581 if (view()->IsEventTracking()) {
2582 view()->CloseTabAfterEventTracking();
2583 return;
2584 }
2585
[email protected]24a4d1062009-07-10 23:10:422586 // If we close the tab while we're in the middle of a drag, we'll crash.
2587 // Instead, cancel the drag and close it as soon as the drag ends.
2588 if (view()->IsDoingDrag()) {
2589 view()->CancelDragAndCloseTab();
2590 return;
2591 }
2592
[email protected]420ae012009-04-24 05:16:322593 // Ignore this if it comes from a RenderViewHost that we aren't showing.
2594 if (delegate() && rvh == render_view_host())
2595 delegate()->CloseContents(this);
2596}
2597
2598void TabContents::RequestMove(const gfx::Rect& new_bounds) {
2599 if (delegate() && delegate()->IsPopup(this))
2600 delegate()->MoveContents(this, new_bounds);
2601}
2602
[email protected]7ab1e7d62009-10-14 23:32:012603void TabContents::DidStartLoading() {
[email protected]420ae012009-04-24 05:16:322604 SetIsLoading(true, NULL);
2605}
2606
[email protected]7ab1e7d62009-10-14 23:32:012607void TabContents::DidStopLoading() {
[email protected]420ae012009-04-24 05:16:322608 scoped_ptr<LoadNotificationDetails> details;
2609
2610 NavigationEntry* entry = controller_.GetActiveEntry();
2611 // An entry may not exist for a stop when loading an initial blank page or
2612 // if an iframe injected by script into a blank page finishes loading.
2613 if (entry) {
[email protected]420ae012009-04-24 05:16:322614 base::TimeDelta elapsed = base::TimeTicks::Now() - current_load_start_;
2615
2616 details.reset(new LoadNotificationDetails(
[email protected]ebe89e062009-08-13 23:16:542617 entry->virtual_url(),
[email protected]420ae012009-04-24 05:16:322618 entry->transition_type(),
2619 elapsed,
2620 &controller_,
2621 controller_.GetCurrentEntryIndex()));
2622 }
2623
2624 // Tell PasswordManager we've finished a page load, which serves as a
2625 // green light to save pending passwords and reset itself.
2626 GetPasswordManager()->DidStopLoading();
2627
2628 SetIsLoading(false, details.get());
2629}
2630
[email protected]25497492010-09-11 15:15:082631void TabContents::DocumentOnLoadCompletedInMainFrame(
2632 RenderViewHost* render_view_host,
2633 int32 page_id) {
2634 NotificationService::current()->Notify(
2635 NotificationType::LOAD_COMPLETED_MAIN_FRAME,
2636 Source<TabContents>(this),
2637 Details<int>(&page_id));
2638}
2639
[email protected]420ae012009-04-24 05:16:322640void TabContents::DidRedirectProvisionalLoad(int32 page_id,
2641 const GURL& source_url,
2642 const GURL& target_url) {
2643 NavigationEntry* entry;
2644 if (page_id == -1)
2645 entry = controller_.pending_entry();
2646 else
2647 entry = controller_.GetEntryWithPageID(GetSiteInstance(), page_id);
2648 if (!entry || entry->url() != source_url)
2649 return;
2650 entry->set_url(target_url);
2651}
2652
[email protected]420ae012009-04-24 05:16:322653void TabContents::RequestOpenURL(const GURL& url, const GURL& referrer,
2654 WindowOpenDisposition disposition) {
2655 if (render_manager_.dom_ui()) {
2656 // When we're a DOM UI, it will provide a page transition type for us (this
2657 // is so the new tab page can specify AUTO_BOOKMARK for automatically
2658 // generated suggestions).
2659 //
2660 // Note also that we hide the referrer for DOM UI pages. We don't really
[email protected]60e448982009-05-06 04:21:162661 // want web sites to see a referrer of "chrome://blah" (and some
2662 // chrome: URLs might have search terms or other stuff we don't want to
[email protected]420ae012009-04-24 05:16:322663 // send to the site), so we send no referrer.
2664 OpenURL(url, GURL(), disposition,
2665 render_manager_.dom_ui()->link_transition_type());
2666 } else {
2667 OpenURL(url, referrer, disposition, PageTransition::LINK);
2668 }
2669}
2670
[email protected]1ee614862009-07-06 20:29:182671void TabContents::DomOperationResponse(const std::string& json_string,
2672 int automation_id) {
2673}
2674
[email protected]8b8e7c92010-08-19 18:05:562675void TabContents::ProcessDOMUIMessage(
2676 const ViewHostMsg_DomMessage_Params& params) {
[email protected]420ae012009-04-24 05:16:322677 if (!render_manager_.dom_ui()) {
[email protected]c2e74fe82009-09-03 17:57:442678 // This can happen if someone uses window.open() to open an extension URL
2679 // from a non-extension context.
[email protected]8b8e7c92010-08-19 18:05:562680 render_view_host()->BlockExtensionRequest(params.request_id);
[email protected]420ae012009-04-24 05:16:322681 return;
2682 }
[email protected]8b8e7c92010-08-19 18:05:562683 render_manager_.dom_ui()->ProcessDOMUIMessage(params);
[email protected]420ae012009-04-24 05:16:322684}
2685
2686void TabContents::ProcessExternalHostMessage(const std::string& message,
2687 const std::string& origin,
2688 const std::string& target) {
2689 if (delegate())
2690 delegate()->ForwardMessageToExternalHost(message, origin, target);
2691}
2692
[email protected]420ae012009-04-24 05:16:322693void TabContents::RunJavaScriptMessage(
2694 const std::wstring& message,
2695 const std::wstring& default_prompt,
2696 const GURL& frame_url,
2697 const int flags,
2698 IPC::Message* reply_msg,
2699 bool* did_suppress_message) {
2700 // Suppress javascript messages when requested and when inside a constrained
2701 // popup window (because that activates them and breaks them out of the
2702 // constrained window jail).
[email protected]91ed49a2009-07-07 21:29:552703 // Also suppress messages when showing an interstitial. The interstitial is
2704 // shown over the previous page, we don't want the hidden page dialogs to
2705 // interfere with the interstitial.
2706 bool suppress_this_message = suppress_javascript_messages_ ||
2707 showing_interstitial_page();
[email protected]420ae012009-04-24 05:16:322708 if (delegate())
2709 suppress_this_message |=
[email protected]b6c874582009-05-08 19:38:312710 (delegate()->GetConstrainingContents(this) != this);
[email protected]420ae012009-04-24 05:16:322711
2712 *did_suppress_message = suppress_this_message;
2713
2714 if (!suppress_this_message) {
2715 base::TimeDelta time_since_last_message(
2716 base::TimeTicks::Now() - last_javascript_message_dismissal_);
2717 bool show_suppress_checkbox = false;
2718 // Show a checkbox offering to suppress further messages if this message is
2719 // being displayed within kJavascriptMessageExpectedDelay of the last one.
2720 if (time_since_last_message <
2721 base::TimeDelta::FromMilliseconds(kJavascriptMessageExpectedDelay))
2722 show_suppress_checkbox = true;
2723
[email protected]d6ad7442010-09-05 19:06:522724 RunJavascriptMessageBox(profile(), this, frame_url, flags, message,
2725 default_prompt, show_suppress_checkbox, reply_msg);
[email protected]420ae012009-04-24 05:16:322726 } else {
2727 // If we are suppressing messages, just reply as is if the user immediately
2728 // pressed "Cancel".
[email protected]beb440c2009-11-06 04:08:542729 OnMessageBoxClosed(reply_msg, false, std::wstring());
[email protected]420ae012009-04-24 05:16:322730 }
2731}
2732
2733void TabContents::RunBeforeUnloadConfirm(const std::wstring& message,
2734 IPC::Message* reply_msg) {
[email protected]7ab1e7d62009-10-14 23:32:012735 is_showing_before_unload_dialog_ = true;
[email protected]d82ed61e2009-06-16 02:46:222736 RunBeforeUnloadDialog(this, message, reply_msg);
[email protected]420ae012009-04-24 05:16:322737}
2738
2739void TabContents::ShowModalHTMLDialog(const GURL& url, int width, int height,
2740 const std::string& json_arguments,
2741 IPC::Message* reply_msg) {
2742 if (delegate()) {
2743 HtmlDialogUIDelegate* dialog_delegate =
2744 new ModalHtmlDialogDelegate(url, width, height, json_arguments,
[email protected]d82ed61e2009-06-16 02:46:222745 reply_msg, this);
[email protected]420ae012009-04-24 05:16:322746 delegate()->ShowHtmlDialog(dialog_delegate, NULL);
2747 }
2748}
2749
[email protected]4d44a1c2010-04-28 19:20:412750void TabContents::PasswordFormsFound(
[email protected]ed3fb032009-06-16 19:50:562751 const std::vector<webkit_glue::PasswordForm>& forms) {
[email protected]4d44a1c2010-04-28 19:20:412752 GetPasswordManager()->PasswordFormsFound(forms);
2753}
2754
2755void TabContents::PasswordFormsVisible(
2756 const std::vector<webkit_glue::PasswordForm>& visible_forms) {
2757 GetPasswordManager()->PasswordFormsVisible(visible_forms);
[email protected]420ae012009-04-24 05:16:322758}
2759
[email protected]420ae012009-04-24 05:16:322760// Checks to see if we should generate a keyword based on the OSDD, and if
2761// necessary uses TemplateURLFetcher to download the OSDD and create a keyword.
[email protected]2de7e002010-10-11 22:58:202762void TabContents::PageHasOSDD(
2763 RenderViewHost* render_view_host,
2764 int32 page_id,
2765 const GURL& url,
2766 const ViewHostMsg_PageHasOSDD_Type& msg_provider_type) {
[email protected]0b5b85c2010-10-11 23:00:122767 // Make sure page_id is the current page and other basic checks.
[email protected]420ae012009-04-24 05:16:322768 DCHECK(url.is_valid());
2769 if (!IsActiveEntry(page_id))
2770 return;
[email protected]420ae012009-04-24 05:16:322771 if (!profile()->GetTemplateURLFetcher())
2772 return;
[email protected]420ae012009-04-24 05:16:322773 if (profile()->IsOffTheRecord())
2774 return;
2775
[email protected]2de7e002010-10-11 22:58:202776 TemplateURLFetcher::ProviderType provider_type;
2777 switch (msg_provider_type.type) {
2778 case ViewHostMsg_PageHasOSDD_Type::AUTODETECTED_PROVIDER:
2779 provider_type = TemplateURLFetcher::AUTODETECTED_PROVIDER;
2780 break;
2781
2782 case ViewHostMsg_PageHasOSDD_Type::EXPLICIT_DEFAULT_PROVIDER:
2783 provider_type = TemplateURLFetcher::EXPLICIT_DEFAULT_PROVIDER;
2784 break;
2785
2786 case ViewHostMsg_PageHasOSDD_Type::EXPLICIT_PROVIDER:
2787 provider_type = TemplateURLFetcher::EXPLICIT_PROVIDER;
2788 break;
2789
2790 default:
2791 NOTREACHED();
2792 return;
2793 }
2794
[email protected]420ae012009-04-24 05:16:322795 const NavigationEntry* entry = controller_.GetLastCommittedEntry();
2796 DCHECK(entry);
2797
2798 const NavigationEntry* base_entry = entry;
2799 if (IsFormSubmit(base_entry)) {
2800 // If the current page is a form submit, find the last page that was not
2801 // a form submit and use its url to generate the keyword from.
2802 int index = controller_.last_committed_entry_index() - 1;
2803 while (index >= 0 && IsFormSubmit(controller_.GetEntryAtIndex(index)))
2804 index--;
2805 if (index >= 0)
2806 base_entry = controller_.GetEntryAtIndex(index);
2807 else
2808 base_entry = NULL;
2809 }
2810
2811 // We want to use the user typed URL if available since that represents what
2812 // the user typed to get here, and fall back on the regular URL if not.
2813 if (!base_entry)
2814 return;
2815 GURL keyword_url = base_entry->user_typed_url().is_valid() ?
2816 base_entry->user_typed_url() : base_entry->url();
2817 if (!keyword_url.is_valid())
2818 return;
[email protected]2de7e002010-10-11 22:58:202819
[email protected]0b5b85c2010-10-11 23:00:122820 std::wstring keyword = TemplateURLModel::GenerateKeyword(
2821 keyword_url,
2822 provider_type == TemplateURLFetcher::AUTODETECTED_PROVIDER);
[email protected]a88dbdd52010-01-15 19:25:532823
[email protected]0b5b85c2010-10-11 23:00:122824 // Download the OpenSearch description document. If this is successful, a
[email protected]420ae012009-04-24 05:16:322825 // new keyword will be created when done.
[email protected]420ae012009-04-24 05:16:322826 profile()->GetTemplateURLFetcher()->ScheduleDownload(
2827 keyword,
2828 url,
2829 base_entry->favicon().url(),
[email protected]0b5b85c2010-10-11 23:00:122830 new TemplateURLFetcherUICallbacks(this),
[email protected]2de7e002010-10-11 22:58:202831 provider_type);
[email protected]420ae012009-04-24 05:16:322832}
2833
[email protected]420ae012009-04-24 05:16:322834GURL TabContents::GetAlternateErrorPageURL() const {
2835 GURL url;
2836 // Disable alternate error pages when in OffTheRecord/Incognito mode.
2837 if (profile()->IsOffTheRecord())
2838 return url;
2839
2840 PrefService* prefs = profile()->GetPrefs();
2841 DCHECK(prefs);
2842 if (prefs->GetBoolean(prefs::kAlternateErrorPagesEnabled)) {
[email protected]a33457b82009-09-21 23:07:152843 url = google_util::AppendGoogleLocaleParam(
2844 GURL(google_util::kLinkDoctorBaseURL));
[email protected]420ae012009-04-24 05:16:322845 url = google_util::AppendGoogleTLDParam(url);
2846 }
2847 return url;
2848}
2849
2850WebPreferences TabContents::GetWebkitPrefs() {
[email protected]6c32ce72010-03-08 05:18:062851 Profile* profile = render_view_host()->process()->profile();
[email protected]7ccddb8c2009-08-04 17:36:552852 bool is_dom_ui = false;
[email protected]447021c2010-09-08 21:29:082853 WebPreferences web_prefs =
2854 RenderViewHostDelegateHelper::GetWebkitPrefs(profile, is_dom_ui);
2855
[email protected]9beff752010-09-22 19:35:432856 // Force accelerated compositing and 2d canvas off for chrome: and
2857 // chrome-extension: pages.
[email protected]447021c2010-09-08 21:29:082858 if (GetURL().SchemeIs(chrome::kChromeUIScheme) ||
2859 GetURL().SchemeIs(chrome::kExtensionScheme)) {
2860 web_prefs.accelerated_compositing_enabled = false;
[email protected]9beff752010-09-22 19:35:432861 web_prefs.accelerated_2d_canvas_enabled = false;
[email protected]447021c2010-09-08 21:29:082862 }
2863
[email protected]39553442010-09-09 00:01:552864#if defined(OS_MACOSX)
2865 // Disable accelerated compositing if IOSurface's are not supported,
2866 // as is the case in 10.5.
2867 if (!IOSurfaceSupport::Initialize())
2868 web_prefs.accelerated_compositing_enabled = false;
2869#endif
2870
[email protected]447021c2010-09-08 21:29:082871 return web_prefs;
[email protected]420ae012009-04-24 05:16:322872}
2873
[email protected]fa1cf0b82010-01-15 21:49:442874void TabContents::OnIgnoredUIEvent() {
2875 if (constrained_window_count()) {
2876 ConstrainedWindow* window = *constrained_window_begin();
2877 window->FocusConstrainedWindow();
2878 }
2879}
2880
[email protected]420ae012009-04-24 05:16:322881void TabContents::OnJSOutOfMemory() {
2882 AddInfoBar(new SimpleAlertInfoBarDelegate(
[email protected]e23d3a32010-08-13 19:39:582883 this, l10n_util::GetStringUTF16(IDS_JS_OUT_OF_MEMORY_PROMPT),
2884 NULL, true));
[email protected]420ae012009-04-24 05:16:322885}
2886
[email protected]420ae012009-04-24 05:16:322887void TabContents::OnCrossSiteResponse(int new_render_process_host_id,
2888 int new_request_id) {
[email protected]57c6a652009-05-04 07:58:342889 // Allows the TabContents to react when a cross-site response is ready to be
[email protected]420ae012009-04-24 05:16:322890 // delivered to a pending RenderViewHost. We must first run the onunload
2891 // handler of the old RenderViewHost before we can allow it to proceed.
2892 render_manager_.OnCrossSiteResponse(new_render_process_host_id,
2893 new_request_id);
2894}
2895
[email protected]420ae012009-04-24 05:16:322896gfx::Rect TabContents::GetRootWindowResizerRect() const {
2897 if (delegate())
2898 return delegate()->GetRootWindowResizerRect();
2899 return gfx::Rect();
2900}
2901
2902void TabContents::RendererUnresponsive(RenderViewHost* rvh,
2903 bool is_during_unload) {
2904 if (is_during_unload) {
2905 // Hang occurred while firing the beforeunload/unload handler.
2906 // Pretend the handler fired so tab closing continues as if it had.
[email protected]829e7612009-04-25 01:15:112907 rvh->set_sudden_termination_allowed(true);
[email protected]420ae012009-04-24 05:16:322908
2909 if (!render_manager_.ShouldCloseTabOnUnresponsiveRenderer())
2910 return;
2911
2912 // If the tab hangs in the beforeunload/unload handler there's really
2913 // nothing we can do to recover. Pretend the unload listeners have
2914 // all fired and close the tab. If the hang is in the beforeunload handler
2915 // then the user will not have the option of cancelling the close.
2916 Close(rvh);
2917 return;
2918 }
2919
2920 if (render_view_host() && render_view_host()->IsRenderViewLive())
[email protected]e7b8d832009-11-20 22:41:002921 hung_renderer_dialog::ShowForTabContents(this);
[email protected]420ae012009-04-24 05:16:322922}
2923
2924void TabContents::RendererResponsive(RenderViewHost* render_view_host) {
[email protected]e7b8d832009-11-20 22:41:002925 hung_renderer_dialog::HideForTabContents(this);
[email protected]420ae012009-04-24 05:16:322926}
2927
2928void TabContents::LoadStateChanged(const GURL& url,
[email protected]094e5b22009-09-25 04:23:562929 net::LoadState load_state,
2930 uint64 upload_position,
2931 uint64 upload_size) {
[email protected]420ae012009-04-24 05:16:322932 load_state_ = load_state;
[email protected]094e5b22009-09-25 04:23:562933 upload_position_ = upload_position;
2934 upload_size_ = upload_size;
[email protected]d686e812009-06-03 19:10:292935 std::wstring languages =
[email protected]ddd231e2010-06-29 20:35:192936 UTF8ToWide(profile()->GetPrefs()->GetString(prefs::kAcceptLanguages));
[email protected]d686e812009-06-03 19:10:292937 std::string host = url.host();
[email protected]ce85f602009-11-07 01:34:532938 load_state_host_ =
2939 net::IDNToUnicode(host.c_str(), host.size(), languages, NULL);
[email protected]420ae012009-04-24 05:16:322940 if (load_state_ == net::LOAD_STATE_READING_RESPONSE)
2941 SetNotWaitingForResponse();
2942 if (is_loading())
[email protected]c9cd2222009-05-06 05:16:502943 NotifyNavigationStateChanged(INVALIDATE_LOAD | INVALIDATE_TAB);
[email protected]420ae012009-04-24 05:16:322944}
2945
[email protected]1ee614862009-07-06 20:29:182946bool TabContents::IsExternalTabContainer() const {
2947 if (!delegate())
2948 return false;
2949
2950 return delegate()->IsExternalTabContainer();
2951}
2952
[email protected]1ee614862009-07-06 20:29:182953void TabContents::DidInsertCSS() {
2954 // This RVHDelegate function is used for extensions and not us.
[email protected]420ae012009-04-24 05:16:322955}
2956
[email protected]130efb02009-09-18 18:54:352957void TabContents::FocusedNodeChanged() {
2958 NotificationService::current()->Notify(
2959 NotificationType::FOCUS_CHANGED_IN_PAGE,
2960 Source<RenderViewHost>(render_view_host()),
2961 NotificationService::NoDetails());
2962}
2963
[email protected]b75b8292010-10-01 07:28:252964void TabContents::UpdateZoomLimits(int minimum_percent,
2965 int maximum_percent,
2966 bool remember) {
2967 minimum_zoom_percent_ = minimum_percent;
2968 maximum_zoom_percent_ = maximum_percent;
2969 temporary_zoom_settings_ = !remember;
[email protected]ebf40a72010-07-22 01:46:382970}
2971
[email protected]420ae012009-04-24 05:16:322972void TabContents::BeforeUnloadFiredFromRenderManager(
2973 bool proceed,
2974 bool* proceed_to_fire_unload) {
2975 if (delegate())
2976 delegate()->BeforeUnloadFired(this, proceed, proceed_to_fire_unload);
2977}
2978
[email protected]3a3d47472010-07-15 21:03:542979void TabContents::DidStartLoadingFromRenderManager(
2980 RenderViewHost* render_view_host) {
2981 DidStartLoading();
2982}
2983
2984void TabContents::RenderViewGoneFromRenderManager(
2985 RenderViewHost* render_view_host) {
2986 RenderViewGone(render_view_host);
2987}
2988
[email protected]420ae012009-04-24 05:16:322989void TabContents::UpdateRenderViewSizeForRenderManager() {
2990 // TODO(brettw) this is a hack. See TabContentsView::SizeContents.
[email protected]0323ee42010-02-17 22:03:262991 gfx::Size size = view_->GetContainerSize();
2992 // 0x0 isn't a valid window size (minimal window size is 1x1) but it may be
2993 // here during container initialization and normal window size will be set
2994 // later. In case of tab duplication this resizing to 0x0 prevents setting
2995 // normal size later so just ignore it.
2996 if (!size.IsEmpty())
2997 view_->SizeContents(size);
[email protected]420ae012009-04-24 05:16:322998}
2999
[email protected]3a3d47472010-07-15 21:03:543000void TabContents::NotifySwappedFromRenderManager() {
3001 NotifySwapped();
3002}
3003
3004NavigationController& TabContents::GetControllerForRenderManager() {
3005 return controller();
3006}
3007
[email protected]420ae012009-04-24 05:16:323008DOMUI* TabContents::CreateDOMUIForRenderManager(const GURL& url) {
[email protected]d82ed61e2009-06-16 02:46:223009 return DOMUIFactory::CreateDOMUIForURL(this, url);
[email protected]420ae012009-04-24 05:16:323010}
3011
3012NavigationEntry*
3013TabContents::GetLastCommittedNavigationEntryForRenderManager() {
3014 return controller_.GetLastCommittedEntry();
3015}
3016
3017bool TabContents::CreateRenderViewForRenderManager(
3018 RenderViewHost* render_view_host) {
[email protected]420ae012009-04-24 05:16:323019 RenderWidgetHostView* rwh_view = view_->CreateViewForWidget(render_view_host);
[email protected]1a98a932009-11-17 00:12:523020
[email protected]674b3822010-08-04 04:02:513021 if (!render_view_host->CreateRenderView(string16()))
[email protected]420ae012009-04-24 05:16:323022 return false;
3023
3024 // Now that the RenderView has been created, we need to tell it its size.
3025 rwh_view->SetSize(view_->GetContainerSize());
3026
3027 UpdateMaxPageIDIfNecessary(render_view_host->site_instance(),
3028 render_view_host);
3029 return true;
3030}
3031
3032void TabContents::Observe(NotificationType type,
3033 const NotificationSource& source,
3034 const NotificationDetails& details) {
3035 switch (type.value) {
3036 case NotificationType::BOOKMARK_MODEL_LOADED:
3037 // BookmarkModel finished loading, fall through to update starred state.
3038 case NotificationType::URLS_STARRED: {
3039 // Somewhere, a URL has been starred.
3040 // Ignore notifications for profiles other than our current one.
3041 Profile* source_profile = Source<Profile>(source).ptr();
3042 if (!source_profile || !source_profile->IsSameProfile(profile()))
3043 return;
3044
3045 UpdateStarredStateForCurrentURL();
3046 break;
3047 }
3048 case NotificationType::PREF_CHANGED: {
[email protected]57ecc4b2010-08-11 03:02:513049 std::string* pref_name_in = Details<std::string>(details).ptr();
[email protected]420ae012009-04-24 05:16:323050 DCHECK(Source<PrefService>(source).ptr() == profile()->GetPrefs());
3051 if (*pref_name_in == prefs::kAlternateErrorPagesEnabled) {
3052 UpdateAlternateErrorPageURL();
3053 } else if (*pref_name_in == prefs::kDefaultCharset ||
[email protected]57ecc4b2010-08-11 03:02:513054 StartsWithASCII(*pref_name_in, "webkit.webprefs.", true)
[email protected]420ae012009-04-24 05:16:323055 ) {
3056 UpdateWebPreferences();
3057 } else {
3058 NOTREACHED() << "unexpected pref change notification" << *pref_name_in;
3059 }
3060 break;
3061 }
3062 case NotificationType::RENDER_WIDGET_HOST_DESTROYED:
3063 view_->RenderWidgetHostDestroyed(Source<RenderWidgetHost>(source).ptr());
3064 break;
3065
3066 case NotificationType::NAV_ENTRY_COMMITTED: {
3067 DCHECK(&controller_ == Source<NavigationController>(source).ptr());
3068
3069 NavigationController::LoadCommittedDetails& committed_details =
3070 *(Details<NavigationController::LoadCommittedDetails>(details).ptr());
3071 ExpireInfoBars(committed_details);
3072 break;
3073 }
3074
[email protected]d3ba77272009-09-03 00:06:093075#if defined(OS_LINUX)
3076 case NotificationType::BROWSER_THEME_CHANGED: {
[email protected]7ff431e2010-01-07 18:18:543077 renderer_preferences_util::UpdateFromSystemSettings(
3078 &renderer_preferences_, profile());
[email protected]d3ba77272009-09-03 00:06:093079 render_view_host()->SyncRendererPrefs();
3080 break;
3081 }
3082#endif
3083
[email protected]6c32ce72010-03-08 05:18:063084 case NotificationType::USER_STYLE_SHEET_UPDATED:
3085 UpdateWebPreferences();
3086 break;
3087
[email protected]79580c62010-02-02 02:36:253088 case NotificationType::CONTENT_SETTINGS_CHANGED: {
[email protected]0314ae02010-04-08 09:18:293089 Details<const HostContentSettingsMap::ContentSettingsDetails>
[email protected]79580c62010-02-02 02:36:253090 settings_details(details);
[email protected]79580c62010-02-02 02:36:253091 NavigationEntry* entry = controller_.GetActiveEntry();
[email protected]da0c8e92010-02-09 23:25:493092 GURL entry_url;
[email protected]0314ae02010-04-08 09:18:293093 if (entry)
[email protected]da0c8e92010-02-09 23:25:493094 entry_url = entry->url();
[email protected]0314ae02010-04-08 09:18:293095 if (settings_details.ptr()->update_all() ||
3096 settings_details.ptr()->pattern().Matches(entry_url)) {
3097 render_view_host()->SendContentSettings(entry_url,
[email protected]b9a4ea7f2010-06-25 07:11:233098 profile()->GetHostContentSettingsMap()->
3099 GetContentSettings(entry_url));
[email protected]79580c62010-02-02 02:36:253100 }
3101 break;
3102 }
3103
[email protected]e5adff72010-06-14 18:13:063104 case NotificationType::EXTENSION_LOADED:
[email protected]a888b29e62010-04-01 13:38:573105 break;
[email protected]a888b29e62010-04-01 13:38:573106
3107 case NotificationType::EXTENSION_UNLOADED:
[email protected]e5adff72010-06-14 18:13:063108 case NotificationType::EXTENSION_UNLOADED_DISABLED:
[email protected]a888b29e62010-04-01 13:38:573109 break;
[email protected]a888b29e62010-04-01 13:38:573110
[email protected]88152052010-10-01 04:05:183111 case NotificationType::GOOGLE_URL_UPDATED:
3112 UpdateAlternateErrorPageURL();
3113 break;
3114
[email protected]420ae012009-04-24 05:16:323115 default:
3116 NOTREACHED();
3117 }
3118}
[email protected]aacd7cc2009-09-02 14:51:103119
[email protected]98aa0b52010-05-06 17:03:083120void TabContents::UpdateExtensionAppIcon(Extension* extension) {
3121 extension_app_icon_.reset();
[email protected]f075fe0a22010-04-26 04:06:433122
[email protected]a888b29e62010-04-01 13:38:573123 if (extension) {
[email protected]98aa0b52010-05-06 17:03:083124 extension_app_image_loader_.reset(new ImageLoadingTracker(this));
3125 extension_app_image_loader_->LoadImage(
[email protected]a888b29e62010-04-01 13:38:573126 extension,
[email protected]807871f2010-09-16 01:04:483127 extension->GetIconResource(Extension::EXTENSION_ICON_SMALLISH,
3128 ExtensionIconSet::MATCH_EXACTLY),
[email protected]a888b29e62010-04-01 13:38:573129 gfx::Size(Extension::EXTENSION_ICON_SMALLISH,
3130 Extension::EXTENSION_ICON_SMALLISH),
3131 ImageLoadingTracker::CACHE);
3132 } else {
[email protected]98aa0b52010-05-06 17:03:083133 extension_app_image_loader_.reset(NULL);
[email protected]a888b29e62010-04-01 13:38:573134 }
3135}
3136
3137Extension* TabContents::GetExtensionContaining(const GURL& url) {
3138 ExtensionsService* extensions_service = profile()->GetExtensionsService();
3139 if (!extensions_service)
3140 return NULL;
3141
3142 Extension* extension = extensions_service->GetExtensionByURL(url);
3143 return extension ?
3144 extension : extensions_service->GetExtensionByWebExtent(url);
3145}
3146
[email protected]a888b29e62010-04-01 13:38:573147void TabContents::OnImageLoaded(SkBitmap* image, ExtensionResource resource,
3148 int index) {
3149 if (image) {
[email protected]98aa0b52010-05-06 17:03:083150 extension_app_icon_ = *image;
[email protected]a888b29e62010-04-01 13:38:573151 NotifyNavigationStateChanged(INVALIDATE_TAB);
3152 }
3153}
3154
[email protected]beb440c2009-11-06 04:08:543155gfx::NativeWindow TabContents::GetMessageBoxRootWindow() {
3156 return view_->GetTopLevelNativeWindow();
3157}
3158
3159void TabContents::OnMessageBoxClosed(IPC::Message* reply_msg,
3160 bool success,
3161 const std::wstring& prompt) {
3162 last_javascript_message_dismissal_ = base::TimeTicks::Now();
3163 if (is_showing_before_unload_dialog_ && !success) {
3164 // If a beforeunload dialog is canceled, we need to stop the throbber from
3165 // spinning, since we forced it to start spinning in Navigate.
3166 DidStopLoading();
3167
3168 tab_close_start_time_ = base::TimeTicks();
3169 }
3170 is_showing_before_unload_dialog_ = false;
3171 render_view_host()->JavaScriptMessageBoxClosed(reply_msg, success, prompt);
3172}
3173
3174void TabContents::SetSuppressMessageBoxes(bool suppress_message_boxes) {
3175 set_suppress_javascript_messages(suppress_message_boxes);
3176}
3177
[email protected]3a3d47472010-07-15 21:03:543178TabContents* TabContents::AsTabContents() {
3179 return this;
3180}
3181
3182ExtensionHost* TabContents::AsExtensionHost() {
3183 return NULL;
3184}
3185
[email protected]41fc0322009-09-04 22:23:403186void TabContents::set_encoding(const std::string& encoding) {
[email protected]aacd7cc2009-09-02 14:51:103187 encoding_ = CharacterEncoding::GetCanonicalEncodingNameByAliasName(encoding);
3188}
[email protected]f45d2a72010-03-08 23:28:353189
3190void TabContents::SetAppIcon(const SkBitmap& app_icon) {
3191 app_icon_ = app_icon;
3192 NotifyNavigationStateChanged(INVALIDATE_TITLE);
3193}
[email protected]ea68c06a2010-04-23 17:25:373194
3195// After a successful *new* login attempt, we take the PasswordFormManager in
3196// provisional_save_manager_ and move it to a SavePasswordInfoBarDelegate while
3197// the user makes up their mind with the "save password" infobar. Note if the
3198// login is one we already know about, the end of the line is
3199// provisional_save_manager_ because we just update it on success and so such
3200// forms never end up in an infobar.
3201class SavePasswordInfoBarDelegate : public ConfirmInfoBarDelegate {
3202 public:
3203 SavePasswordInfoBarDelegate(TabContents* tab_contents,
[email protected]12bb6822010-06-16 02:00:463204 PasswordFormManager* form_to_save)
3205 : ConfirmInfoBarDelegate(tab_contents),
3206 form_to_save_(form_to_save),
[email protected]d75aba1d2010-08-02 23:35:583207 infobar_response_(NO_RESPONSE) {}
[email protected]ea68c06a2010-04-23 17:25:373208
[email protected]d75aba1d2010-08-02 23:35:583209 virtual ~SavePasswordInfoBarDelegate() {}
[email protected]ea68c06a2010-04-23 17:25:373210
[email protected]d75aba1d2010-08-02 23:35:583211 // Begin ConfirmInfoBarDelegate implementation.
[email protected]ea68c06a2010-04-23 17:25:373212 virtual void InfoBarClosed() {
[email protected]12bb6822010-06-16 02:00:463213 UMA_HISTOGRAM_ENUMERATION("PasswordManager.InfoBarResponse",
[email protected]d75aba1d2010-08-02 23:35:583214 infobar_response_, NUM_RESPONSE_TYPES);
[email protected]ea68c06a2010-04-23 17:25:373215 delete this;
3216 }
3217
[email protected]d75aba1d2010-08-02 23:35:583218 virtual Type GetInfoBarType() { return PAGE_ACTION_TYPE; }
3219
[email protected]e23d3a32010-08-13 19:39:583220 virtual string16 GetMessageText() const {
3221 return l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_SAVE_PASSWORD_PROMPT);
[email protected]ea68c06a2010-04-23 17:25:373222 }
3223
3224 virtual SkBitmap* GetIcon() const {
3225 return ResourceBundle::GetSharedInstance().GetBitmapNamed(
3226 IDR_INFOBAR_SAVE_PASSWORD);
3227 }
3228
3229 virtual int GetButtons() const {
3230 return BUTTON_OK | BUTTON_CANCEL;
3231 }
3232
[email protected]e23d3a32010-08-13 19:39:583233 virtual string16 GetButtonLabel(InfoBarButton button) const {
[email protected]ea68c06a2010-04-23 17:25:373234 if (button == BUTTON_OK)
[email protected]e23d3a32010-08-13 19:39:583235 return l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_SAVE_BUTTON);
[email protected]ea68c06a2010-04-23 17:25:373236 if (button == BUTTON_CANCEL)
[email protected]e23d3a32010-08-13 19:39:583237 return l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_BLACKLIST_BUTTON);
[email protected]ea68c06a2010-04-23 17:25:373238 NOTREACHED();
[email protected]e23d3a32010-08-13 19:39:583239 return string16();
[email protected]ea68c06a2010-04-23 17:25:373240 }
3241
3242 virtual bool Accept() {
3243 DCHECK(form_to_save_.get());
3244 form_to_save_->Save();
[email protected]d75aba1d2010-08-02 23:35:583245 infobar_response_ = REMEMBER_PASSWORD;
[email protected]ea68c06a2010-04-23 17:25:373246 return true;
3247 }
3248
3249 virtual bool Cancel() {
3250 DCHECK(form_to_save_.get());
3251 form_to_save_->PermanentlyBlacklist();
[email protected]d75aba1d2010-08-02 23:35:583252 infobar_response_ = DONT_REMEMBER_PASSWORD;
[email protected]ea68c06a2010-04-23 17:25:373253 return true;
3254 }
[email protected]d75aba1d2010-08-02 23:35:583255 // End ConfirmInfoBarDelegate implementation.
[email protected]ea68c06a2010-04-23 17:25:373256
3257 private:
3258 // The PasswordFormManager managing the form we're asking the user about,
3259 // and should update as per her decision.
3260 scoped_ptr<PasswordFormManager> form_to_save_;
3261
[email protected]12bb6822010-06-16 02:00:463262 // Used to track the results we get from the info bar.
3263 enum ResponseType {
[email protected]d75aba1d2010-08-02 23:35:583264 NO_RESPONSE = 0,
3265 REMEMBER_PASSWORD,
3266 DONT_REMEMBER_PASSWORD,
3267 NUM_RESPONSE_TYPES,
[email protected]12bb6822010-06-16 02:00:463268 };
3269 ResponseType infobar_response_;
3270
[email protected]ea68c06a2010-04-23 17:25:373271 DISALLOW_COPY_AND_ASSIGN(SavePasswordInfoBarDelegate);
3272};
3273
3274void TabContents::FillPasswordForm(
[email protected]e768baf2010-07-16 19:36:163275 const webkit_glue::PasswordFormFillData& form_data) {
[email protected]ea68c06a2010-04-23 17:25:373276 render_view_host()->FillPasswordForm(form_data);
3277}
3278
3279void TabContents::AddSavePasswordInfoBar(PasswordFormManager* form_to_save) {
3280 AddInfoBar(new SavePasswordInfoBarDelegate(this, form_to_save));
3281}
3282
3283Profile* TabContents::GetProfileForPasswordManager() {
3284 return profile();
3285}
3286
3287bool TabContents::DidLastPageLoadEncounterSSLErrors() {
3288 return controller().ssl_manager()->ProcessedSSLErrorFromRequest();
3289}