blob: 0c8a6c89d3c213983ab61cfd03b14d84fbb30ee6 [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]06821f42d2010-05-03 22:34:357#if defined(OS_CHROMEOS)
8// For GdkScreen
9#include <gdk/gdk.h>
10#endif // defined(OS_CHROMEOS)
11
[email protected]a92b8642009-05-05 23:38:5612#include "app/l10n_util.h"
[email protected]9929da92009-05-05 02:05:1113#include "app/resource_bundle.h"
[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]7cf1b6ce2010-03-20 06:37:0117#include "base/i18n/rtl.h"
[email protected]420ae012009-04-24 05:16:3218#include "base/process_util.h"
[email protected]96d185d2009-04-24 03:28:5419#include "base/string16.h"
[email protected]996fd702009-09-04 19:12:3720#include "base/string_util.h"
[email protected]96d185d2009-04-24 03:28:5421#include "base/time.h"
[email protected]6db0def92010-03-02 19:55:4522#include "chrome/browser/autocomplete_history_manager.h"
[email protected]21674df2009-10-28 19:51:2123#include "chrome/browser/autofill/autofill_manager.h"
[email protected]66ba4932009-06-04 19:22:1324#include "chrome/browser/blocked_popup_container.h"
[email protected]420ae012009-04-24 05:16:3225#include "chrome/browser/bookmarks/bookmark_model.h"
[email protected]281918912010-05-27 22:05:1326#include "chrome/browser/browser.h"
[email protected]96d185d2009-04-24 03:28:5427#include "chrome/browser/browser_process.h"
[email protected]cf68b092010-01-15 20:05:5528#include "chrome/browser/browser_shutdown.h"
initial.commit09911bf2008-07-26 23:55:2929#include "chrome/browser/cert_store.h"
[email protected]aacd7cc2009-09-02 14:51:1030#include "chrome/browser/character_encoding.h"
[email protected]96d185d2009-04-24 03:28:5431#include "chrome/browser/debugger/devtools_manager.h"
[email protected]420ae012009-04-24 05:16:3232#include "chrome/browser/dom_operation_notification_details.h"
[email protected]96d185d2009-04-24 03:28:5433#include "chrome/browser/dom_ui/dom_ui.h"
34#include "chrome/browser/dom_ui/dom_ui_factory.h"
[email protected]bcef0dc02009-02-28 00:35:0235#include "chrome/browser/download/download_item_model.h"
[email protected]420ae012009-04-24 05:16:3236#include "chrome/browser/download/download_manager.h"
37#include "chrome/browser/download/download_request_manager.h"
[email protected]e7eaedde2009-09-25 20:09:4938#include "chrome/browser/external_protocol_handler.h"
[email protected]92c6f9b92009-10-24 04:35:0839#include "chrome/browser/extensions/extensions_service.h"
[email protected]523623c2010-05-19 16:03:4240#include "chrome/browser/history/top_sites.h"
[email protected]0189bc722009-08-28 21:56:4841#include "chrome/browser/favicon_service.h"
[email protected]e5d2f7132010-04-09 18:13:5342#include "chrome/browser/find_bar_state.h"
[email protected]420ae012009-04-24 05:16:3243#include "chrome/browser/google_util.h"
[email protected]79580c62010-02-02 02:36:2544#include "chrome/browser/host_content_settings_map.h"
[email protected]8897c382009-05-06 17:53:2645#include "chrome/browser/hung_renderer_dialog.h"
[email protected]12f74a92010-02-05 22:32:1446#include "chrome/browser/message_box_handler.h"
[email protected]420ae012009-04-24 05:16:3247#include "chrome/browser/load_from_memory_cache_details.h"
48#include "chrome/browser/load_notification_details.h"
[email protected]84abba62009-10-07 17:01:4449#include "chrome/browser/metrics/metric_event_duration_details.h"
[email protected]ea0e80892009-08-22 00:36:0550#include "chrome/browser/modal_html_dialog_delegate.h"
[email protected]c8865482009-07-23 20:40:1051#include "chrome/browser/omnibox_search_hint.h"
[email protected]fdd61c62009-04-22 19:22:5752#include "chrome/browser/password_manager/password_manager.h"
[email protected]14a000d2010-04-29 21:44:2453#include "chrome/browser/platform_util.h"
[email protected]fdd61c62009-04-22 19:22:5754#include "chrome/browser/plugin_installer.h"
[email protected]052313b2010-02-19 09:43:0855#include "chrome/browser/pref_service.h"
[email protected]ce560f82009-06-03 09:39:4456#include "chrome/browser/profile.h"
[email protected]1db6ff152009-10-12 15:32:0757#include "chrome/browser/renderer_host/render_process_host.h"
[email protected]8cb5d5b2010-02-09 11:36:1658#include "chrome/browser/renderer_host/render_view_host.h"
[email protected]96d185d2009-04-24 03:28:5459#include "chrome/browser/renderer_host/render_widget_host_view.h"
[email protected]fd694982009-07-03 17:32:3760#include "chrome/browser/renderer_host/resource_request_details.h"
[email protected]1db6ff152009-10-12 15:32:0761#include "chrome/browser/renderer_host/site_instance.h"
[email protected]96d185d2009-04-24 03:28:5462#include "chrome/browser/renderer_host/web_cache_manager.h"
[email protected]93623c5d2009-12-10 21:40:3263#include "chrome/browser/renderer_preferences_util.h"
[email protected]152b8ba32010-03-29 19:40:1664#include "chrome/browser/search_engines/template_url_fetcher.h"
65#include "chrome/browser/search_engines/template_url_model.h"
[email protected]c37e3b62010-01-22 00:15:1766#include "chrome/browser/sessions/session_types.h"
[email protected]bd1ad682009-05-15 22:19:1767#include "chrome/browser/tab_contents/infobar_delegate.h"
[email protected]7e383692009-06-12 19:14:5468#include "chrome/browser/tab_contents/interstitial_page.h"
[email protected]f3ec7742009-01-15 00:59:1669#include "chrome/browser/tab_contents/navigation_entry.h"
[email protected]de34a962009-06-26 23:22:4370#include "chrome/browser/tab_contents/provisional_load_details.h"
[email protected]f3ec7742009-01-15 00:59:1671#include "chrome/browser/tab_contents/tab_contents_delegate.h"
[email protected]fdd61c62009-04-22 19:22:5772#include "chrome/browser/tab_contents/tab_contents_view.h"
[email protected]58dca552009-06-17 00:35:0273#include "chrome/browser/tab_contents/thumbnail_generator.h"
[email protected]449478302009-06-09 20:04:2874#include "chrome/browser/thumbnail_store.h"
[email protected]152b8ba32010-03-29 19:40:1675#include "chrome/browser/translate/page_translated_details.h"
[email protected]54ec6472010-04-09 19:39:5876#include "chrome/common/bindings_policy.h"
[email protected]35f7d212009-04-29 21:19:2777#include "chrome/common/chrome_switches.h"
[email protected]3b355642010-02-05 16:01:4978#include "chrome/common/extensions/extension.h"
[email protected]5d246db22009-10-27 06:17:5779#include "chrome/common/extensions/extension_action.h"
[email protected]942690b132010-05-11 06:42:1480#include "chrome/common/extensions/extension_resource.h"
[email protected]bfd04a62009-02-01 18:16:5681#include "chrome/common/notification_service.h"
initial.commit09911bf2008-07-26 23:55:2982#include "chrome/common/pref_names.h"
[email protected]420ae012009-04-24 05:16:3283#include "chrome/common/render_messages.h"
[email protected]1ee614862009-07-06 20:29:1884#include "chrome/common/renderer_preferences.h"
[email protected]96d185d2009-04-24 03:28:5485#include "chrome/common/url_constants.h"
[email protected]ea68c06a2010-04-23 17:25:3786#include "grit/chromium_strings.h"
[email protected]8897c382009-05-06 17:53:2687#include "grit/generated_resources.h"
[email protected]420ae012009-04-24 05:16:3288#include "grit/locale_settings.h"
[email protected]fd626782010-01-22 05:26:0689#include "grit/platform_locale_settings.h"
[email protected]ea68c06a2010-04-23 17:25:3790#include "grit/theme_resources.h"
[email protected]420ae012009-04-24 05:16:3291#include "net/base/mime_util.h"
92#include "net/base/net_errors.h"
[email protected]d686e812009-06-03 19:10:2993#include "net/base/net_util.h"
[email protected]420ae012009-04-24 05:16:3294#include "net/base/registry_controlled_domain.h"
[email protected]1ee614862009-07-06 20:29:1895#include "webkit/glue/password_form.h"
96#include "webkit/glue/webpreferences.h"
[email protected]3e45ba92009-02-20 21:09:0097
[email protected]420ae012009-04-24 05:16:3298// Cross-Site Navigations
99//
100// If a TabContents is told to navigate to a different web site (as determined
101// by SiteInstance), it will replace its current RenderViewHost with a new
102// RenderViewHost dedicated to the new SiteInstance. This works as follows:
103//
104// - Navigate determines whether the destination is cross-site, and if so,
105// it creates a pending_render_view_host_ and moves into the PENDING
106// RendererState.
107// - The pending RVH is "suspended," so that no navigation messages are sent to
108// its renderer until the onbeforeunload JavaScript handler has a chance to
109// run in the current RVH.
110// - The pending RVH tells CrossSiteRequestManager (a thread-safe singleton)
111// that it has a pending cross-site request. ResourceDispatcherHost will
112// check for this when the response arrives.
113// - The current RVH runs its onbeforeunload handler. If it returns false, we
114// cancel all the pending logic and go back to NORMAL. Otherwise we allow
115// the pending RVH to send the navigation request to its renderer.
116// - ResourceDispatcherHost receives a ResourceRequest on the IO thread. It
117// checks CrossSiteRequestManager to see that the RVH responsible has a
118// pending cross-site request, and then installs a CrossSiteEventHandler.
119// - When RDH receives a response, the BufferedEventHandler determines whether
120// it is a download. If so, it sends a message to the new renderer causing
121// it to cancel the request, and the download proceeds in the download
122// thread. For now, we stay in a PENDING state (with a pending RVH) until
[email protected]57c6a652009-05-04 07:58:34123// the next DidNavigate event for this TabContents. This isn't ideal, but it
[email protected]420ae012009-04-24 05:16:32124// doesn't affect any functionality.
125// - After RDH receives a response and determines that it is safe and not a
126// download, it pauses the response to first run the old page's onunload
127// handler. It does this by asynchronously calling the OnCrossSiteResponse
[email protected]57c6a652009-05-04 07:58:34128// method of TabContents on the UI thread, which sends a ClosePage message
[email protected]420ae012009-04-24 05:16:32129// to the current RVH.
130// - Once the onunload handler is finished, a ClosePage_ACK message is sent to
131// the ResourceDispatcherHost, who unpauses the response. Data is then sent
132// to the pending RVH.
133// - The pending renderer sends a FrameNavigate message that invokes the
134// DidNavigate method. This replaces the current RVH with the
135// pending RVH and goes back to the NORMAL RendererState.
136
137namespace {
138
139// Amount of time we wait between when a key event is received and the renderer
140// is queried for its state and pushed to the NavigationEntry.
141const int kQueryStateDelay = 5000;
142
143const int kSyncWaitDelay = 40;
144
[email protected]304f8792009-08-19 21:28:09145#if defined(OS_CHROMEOS)
146// If a popup window is bigger than this fraction of the screen on chrome os,
147// turn it into a tab
148const float kMaxWidthFactor = 0.5;
149const float kMaxHeightFactor = 0.6;
150#endif
151
[email protected]420ae012009-04-24 05:16:32152// If another javascript message box is displayed within
153// kJavascriptMessageExpectedDelay of a previous javascript message box being
154// dismissed, display an option to suppress future message boxes from this
155// contents.
156const int kJavascriptMessageExpectedDelay = 1000;
157
[email protected]420ae012009-04-24 05:16:32158// The list of prefs we want to observe.
159const wchar_t* kPrefsToObserve[] = {
160 prefs::kAlternateErrorPagesEnabled,
161 prefs::kWebKitJavaEnabled,
162 prefs::kWebKitJavascriptEnabled,
163 prefs::kWebKitLoadsImagesAutomatically,
164 prefs::kWebKitPluginsEnabled,
165 prefs::kWebKitUsesUniversalDetector,
166 prefs::kWebKitSerifFontFamily,
167 prefs::kWebKitSansSerifFontFamily,
168 prefs::kWebKitFixedFontFamily,
169 prefs::kWebKitDefaultFontSize,
170 prefs::kWebKitDefaultFixedFontSize,
[email protected]1661a3c02010-05-20 16:32:36171 prefs::kWebkitTabsToLinks,
[email protected]420ae012009-04-24 05:16:32172 prefs::kDefaultCharset
173 // kWebKitStandardFontIsSerif needs to be added
174 // if we let users pick which font to use, serif or sans-serif when
175 // no font is specified or a CSS generic family (serif or sans-serif)
176 // is not specified.
177};
178
179const int kPrefsToObserveLength = arraysize(kPrefsToObserve);
180
[email protected]420ae012009-04-24 05:16:32181// Returns true if the entry's transition type is FORM_SUBMIT.
182bool IsFormSubmit(const NavigationEntry* entry) {
183 return (PageTransition::StripQualifier(entry->transition_type()) ==
184 PageTransition::FORM_SUBMIT);
185}
186
187#if defined(OS_WIN)
188
189BOOL CALLBACK InvalidateWindow(HWND hwnd, LPARAM lparam) {
190 // Note: erase is required to properly paint some widgets borders. This can
191 // be seen with textfields.
192 InvalidateRect(hwnd, NULL, TRUE);
193 return TRUE;
194}
195#endif
196
[email protected]5e369672009-11-03 23:48:30197ViewMsg_Navigate_Params::NavigationType GetNavigationType(
[email protected]1ccb3568d2010-02-19 10:51:16198 Profile* profile, const NavigationEntry& entry,
199 NavigationController::ReloadType reload_type) {
200 switch (reload_type) {
201 case NavigationController::RELOAD:
202 return ViewMsg_Navigate_Params::RELOAD;
203 case NavigationController::RELOAD_IGNORING_CACHE:
204 return ViewMsg_Navigate_Params::RELOAD_IGNORING_CACHE;
205 case NavigationController::NO_RELOAD:
206 break; // Fall through to rest of function.
207 }
[email protected]5e369672009-11-03 23:48:30208
209 if (entry.restore_type() == NavigationEntry::RESTORE_LAST_SESSION &&
210 profile->DidLastSessionExitCleanly())
211 return ViewMsg_Navigate_Params::RESTORE;
212
213 return ViewMsg_Navigate_Params::NORMAL;
214}
215
[email protected]3cc72b12010-03-18 23:03:00216void MakeNavigateParams(const NavigationController& controller,
[email protected]1ccb3568d2010-02-19 10:51:16217 NavigationController::ReloadType reload_type,
218 ViewMsg_Navigate_Params* params) {
[email protected]3cc72b12010-03-18 23:03:00219 const NavigationEntry& entry = *controller.pending_entry();
[email protected]056de2d2009-06-26 16:41:34220 params->page_id = entry.page_id();
[email protected]3cc72b12010-03-18 23:03:00221 params->pending_history_list_offset = controller.pending_entry_index();
222 params->current_history_list_offset = controller.last_committed_entry_index();
223 params->current_history_list_length = controller.entry_count();
[email protected]056de2d2009-06-26 16:41:34224 params->url = entry.url();
225 params->referrer = entry.referrer();
226 params->transition = entry.transition_type();
227 params->state = entry.content_state();
[email protected]3cc72b12010-03-18 23:03:00228 params->navigation_type =
229 GetNavigationType(controller.profile(), entry, reload_type);
[email protected]056de2d2009-06-26 16:41:34230 params->request_time = base::Time::Now();
231}
232
[email protected]420ae012009-04-24 05:16:32233} // namespace
234
235// -----------------------------------------------------------------------------
236
[email protected]fdd61c62009-04-22 19:22:57237// static
238int TabContents::find_request_id_counter_ = -1;
239
[email protected]420ae012009-04-24 05:16:32240
[email protected]420ae012009-04-24 05:16:32241TabContents::TabContents(Profile* profile,
242 SiteInstance* site_instance,
243 int routing_id,
[email protected]34ac70502009-09-25 17:07:23244 const TabContents* base_tab_contents)
[email protected]b680ad22009-04-15 23:19:42245 : delegate_(NULL),
[email protected]66ba4932009-06-04 19:22:13246 ALLOW_THIS_IN_INITIALIZER_LIST(controller_(this, profile)),
247 ALLOW_THIS_IN_INITIALIZER_LIST(view_(
[email protected]d82ed61e2009-06-16 02:46:22248 TabContentsView::Create(this))),
249 ALLOW_THIS_IN_INITIALIZER_LIST(render_manager_(this, this)),
[email protected]fdd61c62009-04-22 19:22:57250 property_bag_(),
251 registrar_(),
[email protected]d82ed61e2009-06-16 02:46:22252 ALLOW_THIS_IN_INITIALIZER_LIST(printing_(*this)),
[email protected]fdd61c62009-04-22 19:22:57253 save_package_(),
[email protected]6db0def92010-03-02 19:55:45254 autocomplete_history_manager_(),
[email protected]21674df2009-10-28 19:51:21255 autofill_manager_(),
[email protected]fdd61c62009-04-22 19:22:57256 password_manager_(),
257 plugin_installer_(),
[email protected]6f821dd2010-02-23 00:54:06258 bookmark_drag_(NULL),
[email protected]d82ed61e2009-06-16 02:46:22259 ALLOW_THIS_IN_INITIALIZER_LIST(fav_icon_helper_(this)),
[email protected]fdd61c62009-04-22 19:22:57260 select_file_dialog_(),
[email protected]d5f942ba2008-09-26 19:30:34261 is_loading_(false),
initial.commit09911bf2008-07-26 23:55:29262 is_crashed_(false),
[email protected]d5f942ba2008-09-26 19:30:34263 waiting_for_response_(false),
[email protected]d5f942ba2008-09-26 19:30:34264 max_page_id_(-1),
[email protected]fdd61c62009-04-22 19:22:57265 current_load_start_(),
266 load_state_(net::LOAD_STATE_IDLE),
267 load_state_host_(),
[email protected]094e5b22009-09-25 04:23:56268 upload_size_(0),
269 upload_position_(0),
[email protected]fdd61c62009-04-22 19:22:57270 received_page_title_(false),
271 is_starred_(false),
272 contents_mime_type_(),
273 encoding_(),
[email protected]332af7732009-03-11 13:21:35274 blocked_popups_(NULL),
[email protected]8cc8d492010-02-02 10:40:49275 dont_notify_render_view_(false),
[email protected]f17a0ee2010-05-17 17:38:47276 displayed_insecure_content_(false),
[email protected]fdd61c62009-04-22 19:22:57277 infobar_delegates_(),
[email protected]fdd61c62009-04-22 19:22:57278 find_ui_active_(false),
279 find_op_aborted_(false),
280 current_find_request_id_(find_request_id_counter_++),
[email protected]e491f1c2009-05-22 20:28:12281 last_search_case_sensitive_(false),
[email protected]e491f1c2009-05-22 20:28:12282 last_search_result_(),
[email protected]98aa0b52010-05-06 17:03:08283 extension_app_(NULL),
284 extension_app_for_current_page_(NULL),
[email protected]fdd61c62009-04-22 19:22:57285 capturing_contents_(false),
286 is_being_destroyed_(false),
287 notify_disconnection_(false),
288 history_requests_(),
289#if defined(OS_WIN)
290 message_box_active_(CreateEvent(NULL, TRUE, FALSE, NULL)),
291#endif
292 last_javascript_message_dismissal_(),
[email protected]c2e74fe82009-09-03 17:57:44293 suppress_javascript_messages_(false),
[email protected]7ab1e7d62009-10-14 23:32:01294 is_showing_before_unload_dialog_(false),
[email protected]7ff431e2010-01-07 18:18:54295 renderer_preferences_(),
[email protected]1a242c32010-02-02 21:20:54296 opener_dom_ui_type_(DOMUIFactory::kNoDOMUI),
[email protected]777a7b62010-05-11 13:28:16297 language_state_(&controller_),
[email protected]b3df5a42010-05-11 14:31:09298 geolocation_settings_state_(profile),
[email protected]0cce15f2010-05-21 16:58:39299 closed_by_user_gesture_(false) {
[email protected]0de80162010-02-03 04:52:35300 ClearBlockedContentSettings();
[email protected]7ff431e2010-01-07 18:18:54301 renderer_preferences_util::UpdateFromSystemSettings(
302 &renderer_preferences_, profile);
303
[email protected]16779842009-07-08 23:45:29304#if defined(OS_CHROMEOS)
[email protected]58dca552009-06-17 00:35:02305 // Make sure the thumbnailer is started before starting the render manager.
306 // The thumbnailer will want to listen for RVH creations, one of which will
307 // happen in RVHManager::Init.
308 ThumbnailGenerator* generator = g_browser_process->GetThumbnailGenerator();
309 if (generator)
310 generator->StartThumbnailing();
311#endif
312
[email protected]12636df2009-09-28 22:32:21313 render_manager_.Init(profile, site_instance, routing_id);
[email protected]420ae012009-04-24 05:16:32314
[email protected]34ac70502009-09-25 17:07:23315 // We have the initial size of the view be based on the size of the passed in
316 // tab contents (normally a tab from the same window).
317 view_->CreateView(base_tab_contents ?
318 base_tab_contents->view()->GetContainerSize() : gfx::Size());
[email protected]420ae012009-04-24 05:16:32319
320 // Register for notifications about all interested prefs change.
321 PrefService* prefs = profile->GetPrefs();
322 if (prefs) {
323 for (int i = 0; i < kPrefsToObserveLength; ++i)
324 prefs->AddPrefObserver(kPrefsToObserve[i], this);
325 }
326
327 // Register for notifications about URL starredness changing on any profile.
328 registrar_.Add(this, NotificationType::URLS_STARRED,
329 NotificationService::AllSources());
330 registrar_.Add(this, NotificationType::BOOKMARK_MODEL_LOADED,
331 NotificationService::AllSources());
332 registrar_.Add(this, NotificationType::RENDER_WIDGET_HOST_DESTROYED,
333 NotificationService::AllSources());
[email protected]d3ba77272009-09-03 00:06:09334#if defined(OS_LINUX)
335 registrar_.Add(this, NotificationType::BROWSER_THEME_CHANGED,
336 NotificationService::AllSources());
337#endif
[email protected]420ae012009-04-24 05:16:32338
[email protected]6c32ce72010-03-08 05:18:06339 registrar_.Add(this, NotificationType::USER_STYLE_SHEET_UPDATED,
340 NotificationService::AllSources());
341
[email protected]79580c62010-02-02 02:36:25342 // Register for notifications about content setting changes.
343 registrar_.Add(this, NotificationType::CONTENT_SETTINGS_CHANGED,
344 NotificationService::AllSources());
345
[email protected]a888b29e62010-04-01 13:38:57346 // Listen for extension changes so we can update extension_for_current_page_.
347 registrar_.Add(this, NotificationType::EXTENSION_LOADED,
348 NotificationService::AllSources());
349 registrar_.Add(this, NotificationType::EXTENSION_UNLOADED,
350 NotificationService::AllSources());
351 registrar_.Add(this, NotificationType::EXTENSION_UNLOADED_DISABLED,
352 NotificationService::AllSources());
353
[email protected]c8865482009-07-23 20:40:10354 // Set-up the showing of the omnibox search infobar if applicable.
355 if (OmniboxSearchHint::IsEnabled(profile))
356 omnibox_search_hint_.reset(new OmniboxSearchHint(this));
[email protected]332af7732009-03-11 13:21:35357}
initial.commit09911bf2008-07-26 23:55:29358
359TabContents::~TabContents() {
[email protected]420ae012009-04-24 05:16:32360 is_being_destroyed_ = true;
361
[email protected]bfe4c1582009-10-02 18:11:09362 // We don't want any notifications while we're running our destructor.
[email protected]420ae012009-04-24 05:16:32363 registrar_.RemoveAll();
364
365 // Unregister the notifications of all observed prefs change.
366 PrefService* prefs = profile()->GetPrefs();
367 if (prefs) {
368 for (int i = 0; i < kPrefsToObserveLength; ++i)
369 prefs->RemovePrefObserver(kPrefsToObserve[i], this);
370 }
371
[email protected]420ae012009-04-24 05:16:32372 NotifyDisconnected();
[email protected]e7b8d832009-11-20 22:41:00373 hung_renderer_dialog::HideForTabContents(this);
[email protected]420ae012009-04-24 05:16:32374
[email protected]420ae012009-04-24 05:16:32375 // First cleanly close all child windows.
376 // TODO(mpcomplete): handle case if MaybeCloseChildWindows() already asked
377 // some of these to close. CloseWindows is async, so it might get called
378 // twice before it runs.
[email protected]8cc8d492010-02-02 10:40:49379 CloseConstrainedWindows();
[email protected]420ae012009-04-24 05:16:32380
[email protected]8cc8d492010-02-02 10:40:49381 // Close all blocked popups.
[email protected]66ba4932009-06-04 19:22:13382 if (blocked_popups_)
383 blocked_popups_->Destroy();
384
[email protected]420ae012009-04-24 05:16:32385 // Notify any observer that have a reference on this tab contents.
386 NotificationService::current()->Notify(
387 NotificationType::TAB_CONTENTS_DESTROYED,
388 Source<TabContents>(this),
389 NotificationService::NoDetails());
390
[email protected]1e5e74f2009-05-27 20:55:12391 // Notify any lasting InfobarDelegates that have not yet been removed that
392 // whatever infobar they were handling in this TabContents has closed,
393 // because the TabContents is going away entirely.
394 // This must happen after the TAB_CONTENTS_DESTROYED notification as the
395 // notification may trigger infobars calls that access their delegate. (and
396 // some implementations of InfoBarDelegate do delete themselves on
397 // InfoBarClosed()).
398 for (int i = 0; i < infobar_delegate_count(); ++i) {
399 InfoBarDelegate* delegate = GetInfoBarDelegateAt(i);
400 delegate->InfoBarClosed();
401 }
402 infobar_delegates_.clear();
403
[email protected]420ae012009-04-24 05:16:32404 // TODO(brettw) this should be moved to the view.
405#if defined(OS_WIN)
406 // If we still have a window handle, destroy it. GetNativeView can return
407 // NULL if this contents was part of a window that closed.
408 if (GetNativeView())
409 ::DestroyWindow(GetNativeView());
410#endif
[email protected]7ab1e7d62009-10-14 23:32:01411
412 // OnCloseStarted isn't called in unit tests.
413 if (!tab_close_start_time_.is_null()) {
414 UMA_HISTOGRAM_TIMES("Tab.Close",
415 base::TimeTicks::Now() - tab_close_start_time_);
416 }
initial.commit09911bf2008-07-26 23:55:29417}
418
[email protected]d5f942ba2008-09-26 19:30:34419// static
420void TabContents::RegisterUserPrefs(PrefService* prefs) {
[email protected]420ae012009-04-24 05:16:32421 prefs->RegisterBooleanPref(prefs::kAlternateErrorPagesEnabled, true);
422
423 WebPreferences pref_defaults;
424 prefs->RegisterBooleanPref(prefs::kWebKitJavascriptEnabled,
425 pref_defaults.javascript_enabled);
426 prefs->RegisterBooleanPref(prefs::kWebKitWebSecurityEnabled,
427 pref_defaults.web_security_enabled);
428 prefs->RegisterBooleanPref(
429 prefs::kWebKitJavascriptCanOpenWindowsAutomatically, true);
430 prefs->RegisterBooleanPref(prefs::kWebKitLoadsImagesAutomatically,
431 pref_defaults.loads_images_automatically);
432 prefs->RegisterBooleanPref(prefs::kWebKitPluginsEnabled,
433 pref_defaults.plugins_enabled);
434 prefs->RegisterBooleanPref(prefs::kWebKitDomPasteEnabled,
435 pref_defaults.dom_paste_enabled);
436 prefs->RegisterBooleanPref(prefs::kWebKitShrinksStandaloneImagesToFit,
437 pref_defaults.shrinks_standalone_images_to_fit);
[email protected]c4e98902010-06-01 10:20:14438 prefs->RegisterDictionaryPref(prefs::kWebKitInspectorSettings);
[email protected]420ae012009-04-24 05:16:32439 prefs->RegisterBooleanPref(prefs::kWebKitTextAreasAreResizable,
440 pref_defaults.text_areas_are_resizable);
441 prefs->RegisterBooleanPref(prefs::kWebKitJavaEnabled,
442 pref_defaults.java_enabled);
[email protected]1661a3c02010-05-20 16:32:36443 prefs->RegisterBooleanPref(prefs::kWebkitTabsToLinks,
444 pref_defaults.tabs_to_links);
[email protected]420ae012009-04-24 05:16:32445
446 prefs->RegisterLocalizedStringPref(prefs::kAcceptLanguages,
447 IDS_ACCEPT_LANGUAGES);
448 prefs->RegisterLocalizedStringPref(prefs::kDefaultCharset,
449 IDS_DEFAULT_ENCODING);
450 prefs->RegisterLocalizedBooleanPref(prefs::kWebKitStandardFontIsSerif,
451 IDS_STANDARD_FONT_IS_SERIF);
452 prefs->RegisterLocalizedStringPref(prefs::kWebKitFixedFontFamily,
453 IDS_FIXED_FONT_FAMILY);
454 prefs->RegisterLocalizedStringPref(prefs::kWebKitSerifFontFamily,
455 IDS_SERIF_FONT_FAMILY);
456 prefs->RegisterLocalizedStringPref(prefs::kWebKitSansSerifFontFamily,
457 IDS_SANS_SERIF_FONT_FAMILY);
458 prefs->RegisterLocalizedStringPref(prefs::kWebKitCursiveFontFamily,
459 IDS_CURSIVE_FONT_FAMILY);
460 prefs->RegisterLocalizedStringPref(prefs::kWebKitFantasyFontFamily,
461 IDS_FANTASY_FONT_FAMILY);
462 prefs->RegisterLocalizedIntegerPref(prefs::kWebKitDefaultFontSize,
463 IDS_DEFAULT_FONT_SIZE);
464 prefs->RegisterLocalizedIntegerPref(prefs::kWebKitDefaultFixedFontSize,
465 IDS_DEFAULT_FIXED_FONT_SIZE);
466 prefs->RegisterLocalizedIntegerPref(prefs::kWebKitMinimumFontSize,
467 IDS_MINIMUM_FONT_SIZE);
468 prefs->RegisterLocalizedIntegerPref(prefs::kWebKitMinimumLogicalFontSize,
469 IDS_MINIMUM_LOGICAL_FONT_SIZE);
470 prefs->RegisterLocalizedBooleanPref(prefs::kWebKitUsesUniversalDetector,
471 IDS_USES_UNIVERSAL_DETECTOR);
472 prefs->RegisterLocalizedStringPref(prefs::kStaticEncodings,
473 IDS_STATIC_ENCODING_LIST);
initial.commit09911bf2008-07-26 23:55:29474}
475
[email protected]13367f72009-07-08 16:39:02476// Returns true if contains content rendered by an extension.
477bool TabContents::HostsExtension() const {
478 return GetURL().SchemeIs(chrome::kExtensionScheme);
[email protected]d5f942ba2008-09-26 19:30:34479}
480
[email protected]cf28ec52010-04-09 22:56:34481AutoFillManager* TabContents::GetAutoFillManager() {
482 if (autofill_manager_.get() == NULL)
483 autofill_manager_.reset(new AutoFillManager(this));
484 return autofill_manager_.get();
485}
486
[email protected]6e95706d2009-04-23 22:55:01487PasswordManager* TabContents::GetPasswordManager() {
488 if (password_manager_.get() == NULL)
489 password_manager_.reset(new PasswordManager(this));
490 return password_manager_.get();
491}
492
493PluginInstaller* TabContents::GetPluginInstaller() {
494 if (plugin_installer_.get() == NULL)
495 plugin_installer_.reset(new PluginInstaller(this));
496 return plugin_installer_.get();
497}
498
[email protected]8cb5d5b2010-02-09 11:36:16499RenderProcessHost* TabContents::GetRenderProcessHost() const {
500 return render_manager_.current_host()->process();
501}
502
[email protected]98aa0b52010-05-06 17:03:08503void TabContents::SetExtensionApp(Extension* extension) {
[email protected]867a73e12010-03-19 20:45:46504 DCHECK(!extension || extension->GetFullLaunchURL().is_valid());
[email protected]98aa0b52010-05-06 17:03:08505 extension_app_ = extension;
[email protected]fca656c2010-02-10 20:30:10506
[email protected]98aa0b52010-05-06 17:03:08507 UpdateExtensionAppIcon(extension_app_);
[email protected]a888b29e62010-04-01 13:38:57508
[email protected]fca656c2010-02-10 20:30:10509 NotificationService::current()->Notify(
510 NotificationType::TAB_CONTENTS_APPLICATION_EXTENSION_CHANGED,
511 Source<TabContents>(this),
512 NotificationService::NoDetails());
[email protected]3b355642010-02-05 16:01:49513}
514
[email protected]98aa0b52010-05-06 17:03:08515void TabContents::SetExtensionAppById(const std::string& extension_app_id) {
516 if (extension_app_id.empty())
[email protected]911f8152010-03-18 16:46:40517 return;
518
519 ExtensionsService* extension_service = profile()->GetExtensionsService();
520 if (extension_service && extension_service->is_ready()) {
521 Extension* extension =
[email protected]98aa0b52010-05-06 17:03:08522 extension_service->GetExtensionById(extension_app_id, false);
[email protected]911f8152010-03-18 16:46:40523 if (extension)
[email protected]98aa0b52010-05-06 17:03:08524 SetExtensionApp(extension);
[email protected]911f8152010-03-18 16:46:40525 }
526}
527
[email protected]98aa0b52010-05-06 17:03:08528SkBitmap* TabContents::GetExtensionAppIcon() {
[email protected]8eb043b2010-04-30 07:19:51529 // We don't show the big icons in tabs for TYPE_EXTENSION_APP windows because
530 // for those windows, we already have a big icon in the top-left outside any
531 // tab. Having big tab icons too looks kinda redonk.
[email protected]06821f42d2010-05-03 22:34:35532 Browser* browser = delegate_ ? delegate_->GetBrowser() : NULL;
533 if (browser && browser->type() == Browser::TYPE_EXTENSION_APP)
[email protected]8eb043b2010-04-30 07:19:51534 return NULL;
[email protected]8eb043b2010-04-30 07:19:51535
[email protected]98aa0b52010-05-06 17:03:08536 if (extension_app_icon_.empty())
[email protected]8eb043b2010-04-30 07:19:51537 return NULL;
538
[email protected]98aa0b52010-05-06 17:03:08539 return &extension_app_icon_;
[email protected]8eb043b2010-04-30 07:19:51540}
541
[email protected]d5f942ba2008-09-26 19:30:34542const GURL& TabContents::GetURL() const {
543 // We may not have a navigation entry yet
[email protected]ce3fa3c2009-04-20 19:55:57544 NavigationEntry* entry = controller_.GetActiveEntry();
[email protected]ebe89e062009-08-13 23:16:54545 return entry ? entry->virtual_url() : GURL::EmptyGURL();
[email protected]d5f942ba2008-09-26 19:30:34546}
547
[email protected]96d185d2009-04-24 03:28:54548const string16& TabContents::GetTitle() const {
[email protected]4c6092c5b2009-06-06 00:23:55549 // Transient entries take precedence. They are used for interstitial pages
550 // that are shown on top of existing pages.
551 NavigationEntry* entry = controller_.GetTransientEntry();
552 if (entry)
553 return entry->GetTitleForDisplay(&controller_);
554
[email protected]96d185d2009-04-24 03:28:54555 DOMUI* our_dom_ui = render_manager_.pending_dom_ui() ?
556 render_manager_.pending_dom_ui() : render_manager_.dom_ui();
557 if (our_dom_ui) {
558 // Don't override the title in view source mode.
[email protected]4c6092c5b2009-06-06 00:23:55559 entry = controller_.GetActiveEntry();
[email protected]96d185d2009-04-24 03:28:54560 if (!(entry && entry->IsViewSourceMode())) {
561 // Give the DOM UI the chance to override our title.
562 const string16& title = our_dom_ui->overridden_title();
563 if (!title.empty())
564 return title;
565 }
566 }
567
568 // We use the title for the last committed entry rather than a pending
569 // navigation entry. For example, when the user types in a URL, we want to
570 // keep the old page's title until the new load has committed and we get a new
571 // title.
[email protected]96d185d2009-04-24 03:28:54572 entry = controller_.GetLastCommittedEntry();
573 if (entry)
574 return entry->GetTitleForDisplay(&controller_);
[email protected]96d185d2009-04-24 03:28:54575 return EmptyString16();
576}
577
[email protected]bbbc1ef2010-02-12 18:03:41578// static
579string16 TabContents::GetDefaultTitle() {
580 return l10n_util::GetStringUTF16(IDS_DEFAULT_TAB_TITLE);
581}
582
[email protected]d5f942ba2008-09-26 19:30:34583int32 TabContents::GetMaxPageID() {
584 if (GetSiteInstance())
585 return GetSiteInstance()->max_page_id();
586 else
587 return max_page_id_;
588}
589
590void TabContents::UpdateMaxPageID(int32 page_id) {
591 // Ensure both the SiteInstance and RenderProcessHost update their max page
[email protected]57c6a652009-05-04 07:58:34592 // IDs in sync. Only TabContents will also have site instances, except during
[email protected]d5f942ba2008-09-26 19:30:34593 // testing.
594 if (GetSiteInstance())
595 GetSiteInstance()->UpdateMaxPageID(page_id);
[email protected]8cb5d5b2010-02-09 11:36:16596 GetRenderProcessHost()->UpdateMaxPageID(page_id);
[email protected]d5f942ba2008-09-26 19:30:34597}
598
[email protected]96d185d2009-04-24 03:28:54599SiteInstance* TabContents::GetSiteInstance() const {
600 return render_manager_.current_host()->site_instance();
601}
602
[email protected]96d185d2009-04-24 03:28:54603bool TabContents::ShouldDisplayURL() {
[email protected]8ab24cc2009-11-13 20:56:15604 // Don't hide the url in view source mode and with interstitials.
[email protected]96d185d2009-04-24 03:28:54605 NavigationEntry* entry = controller_.GetActiveEntry();
[email protected]8ab24cc2009-11-13 20:56:15606 if (entry && (entry->IsViewSourceMode() ||
607 entry->page_type() == NavigationEntry::INTERSTITIAL_PAGE)) {
[email protected]96d185d2009-04-24 03:28:54608 return true;
[email protected]8ab24cc2009-11-13 20:56:15609 }
[email protected]83e3895b2009-06-11 00:07:16610
[email protected]96d185d2009-04-24 03:28:54611 DOMUI* dom_ui = GetDOMUIForCurrentState();
612 if (dom_ui)
613 return !dom_ui->should_hide_url();
614 return true;
615}
616
[email protected]d5f942ba2008-09-26 19:30:34617SkBitmap TabContents::GetFavIcon() const {
618 // Like GetTitle(), we also want to use the favicon for the last committed
619 // entry rather than a pending navigation entry.
[email protected]ce3fa3c2009-04-20 19:55:57620 NavigationEntry* entry = controller_.GetTransientEntry();
[email protected]cbab76d2008-10-13 22:42:47621 if (entry)
622 return entry->favicon().bitmap();
623
[email protected]ce3fa3c2009-04-20 19:55:57624 entry = controller_.GetLastCommittedEntry();
[email protected]d5f942ba2008-09-26 19:30:34625 if (entry)
626 return entry->favicon().bitmap();
[email protected]d5f942ba2008-09-26 19:30:34627 return SkBitmap();
628}
629
[email protected]0b303cc2009-09-28 22:35:15630bool TabContents::FavIconIsValid() const {
631 NavigationEntry* entry = controller_.GetTransientEntry();
632 if (entry)
633 return entry->favicon().is_valid();
634
635 entry = controller_.GetLastCommittedEntry();
636 if (entry)
637 return entry->favicon().is_valid();
638
639 return false;
640}
641
[email protected]96d185d2009-04-24 03:28:54642bool TabContents::ShouldDisplayFavIcon() {
643 // Always display a throbber during pending loads.
644 if (controller_.GetLastCommittedEntry() && controller_.pending_entry())
645 return true;
646
647 DOMUI* dom_ui = GetDOMUIForCurrentState();
648 if (dom_ui)
649 return !dom_ui->hide_favicon();
650 return true;
651}
652
[email protected]2d5a3592010-01-30 04:29:52653bool TabContents::IsContentBlocked(ContentSettingsType content_type) const {
[email protected]8cc8d492010-02-02 10:40:49654 if (content_type == CONTENT_SETTINGS_TYPE_POPUPS)
655 return blocked_popups_ != NULL;
656
[email protected]0de80162010-02-03 04:52:35657 if (content_type == CONTENT_SETTINGS_TYPE_IMAGES ||
658 content_type == CONTENT_SETTINGS_TYPE_JAVASCRIPT ||
[email protected]3dbb80b2010-02-09 22:41:20659 content_type == CONTENT_SETTINGS_TYPE_PLUGINS ||
660 content_type == CONTENT_SETTINGS_TYPE_COOKIES)
[email protected]0de80162010-02-03 04:52:35661 return content_blocked_[content_type];
662
[email protected]b1235062010-03-25 17:31:27663 // TODO(joth): remove once fully implemented.
664 if (content_type == CONTENT_SETTINGS_TYPE_GEOLOCATION)
665 return false;
666
[email protected]3dbb80b2010-02-09 22:41:20667 NOTREACHED();
[email protected]2d5a3592010-01-30 04:29:52668 return false;
669}
670
[email protected]96d185d2009-04-24 03:28:54671std::wstring TabContents::GetStatusText() const {
672 if (!is_loading() || load_state_ == net::LOAD_STATE_IDLE)
673 return std::wstring();
674
675 switch (load_state_) {
676 case net::LOAD_STATE_WAITING_FOR_CACHE:
677 return l10n_util::GetString(IDS_LOAD_STATE_WAITING_FOR_CACHE);
[email protected]8a1f3312010-05-25 19:25:04678 case net::LOAD_STATE_ESTABLISHING_PROXY_TUNNEL:
679 return l10n_util::GetString(IDS_LOAD_STATE_ESTABLISHING_PROXY_TUNNEL);
[email protected]96d185d2009-04-24 03:28:54680 case net::LOAD_STATE_RESOLVING_PROXY_FOR_URL:
681 return l10n_util::GetString(IDS_LOAD_STATE_RESOLVING_PROXY_FOR_URL);
682 case net::LOAD_STATE_RESOLVING_HOST:
683 return l10n_util::GetString(IDS_LOAD_STATE_RESOLVING_HOST);
684 case net::LOAD_STATE_CONNECTING:
685 return l10n_util::GetString(IDS_LOAD_STATE_CONNECTING);
[email protected]375e3112010-05-27 20:32:06686 case net::LOAD_STATE_SSL_HANDSHAKE:
687 return l10n_util::GetString(IDS_LOAD_STATE_SSL_HANDSHAKE);
[email protected]96d185d2009-04-24 03:28:54688 case net::LOAD_STATE_SENDING_REQUEST:
[email protected]094e5b22009-09-25 04:23:56689 if (upload_size_)
690 return l10n_util::GetStringF(
691 IDS_LOAD_STATE_SENDING_REQUEST_WITH_PROGRESS,
692 static_cast<int>((100 * upload_position_) / upload_size_));
693 else
694 return l10n_util::GetString(IDS_LOAD_STATE_SENDING_REQUEST);
[email protected]96d185d2009-04-24 03:28:54695 case net::LOAD_STATE_WAITING_FOR_RESPONSE:
696 return l10n_util::GetStringF(IDS_LOAD_STATE_WAITING_FOR_RESPONSE,
697 load_state_host_);
698 // Ignore net::LOAD_STATE_READING_RESPONSE and net::LOAD_STATE_IDLE
699 case net::LOAD_STATE_IDLE:
700 case net::LOAD_STATE_READING_RESPONSE:
701 break;
702 }
703
704 return std::wstring();
705}
706
[email protected]d5f942ba2008-09-26 19:30:34707void TabContents::SetIsCrashed(bool state) {
708 if (state == is_crashed_)
709 return;
710
711 is_crashed_ = state;
[email protected]c9cd2222009-05-06 05:16:50712 NotifyNavigationStateChanged(INVALIDATE_TAB);
[email protected]d5f942ba2008-09-26 19:30:34713}
714
[email protected]744ef172009-10-16 21:53:46715void TabContents::PageActionStateChanged() {
716 NotifyNavigationStateChanged(TabContents::INVALIDATE_PAGE_ACTIONS);
[email protected]d7eaf572009-07-01 21:57:00717}
[email protected]ce5c4502009-05-06 16:46:11718
[email protected]d5f942ba2008-09-26 19:30:34719void TabContents::NotifyNavigationStateChanged(unsigned changed_flags) {
720 if (delegate_)
721 delegate_->NavigationStateChanged(this, changed_flags);
722}
723
[email protected]96d185d2009-04-24 03:28:54724void TabContents::DidBecomeSelected() {
725 controller_.SetActive(true);
[email protected]8cb5d5b2010-02-09 11:36:16726 RenderWidgetHostView* rwhv = GetRenderWidgetHostView();
727 if (rwhv) {
728 rwhv->DidBecomeSelected();
[email protected]789e9152009-08-04 21:59:43729#if defined(OS_MACOSX)
[email protected]8cb5d5b2010-02-09 11:36:16730 rwhv->SetActive(true);
[email protected]789e9152009-08-04 21:59:43731#endif
732 }
[email protected]96d185d2009-04-24 03:28:54733
[email protected]8cb5d5b2010-02-09 11:36:16734 WebCacheManager::GetInstance()->ObserveActivity(GetRenderProcessHost()->id());
[email protected]96d185d2009-04-24 03:28:54735}
736
737void TabContents::WasHidden() {
738 if (!capturing_contents()) {
739 // |render_view_host()| can be NULL if the user middle clicks a link to open
740 // a tab in then background, then closes the tab before selecting it. This
741 // is because closing the tab calls TabContents::Destroy(), which removes
742 // the |render_view_host()|; then when we actually destroy the window,
743 // OnWindowPosChanged() notices and calls HideContents() (which calls us).
[email protected]8cb5d5b2010-02-09 11:36:16744 RenderWidgetHostView* rwhv = GetRenderWidgetHostView();
745 if (rwhv)
746 rwhv->WasHidden();
[email protected]96d185d2009-04-24 03:28:54747 }
748
749 NotificationService::current()->Notify(
750 NotificationType::TAB_CONTENTS_HIDDEN,
751 Source<TabContents>(this),
752 NotificationService::NoDetails());
753}
754
[email protected]d5f942ba2008-09-26 19:30:34755void TabContents::Activate() {
756 if (delegate_)
757 delegate_->ActivateContents(this);
758}
759
[email protected]96d185d2009-04-24 03:28:54760void TabContents::ShowContents() {
[email protected]8cb5d5b2010-02-09 11:36:16761 RenderWidgetHostView* rwhv = GetRenderWidgetHostView();
762 if (rwhv)
763 rwhv->DidBecomeSelected();
[email protected]96d185d2009-04-24 03:28:54764}
765
766void TabContents::HideContents() {
767 // TODO(pkasting): http://b/1239839 Right now we purposefully don't call
768 // our superclass HideContents(), because some callers want to be very picky
769 // about the order in which these get called. In addition to making the code
770 // here practically impossible to understand, this also means we end up
771 // calling TabContents::WasHidden() twice if callers call both versions of
[email protected]57c6a652009-05-04 07:58:34772 // HideContents() on a TabContents.
[email protected]96d185d2009-04-24 03:28:54773 WasHidden();
774}
775
[email protected]c0588052008-10-27 23:01:50776void TabContents::OpenURL(const GURL& url, const GURL& referrer,
[email protected]d5f942ba2008-09-26 19:30:34777 WindowOpenDisposition disposition,
778 PageTransition::Type transition) {
779 if (delegate_)
[email protected]c0588052008-10-27 23:01:50780 delegate_->OpenURLFromTab(this, url, referrer, disposition, transition);
[email protected]d5f942ba2008-09-26 19:30:34781}
782
[email protected]1ccb3568d2010-02-19 10:51:16783bool TabContents::NavigateToPendingEntry(
784 NavigationController::ReloadType reload_type) {
[email protected]96d185d2009-04-24 03:28:54785 const NavigationEntry& entry = *controller_.pending_entry();
786
787 RenderViewHost* dest_render_view_host = render_manager_.Navigate(entry);
788 if (!dest_render_view_host)
789 return false; // Unable to create the desired render view host.
790
[email protected]770dd8b2010-05-24 18:11:39791 if (delegate_ && delegate_->ShouldEnablePreferredSizeNotifications()) {
792 dest_render_view_host->EnablePreferredSizeChangedMode(
793 kPreferredSizeWidth | kPreferredSizeHeightThisIsSlow);
794 }
[email protected]9fb325e2010-05-06 18:23:24795
[email protected]0352e5472010-04-29 00:11:40796 // For security, we should never send non-DOM-UI URLs (other than about:blank)
797 // to a DOM UI renderer. Double check that here.
[email protected]54ec6472010-04-09 19:39:58798 int enabled_bindings = dest_render_view_host->enabled_bindings();
[email protected]0352e5472010-04-29 00:11:40799 bool is_allowed_in_dom_ui_renderer =
800 DOMUIFactory::UseDOMUIForURL(entry.url()) ||
801 entry.url() == GURL(chrome::kAboutBlankURL);
[email protected]54ec6472010-04-09 19:39:58802 CHECK(!BindingsPolicy::is_dom_ui_enabled(enabled_bindings) ||
[email protected]0352e5472010-04-29 00:11:40803 is_allowed_in_dom_ui_renderer);
[email protected]54ec6472010-04-09 19:39:58804
[email protected]96d185d2009-04-24 03:28:54805 // Tell DevTools agent that it is attached prior to the navigation.
[email protected]d9f9b792009-06-24 13:17:12806 DevToolsManager* devtools_manager = DevToolsManager::GetInstance();
[email protected]7e8e6b62009-05-08 11:28:32807 if (devtools_manager) { // NULL in unit tests.
[email protected]3cc72b12010-03-18 23:03:00808 devtools_manager->OnNavigatingToPendingEntry(render_view_host(),
809 dest_render_view_host,
810 entry.url());
[email protected]7e8e6b62009-05-08 11:28:32811 }
[email protected]96d185d2009-04-24 03:28:54812
813 // Used for page load time metrics.
814 current_load_start_ = base::TimeTicks::Now();
815
816 // Navigate in the desired RenderViewHost.
[email protected]056de2d2009-06-26 16:41:34817 ViewMsg_Navigate_Params navigate_params;
[email protected]3cc72b12010-03-18 23:03:00818 MakeNavigateParams(controller_, reload_type, &navigate_params);
[email protected]056de2d2009-06-26 16:41:34819 dest_render_view_host->Navigate(navigate_params);
[email protected]96d185d2009-04-24 03:28:54820
821 if (entry.page_id() == -1) {
822 // HACK!! This code suppresses javascript: URLs from being added to
823 // session history, which is what we want to do for javascript: URLs that
824 // do not generate content. What we really need is a message from the
825 // renderer telling us that a new page was not created. The same message
826 // could be used for mailto: URLs and the like.
827 if (entry.url().SchemeIs(chrome::kJavaScriptScheme))
828 return false;
829 }
830
831 // Clear any provisional password saves - this stops password infobars
832 // showing up on pages the user navigates to while the right page is
833 // loading.
834 GetPasswordManager()->ClearProvisionalSave();
835
[email protected]1ccb3568d2010-02-19 10:51:16836 if (reload_type != NavigationController::NO_RELOAD &&
837 !profile()->IsOffTheRecord()) {
[email protected]0189bc722009-08-28 21:56:48838 FaviconService* favicon_service =
839 profile()->GetFaviconService(Profile::IMPLICIT_ACCESS);
840 if (favicon_service)
841 favicon_service->SetFaviconOutOfDateForPage(entry.url());
[email protected]96d185d2009-04-24 03:28:54842 }
843
[email protected]a888b29e62010-04-01 13:38:57844 // The url likely changed, see if there is an extension whose extent contains
845 // the current page.
[email protected]98aa0b52010-05-06 17:03:08846 UpdateExtensionAppForCurrentPage();
[email protected]a888b29e62010-04-01 13:38:57847
[email protected]d5f942ba2008-09-26 19:30:34848 return true;
849}
850
[email protected]96d185d2009-04-24 03:28:54851void TabContents::Stop() {
852 render_manager_.Stop();
853 printing_.Stop();
854}
855
[email protected]96d185d2009-04-24 03:28:54856void TabContents::DisassociateFromPopupCount() {
857 render_view_host()->DisassociateFromPopupCount();
858}
859
860TabContents* TabContents::Clone() {
861 // We create a new SiteInstance so that the new tab won't share processes
862 // with the old one. This can be changed in the future if we need it to share
863 // processes for some reason.
[email protected]420ae012009-04-24 05:16:32864 TabContents* tc = new TabContents(profile(),
[email protected]96d185d2009-04-24 03:28:54865 SiteInstance::CreateSiteInstance(profile()),
[email protected]12636df2009-09-28 22:32:21866 MSG_ROUTING_NONE, this);
[email protected]96d185d2009-04-24 03:28:54867 tc->controller().CopyStateFrom(controller_);
[email protected]98aa0b52010-05-06 17:03:08868 tc->extension_app_ = extension_app_;
869 tc->extension_app_for_current_page_ = extension_app_for_current_page_;
870 tc->extension_app_icon_ = extension_app_icon_;
[email protected]96d185d2009-04-24 03:28:54871 return tc;
872}
873
[email protected]4d677202009-07-19 07:37:12874void TabContents::ShowPageInfo(const GURL& url,
875 const NavigationEntry::SSLStatus& ssl,
876 bool show_history) {
877 if (!delegate_)
878 return;
879
[email protected]bb678332009-07-21 00:15:50880 delegate_->ShowPageInfo(profile(), url, ssl, show_history);
[email protected]4d677202009-07-19 07:37:12881}
882
initial.commit09911bf2008-07-26 23:55:29883ConstrainedWindow* TabContents::CreateConstrainedDialog(
[email protected]e8382172009-06-19 22:16:28884 ConstrainedWindowDelegate* delegate) {
initial.commit09911bf2008-07-26 23:55:29885 ConstrainedWindow* window =
[email protected]e8382172009-06-19 22:16:28886 ConstrainedWindow::CreateConstrainedDialog(this, delegate);
initial.commit09911bf2008-07-26 23:55:29887 child_windows_.push_back(window);
[email protected]fa1cf0b82010-01-15 21:49:44888
889 if (child_windows_.size() == 1) {
890 window->ShowConstrainedWindow();
891 BlockTabContent(true);
892 }
893
initial.commit09911bf2008-07-26 23:55:29894 return window;
895}
896
[email protected]fa1cf0b82010-01-15 21:49:44897void TabContents::BlockTabContent(bool blocked) {
[email protected]8dccd7cb2010-02-25 05:19:55898 RenderWidgetHostView* rwhv = GetRenderWidgetHostView();
899 if (rwhv)
900 rwhv->SetVisuallyDeemphasized(blocked);
[email protected]fa1cf0b82010-01-15 21:49:44901 render_view_host()->set_ignore_input_events(blocked);
902 if (delegate_)
903 delegate_->SetTabContentBlocked(this, blocked);
904}
905
initial.commit09911bf2008-07-26 23:55:29906void TabContents::AddNewContents(TabContents* new_contents,
907 WindowOpenDisposition disposition,
908 const gfx::Rect& initial_pos,
[email protected]7e7414ae2010-01-26 20:19:29909 bool user_gesture) {
initial.commit09911bf2008-07-26 23:55:29910 if (!delegate_)
911 return;
912
[email protected]35f7d212009-04-29 21:19:27913 if ((disposition == NEW_POPUP) && !user_gesture &&
914 !CommandLine::ForCurrentProcess()->HasSwitch(
915 switches::kDisablePopupBlocking)) {
[email protected]2c4410d2009-05-06 23:46:22916 // Unrequested popups from normal pages are constrained unless they're in
[email protected]b6c874582009-05-08 19:38:31917 // the whitelist. The popup owner will handle checking this.
[email protected]7e7414ae2010-01-26 20:19:29918 delegate_->GetConstrainingContents(this)->AddPopup(
919 new_contents, initial_pos);
[email protected]b6c874582009-05-08 19:38:31920 } else {
[email protected]304f8792009-08-19 21:28:09921#if defined(OS_CHROMEOS)
922 if (disposition == NEW_POPUP) {
923 // If the popup is bigger than a given factor of the screen, then
924 // turn it into a foreground tab (on chrome os only)
925 GdkScreen* screen = gdk_screen_get_default();
926 int max_width = gdk_screen_get_width(screen) * kMaxWidthFactor;
927 int max_height = gdk_screen_get_height(screen) * kMaxHeightFactor;
928 if (initial_pos.width() > max_width ||
929 initial_pos.height() > max_height) {
930 disposition = NEW_FOREGROUND_TAB;
931 }
932 }
933#endif
934
[email protected]0aa55312008-10-17 21:53:08935 new_contents->DisassociateFromPopupCount();
initial.commit09911bf2008-07-26 23:55:29936 delegate_->AddNewContents(this, new_contents, disposition, initial_pos,
937 user_gesture);
[email protected]7f37dd92009-09-15 16:35:49938 NotificationService::current()->Notify(
939 NotificationType::TAB_ADDED,
940 Source<TabContentsDelegate>(delegate_),
941 Details<TabContents>(this));
initial.commit09911bf2008-07-26 23:55:29942 }
initial.commit09911bf2008-07-26 23:55:29943
[email protected]8cc8d492010-02-02 10:40:49944 // TODO(pkasting): Why is this necessary?
945 PopupNotificationVisibilityChanged(blocked_popups_ != NULL);
initial.commit09911bf2008-07-26 23:55:29946}
947
[email protected]bcd9dc42010-01-23 16:38:18948bool TabContents::ExecuteCode(int request_id, const std::string& extension_id,
[email protected]61f5a7b2009-12-22 22:21:20949 const std::vector<URLPattern>& host_permissions,
[email protected]20ad2692009-11-20 18:27:20950 bool is_js_code, const std::string& code_string,
951 bool all_frames) {
[email protected]ebd0eae72010-02-16 23:50:51952 RenderViewHost* host = render_view_host();
953 if (!host)
954 return false;
955
956 return host->Send(new ViewMsg_ExecuteCode(host->routing_id(),
957 ViewMsg_ExecuteCode_Params(request_id, extension_id, host_permissions,
958 is_js_code, code_string, all_frames)));
[email protected]912256b32009-09-18 09:47:35959}
960
[email protected]96d185d2009-04-24 03:28:54961void TabContents::PopupNotificationVisibilityChanged(bool visible) {
[email protected]8cc8d492010-02-02 10:40:49962 if (is_being_destroyed_)
963 return;
964 if (!dont_notify_render_view_)
[email protected]e8345242010-05-06 03:00:40965 render_view_host()->AllowScriptToClose(!visible);
[email protected]0de80162010-02-03 04:52:35966 if (delegate_)
[email protected]20ad6a92010-04-21 14:07:24967 delegate_->OnContentSettingsChange(this);
[email protected]96d185d2009-04-24 03:28:54968}
969
[email protected]5c9e97a2009-09-09 23:48:30970gfx::NativeView TabContents::GetContentNativeView() const {
[email protected]96d185d2009-04-24 03:28:54971 return view_->GetContentNativeView();
972}
973
974gfx::NativeView TabContents::GetNativeView() const {
975 return view_->GetNativeView();
976}
977
978void TabContents::GetContainerBounds(gfx::Rect *out) const {
979 view_->GetContainerBounds(out);
980}
981
982void TabContents::Focus() {
983 view_->Focus();
984}
985
[email protected]90daadb42009-06-08 21:27:28986void TabContents::FocusThroughTabTraversal(bool reverse) {
[email protected]7e383692009-06-12 19:14:54987 if (showing_interstitial_page()) {
988 render_manager_.interstitial_page()->FocusThroughTabTraversal(reverse);
989 return;
990 }
[email protected]96d185d2009-04-24 03:28:54991 render_view_host()->SetInitialFocus(reverse);
992}
993
994bool TabContents::FocusLocationBarByDefault() {
995 DOMUI* dom_ui = GetDOMUIForCurrentState();
996 if (dom_ui)
997 return dom_ui->focus_location_bar_by_default();
[email protected]3e3f0eb2009-06-22 18:33:43998 NavigationEntry* entry = controller_.GetActiveEntry();
[email protected]e0d481582009-09-15 21:06:25999 if (entry && entry->url() == GURL(chrome::kAboutBlankURL))
[email protected]3e3f0eb2009-06-22 18:33:431000 return true;
[email protected]96d185d2009-04-24 03:28:541001 return false;
1002}
1003
[email protected]a26dc362010-04-23 01:48:581004void TabContents::SetFocusToLocationBar(bool select_all) {
[email protected]a11aaf22010-03-30 00:03:381005 if (delegate())
[email protected]a26dc362010-04-23 01:48:581006 delegate()->SetFocusToLocationBar(select_all);
[email protected]a11aaf22010-03-30 00:03:381007}
1008
[email protected]616ed5a2008-11-21 22:27:241009void TabContents::AddInfoBar(InfoBarDelegate* delegate) {
[email protected]f7019302010-03-26 19:58:321010 if (delegate_ && !delegate_->infobars_enabled()) {
1011 delegate->InfoBarClosed();
1012 return;
1013 }
1014
[email protected]616ed5a2008-11-21 22:27:241015 // Look through the existing InfoBarDelegates we have for a match. If we've
1016 // already got one that matches, then we don't add the new one.
[email protected]f86a07022008-11-25 01:06:051017 for (int i = 0; i < infobar_delegate_count(); ++i) {
[email protected]6d27a7b2009-12-18 23:25:451018 if (GetInfoBarDelegateAt(i)->EqualsDelegate(delegate)) {
1019 // Tell the new infobar to close so that it can clean itself up.
1020 delegate->InfoBarClosed();
[email protected]616ed5a2008-11-21 22:27:241021 return;
[email protected]6d27a7b2009-12-18 23:25:451022 }
[email protected]616ed5a2008-11-21 22:27:241023 }
1024
1025 infobar_delegates_.push_back(delegate);
[email protected]bfd04a62009-02-01 18:16:561026 NotificationService::current()->Notify(
1027 NotificationType::TAB_CONTENTS_INFOBAR_ADDED,
1028 Source<TabContents>(this),
1029 Details<InfoBarDelegate>(delegate));
[email protected]616ed5a2008-11-21 22:27:241030
1031 // Add ourselves as an observer for navigations the first time a delegate is
1032 // added. We use this notification to expire InfoBars that need to expire on
1033 // page transitions.
1034 if (infobar_delegates_.size() == 1) {
[email protected]bfd04a62009-02-01 18:16:561035 registrar_.Add(this, NotificationType::NAV_ENTRY_COMMITTED,
[email protected]ce3fa3c2009-04-20 19:55:571036 Source<NavigationController>(&controller_));
[email protected]616ed5a2008-11-21 22:27:241037 }
1038}
1039
1040void TabContents::RemoveInfoBar(InfoBarDelegate* delegate) {
[email protected]f7019302010-03-26 19:58:321041 if (delegate_ && !delegate_->infobars_enabled()) {
1042 return;
1043 }
1044
[email protected]616ed5a2008-11-21 22:27:241045 std::vector<InfoBarDelegate*>::iterator it =
1046 find(infobar_delegates_.begin(), infobar_delegates_.end(), delegate);
1047 if (it != infobar_delegates_.end()) {
1048 InfoBarDelegate* delegate = *it;
[email protected]bfd04a62009-02-01 18:16:561049 NotificationService::current()->Notify(
1050 NotificationType::TAB_CONTENTS_INFOBAR_REMOVED,
1051 Source<TabContents>(this),
1052 Details<InfoBarDelegate>(delegate));
[email protected]f86a07022008-11-25 01:06:051053 infobar_delegates_.erase(it);
[email protected]616ed5a2008-11-21 22:27:241054
[email protected]6a02963e2009-01-06 16:58:031055 // Remove ourselves as an observer if we are tracking no more InfoBars.
1056 if (infobar_delegates_.empty()) {
[email protected]bfd04a62009-02-01 18:16:561057 registrar_.Remove(this, NotificationType::NAV_ENTRY_COMMITTED,
[email protected]ce3fa3c2009-04-20 19:55:571058 Source<NavigationController>(&controller_));
[email protected]6a02963e2009-01-06 16:58:031059 }
[email protected]616ed5a2008-11-21 22:27:241060 }
1061}
[email protected]3edd9522009-03-04 22:19:411062
[email protected]f81821c2009-08-07 01:29:471063void TabContents::ReplaceInfoBar(InfoBarDelegate* old_delegate,
1064 InfoBarDelegate* new_delegate) {
[email protected]f7019302010-03-26 19:58:321065 if (delegate_ && !delegate_->infobars_enabled()) {
1066 new_delegate->InfoBarClosed();
1067 return;
1068 }
1069
[email protected]f81821c2009-08-07 01:29:471070 std::vector<InfoBarDelegate*>::iterator it =
1071 find(infobar_delegates_.begin(), infobar_delegates_.end(), old_delegate);
1072 DCHECK(it != infobar_delegates_.end());
1073
1074 // Notify the container about the change of plans.
1075 scoped_ptr<std::pair<InfoBarDelegate*, InfoBarDelegate*> > details(
1076 new std::pair<InfoBarDelegate*, InfoBarDelegate*>(
1077 old_delegate, new_delegate));
1078 NotificationService::current()->Notify(
1079 NotificationType::TAB_CONTENTS_INFOBAR_REPLACED,
1080 Source<TabContents>(this),
1081 Details<std::pair<InfoBarDelegate*, InfoBarDelegate*> >(details.get()));
1082
1083 // Remove the old one.
1084 infobar_delegates_.erase(it);
1085
1086 // Add the new one.
1087 infobar_delegates_.push_back(new_delegate);
1088}
1089
[email protected]20ede072009-10-06 00:28:351090bool TabContents::ShouldShowBookmarkBar() {
[email protected]aa9196f2009-10-22 16:20:271091 if (showing_interstitial_page())
1092 return false;
1093
[email protected]96d185d2009-04-24 03:28:541094 // See GetDOMUIForCurrentState() comment for more info. This case is very
1095 // similar, but for non-first loads, we want to use the committed entry. This
1096 // is so the bookmarks bar disappears at the same time the page does.
1097 if (controller_.GetLastCommittedEntry()) {
1098 // Not the first load, always use the committed DOM UI.
1099 if (render_manager_.dom_ui())
1100 return render_manager_.dom_ui()->force_bookmark_bar_visible();
1101 return false; // Default.
1102 }
1103
1104 // When it's the first load, we know either the pending one or the committed
1105 // one will have the DOM UI in it (see GetDOMUIForCurrentState), and only one
1106 // of them will be valid, so we can just check both.
1107 if (render_manager_.pending_dom_ui())
1108 return render_manager_.pending_dom_ui()->force_bookmark_bar_visible();
1109 if (render_manager_.dom_ui())
1110 return render_manager_.dom_ui()->force_bookmark_bar_visible();
1111 return false; // Default.
1112}
1113
[email protected]d8f16ae2009-08-30 03:47:261114bool TabContents::IsExtensionShelfAlwaysVisible() {
1115 // See GetDOMUIForCurrentState() comment for more info. This case is very
1116 // similar, but for non-first loads, we want to use the committed entry. This
1117 // is so the bookmarks bar disappears at the same time the page does.
1118 if (controller_.GetLastCommittedEntry()) {
1119 // Not the first load, always use the committed DOM UI.
1120 if (render_manager_.dom_ui())
1121 return render_manager_.dom_ui()->force_extension_shelf_visible();
1122 return false; // Default.
1123 }
1124
1125 // When it's the first load, we know either the pending one or the committed
1126 // one will have the DOM UI in it (see GetDOMUIForCurrentState), and only one
1127 // of them will be valid, so we can just check both.
1128 if (render_manager_.pending_dom_ui())
1129 return render_manager_.pending_dom_ui()->force_extension_shelf_visible();
1130 if (render_manager_.dom_ui())
1131 return render_manager_.dom_ui()->force_extension_shelf_visible();
1132 return false; // Default.
1133}
1134
[email protected]3edd9522009-03-04 22:19:411135void TabContents::ToolbarSizeChanged(bool is_animating) {
1136 TabContentsDelegate* d = delegate();
1137 if (d)
1138 d->ToolbarSizeChanged(this, is_animating);
1139}
[email protected]616ed5a2008-11-21 22:27:241140
[email protected]fc6fb7fb2009-11-07 02:35:041141bool TabContents::CanDownload(int request_id) {
1142 TabContentsDelegate* d = delegate();
1143 if (d)
1144 return d->CanDownload(request_id);
1145 return true;
1146}
1147
[email protected]d5f942ba2008-09-26 19:30:341148void TabContents::OnStartDownload(DownloadItem* download) {
1149 DCHECK(download);
[email protected]d5f942ba2008-09-26 19:30:341150
1151 // Download in a constrained popup is shown in the tab that opened it.
[email protected]b6c874582009-05-08 19:38:311152 TabContents* tab_contents = delegate()->GetConstrainingContents(this);
[email protected]d5f942ba2008-09-26 19:30:341153
[email protected]c70f9b82010-04-21 07:31:111154 if (tab_contents && tab_contents->delegate()) {
[email protected]59560e0b2009-06-04 03:30:221155 tab_contents->delegate()->OnStartDownload(download);
[email protected]c70f9b82010-04-21 07:31:111156 // If the download occurs in a new tab, close it
1157 if (controller_.IsInitialNavigation() && (tab_contents == this))
1158 delegate()->CloseContents(this);
1159 }
[email protected]3edd9522009-03-04 22:19:411160}
[email protected]3edd9522009-03-04 22:19:411161
[email protected]d5f942ba2008-09-26 19:30:341162void TabContents::WillClose(ConstrainedWindow* window) {
1163 ConstrainedWindowList::iterator it =
1164 find(child_windows_.begin(), child_windows_.end(), window);
[email protected]fa1cf0b82010-01-15 21:49:441165 bool removed_topmost_window = it == child_windows_.begin();
[email protected]d5f942ba2008-09-26 19:30:341166 if (it != child_windows_.end())
1167 child_windows_.erase(it);
[email protected]55098792010-03-24 18:20:371168 if (child_windows_.size() > 0) {
1169 if (removed_topmost_window) {
1170 child_windows_[0]->ShowConstrainedWindow();
1171 }
[email protected]fa1cf0b82010-01-15 21:49:441172 BlockTabContent(true);
1173 } else {
1174 BlockTabContent(false);
1175 }
[email protected]66ba4932009-06-04 19:22:131176}
[email protected]d5f942ba2008-09-26 19:30:341177
[email protected]66ba4932009-06-04 19:22:131178void TabContents::WillCloseBlockedPopupContainer(
1179 BlockedPopupContainer* container) {
1180 DCHECK(blocked_popups_ == container);
1181 blocked_popups_ = NULL;
[email protected]8cc8d492010-02-02 10:40:491182 PopupNotificationVisibilityChanged(false);
[email protected]d5f942ba2008-09-26 19:30:341183}
1184
[email protected]d5f942ba2008-09-26 19:30:341185void TabContents::DidMoveOrResize(ConstrainedWindow* window) {
[email protected]332af7732009-03-11 13:21:351186#if defined(OS_WIN)
[email protected]92edc472009-02-10 20:32:061187 UpdateWindow(GetNativeView());
[email protected]332af7732009-03-11 13:21:351188#endif
[email protected]d5f942ba2008-09-26 19:30:341189}
1190
[email protected]c1dc9f132009-11-20 23:13:211191void TabContents::StartFinding(string16 search_string,
[email protected]e491f1c2009-05-22 20:28:121192 bool forward_direction,
1193 bool case_sensitive) {
[email protected]c1dc9f132009-11-20 23:13:211194 // If search_string is empty, it means FindNext was pressed with a keyboard
[email protected]6e95706d2009-04-23 22:55:011195 // shortcut so unless we have something to search for we return early.
[email protected]c1dc9f132009-11-20 23:13:211196 if (search_string.empty() && find_text_.empty()) {
[email protected]e5d2f7132010-04-09 18:13:531197 string16 last_search_prepopulate_text =
1198 FindBarState::GetLastPrepopulateText(profile());
1199
[email protected]87fae512009-12-11 02:20:211200 // Try the last thing we searched for on this tab, then the last thing
1201 // searched for on any tab.
1202 if (!previous_find_text_.empty())
1203 search_string = previous_find_text_;
[email protected]e5d2f7132010-04-09 18:13:531204 else if (!last_search_prepopulate_text.empty())
1205 search_string = last_search_prepopulate_text;
[email protected]87fae512009-12-11 02:20:211206 else
[email protected]e491f1c2009-05-22 20:28:121207 return;
[email protected]e491f1c2009-05-22 20:28:121208 }
[email protected]6e95706d2009-04-23 22:55:011209
[email protected]101c90e2009-10-26 21:14:441210 // Keep track of the previous search.
1211 previous_find_text_ = find_text_;
1212
[email protected]6e95706d2009-04-23 22:55:011213 // This is a FindNext operation if we are searching for the same text again,
1214 // or if the passed in search text is empty (FindNext keyboard shortcut). The
1215 // exception to this is if the Find was aborted (then we don't want FindNext
1216 // because the highlighting has been cleared and we need it to reappear). We
1217 // therefore treat FindNext after an aborted Find operation as a full fledged
1218 // Find.
[email protected]c1dc9f132009-11-20 23:13:211219 bool find_next = (find_text_ == search_string || search_string.empty()) &&
[email protected]e491f1c2009-05-22 20:28:121220 (last_search_case_sensitive_ == case_sensitive) &&
[email protected]6e95706d2009-04-23 22:55:011221 !find_op_aborted_;
1222 if (!find_next)
1223 current_find_request_id_ = find_request_id_counter_++;
1224
[email protected]c1dc9f132009-11-20 23:13:211225 if (!search_string.empty())
1226 find_text_ = search_string;
[email protected]e491f1c2009-05-22 20:28:121227 last_search_case_sensitive_ = case_sensitive;
[email protected]6e95706d2009-04-23 22:55:011228
1229 find_op_aborted_ = false;
1230
1231 // Keep track of what the last search was across the tabs.
[email protected]e5d2f7132010-04-09 18:13:531232 FindBarState* find_bar_state = profile()->GetFindBarState();
1233 find_bar_state->set_last_prepopulate_text(find_text_);
[email protected]6e95706d2009-04-23 22:55:011234 render_view_host()->StartFinding(current_find_request_id_,
1235 find_text_,
1236 forward_direction,
[email protected]e491f1c2009-05-22 20:28:121237 case_sensitive,
[email protected]6e95706d2009-04-23 22:55:011238 find_next);
1239}
1240
[email protected]5bc8fe92010-03-11 18:19:001241void TabContents::StopFinding(
1242 FindBarController::SelectionAction selection_action) {
[email protected]d6e8d332010-06-04 22:26:011243 if (selection_action == FindBarController::kClearSelection) {
1244 // kClearSelection means the find string has been cleared by the user, but
1245 // the UI has not been dismissed. In that case we want to clear the
1246 // previously remembered search (http://crbug.com/42639).
1247 previous_find_text_ = string16();
1248 } else {
[email protected]2d2dffc2009-06-09 21:41:001249 find_ui_active_ = false;
[email protected]d6e8d332010-06-04 22:26:011250 if (!find_text_.empty())
1251 previous_find_text_ = find_text_;
1252 }
[email protected]101c90e2009-10-26 21:14:441253 find_text_.clear();
[email protected]6e95706d2009-04-23 22:55:011254 find_op_aborted_ = true;
[email protected]e491f1c2009-05-22 20:28:121255 last_search_result_ = FindNotificationDetails();
[email protected]5bc8fe92010-03-11 18:19:001256 render_view_host()->StopFinding(selection_action);
[email protected]6e95706d2009-04-23 22:55:011257}
1258
[email protected]420ae012009-04-24 05:16:321259void TabContents::OnSavePage() {
1260 // If we can not save the page, try to download it.
1261 if (!SavePackage::IsSavableContents(contents_mime_type())) {
1262 DownloadManager* dlm = profile()->GetDownloadManager();
1263 const GURL& current_page_url = GetURL();
1264 if (dlm && current_page_url.is_valid())
[email protected]d82ed61e2009-06-16 02:46:221265 dlm->DownloadUrl(current_page_url, GURL(), "", this);
[email protected]420ae012009-04-24 05:16:321266 return;
1267 }
1268
1269 Stop();
1270
1271 // Create the save package and possibly prompt the user for the name to save
1272 // the page as. The user prompt is an asynchronous operation that runs on
1273 // another thread.
[email protected]d82ed61e2009-06-16 02:46:221274 save_package_ = new SavePackage(this);
[email protected]420ae012009-04-24 05:16:321275 save_package_->GetSaveInfo();
1276}
1277
1278// Used in automated testing to bypass prompting the user for file names.
1279// Instead, the names and paths are hard coded rather than running them through
1280// file name sanitation and extension / mime checking.
[email protected]828cabe2009-09-26 22:47:111281bool TabContents::SavePage(const FilePath& main_file, const FilePath& dir_path,
[email protected]420ae012009-04-24 05:16:321282 SavePackage::SavePackageType save_type) {
1283 // Stop the page from navigating.
1284 Stop();
1285
[email protected]828cabe2009-09-26 22:47:111286 save_package_ = new SavePackage(this, save_type, main_file, dir_path);
[email protected]cdf6cc82009-08-04 21:48:591287 return save_package_->Init();
[email protected]420ae012009-04-24 05:16:321288}
1289
[email protected]89d6e6e2009-12-03 23:06:511290void TabContents::EmailPageLocation() {
1291 std::string title = EscapeQueryParamValue(UTF16ToUTF8(GetTitle()), false);
1292 std::string page_url = EscapeQueryParamValue(GetURL().spec(), false);
1293 std::string mailto = std::string("mailto:?subject=Fwd:%20") +
1294 title + "&body=%0A%0A" + page_url;
1295 platform_util::OpenExternal(GURL(mailto));
1296}
1297
[email protected]420ae012009-04-24 05:16:321298void TabContents::PrintPreview() {
1299 // We don't show the print preview yet, only the print dialog.
1300 PrintNow();
1301}
1302
1303bool TabContents::PrintNow() {
1304 // We can't print interstitial page for now.
1305 if (showing_interstitial_page())
1306 return false;
1307
1308 return render_view_host()->PrintPages();
1309}
1310
[email protected]82270452009-06-19 15:58:011311void TabContents::PrintingDone(int document_cookie, bool success) {
1312 render_view_host()->PrintingDone(document_cookie, success);
1313}
1314
[email protected]420ae012009-04-24 05:16:321315bool TabContents::IsActiveEntry(int32 page_id) {
1316 NavigationEntry* active_entry = controller_.GetActiveEntry();
1317 return (active_entry != NULL &&
1318 active_entry->site_instance() == GetSiteInstance() &&
1319 active_entry->page_id() == page_id);
1320}
1321
[email protected]b2fe07d12010-02-09 14:38:081322void TabContents::SetOverrideEncoding(const std::string& encoding) {
[email protected]8cb5d5b2010-02-09 11:36:161323 set_encoding(encoding);
1324 render_view_host()->SetPageEncoding(encoding);
1325}
1326
[email protected]b2fe07d12010-02-09 14:38:081327void TabContents::ResetOverrideEncoding() {
[email protected]8cb5d5b2010-02-09 11:36:161328 reset_encoding();
1329 render_view_host()->ResetPageEncodingToDefault();
1330}
1331
1332void TabContents::WindowMoveOrResizeStarted() {
1333 render_view_host()->WindowMoveOrResizeStarted();
1334}
1335
[email protected]3f8eb7f2009-10-02 23:58:051336void TabContents::LogNewTabTime(const std::string& event_name) {
1337 // Not all new tab pages get timed. In those cases, we don't have a
1338 // new_tab_start_time_.
1339 if (new_tab_start_time_.is_null())
1340 return;
1341
1342 base::TimeDelta duration = base::TimeTicks::Now() - new_tab_start_time_;
[email protected]84abba62009-10-07 17:01:441343 MetricEventDurationDetails details(event_name,
1344 static_cast<int>(duration.InMilliseconds()));
1345
[email protected]7ab1e7d62009-10-14 23:32:011346 if (event_name == "Tab.NewTabScriptStart") {
1347 UMA_HISTOGRAM_TIMES("Tab.NewTabScriptStart", duration);
1348 } else if (event_name == "Tab.NewTabDOMContentLoaded") {
1349 UMA_HISTOGRAM_TIMES("Tab.NewTabDOMContentLoaded", duration);
1350 } else if (event_name == "Tab.NewTabOnload") {
1351 UMA_HISTOGRAM_TIMES("Tab.NewTabOnload", duration);
[email protected]3f8eb7f2009-10-02 23:58:051352 // The new tab page has finished loading; reset it.
1353 new_tab_start_time_ = base::TimeTicks();
[email protected]84abba62009-10-07 17:01:441354 } else {
1355 NOTREACHED();
[email protected]3f8eb7f2009-10-02 23:58:051356 }
[email protected]84abba62009-10-07 17:01:441357 NotificationService::current()->Notify(
1358 NotificationType::METRIC_EVENT_DURATION,
1359 Source<TabContents>(this),
1360 Details<MetricEventDurationDetails>(&details));
[email protected]3f8eb7f2009-10-02 23:58:051361}
1362
[email protected]7ab1e7d62009-10-14 23:32:011363void TabContents::OnCloseStarted() {
1364 if (tab_close_start_time_.is_null())
1365 tab_close_start_time_ = base::TimeTicks::Now();
1366}
1367
[email protected]46624bf2010-06-09 16:04:191368bool TabContents::ShouldAcceptDragAndDrop() const {
1369#if defined(OS_CHROMEOS)
1370 // ChromeOS panels (pop-ups) do not take drag-n-drop.
1371 // See http://crosbug.com/2413
1372 return delegate() && !delegate()->IsPopup(const_cast<TabContents*>(this));
1373#else
1374 return true;
1375#endif
1376}
1377
[email protected]c37e3b62010-01-22 00:15:171378TabContents* TabContents::CloneAndMakePhantom() {
[email protected]c37e3b62010-01-22 00:15:171379 TabNavigation tab_nav;
[email protected]df72ac72010-02-06 00:43:161380
1381 NavigationEntry* entry = controller().GetActiveEntry();
[email protected]98aa0b52010-05-06 17:03:081382 if (extension_app_)
1383 tab_nav.set_virtual_url(extension_app_->GetFullLaunchURL());
[email protected]df72ac72010-02-06 00:43:161384 else if (entry)
1385 tab_nav.SetFromNavigationEntry(*entry);
1386
[email protected]c37e3b62010-01-22 00:15:171387 std::vector<TabNavigation> navigations;
1388 navigations.push_back(tab_nav);
1389
1390 TabContents* new_contents =
1391 new TabContents(profile(), NULL, MSG_ROUTING_NONE, NULL);
[email protected]98aa0b52010-05-06 17:03:081392 new_contents->SetExtensionApp(extension_app_);
[email protected]c37e3b62010-01-22 00:15:171393 new_contents->controller().RestoreFromState(navigations, 0, false);
[email protected]c37e3b62010-01-22 00:15:171394
[email protected]98aa0b52010-05-06 17:03:081395 if (!extension_app_ && entry)
[email protected]df72ac72010-02-06 00:43:161396 new_contents->controller().GetActiveEntry()->favicon() = entry->favicon();
1397
[email protected]c37e3b62010-01-22 00:15:171398 return new_contents;
1399}
1400
[email protected]0de80162010-02-03 04:52:351401// Resets the |content_blocked_| array.
1402void TabContents::ClearBlockedContentSettings() {
[email protected]15cf526b2010-02-12 06:33:491403 for (size_t i = 0; i < arraysize(content_blocked_); ++i)
[email protected]0de80162010-02-03 04:52:351404 content_blocked_[i] = false;
1405}
1406
[email protected]96d185d2009-04-24 03:28:541407// Notifies the RenderWidgetHost instance about the fact that the page is
1408// loading, or done loading and calls the base implementation.
1409void TabContents::SetIsLoading(bool is_loading,
1410 LoadNotificationDetails* details) {
1411 if (is_loading == is_loading_)
1412 return;
1413
1414 if (!is_loading) {
1415 load_state_ = net::LOAD_STATE_IDLE;
1416 load_state_host_.clear();
[email protected]094e5b22009-09-25 04:23:561417 upload_size_ = 0;
1418 upload_position_ = 0;
[email protected]96d185d2009-04-24 03:28:541419 }
1420
1421 render_manager_.SetIsLoading(is_loading);
1422
1423 is_loading_ = is_loading;
1424 waiting_for_response_ = is_loading;
1425
1426 if (delegate_)
1427 delegate_->LoadingStateChanged(this);
[email protected]329581b2009-04-28 06:52:351428 NotifyNavigationStateChanged(INVALIDATE_LOAD);
[email protected]96d185d2009-04-24 03:28:541429
1430 NotificationType type = is_loading ? NotificationType::LOAD_START :
1431 NotificationType::LOAD_STOP;
[email protected]ce5c4502009-05-06 16:46:111432 NotificationDetails det = NotificationService::NoDetails();
[email protected]96d185d2009-04-24 03:28:541433 if (details)
1434 det = Details<LoadNotificationDetails>(details);
1435 NotificationService::current()->Notify(type,
1436 Source<NavigationController>(&controller_),
1437 det);
1438}
1439
[email protected]b6c874582009-05-08 19:38:311440void TabContents::AddPopup(TabContents* new_contents,
[email protected]7e7414ae2010-01-26 20:19:291441 const gfx::Rect& initial_pos) {
[email protected]57eda82a2010-05-05 21:28:061442 // A page can't spawn popups (or do anything else, either) until its load
1443 // commits, so when we reach here, the popup was spawned by the
1444 // NavigationController's last committed entry, not the active entry. For
1445 // example, if a page opens a popup in an onunload() handler, then the active
1446 // entry is the page to be loaded as we navigate away from the unloading
1447 // page. For this reason, we can't use GetURL() to get the opener URL,
1448 // because it returns the active entry.
1449 NavigationEntry* entry = controller_.GetLastCommittedEntry();
1450 GURL creator = entry ? entry->virtual_url() : GURL::EmptyGURL();
1451
1452 if (creator.is_valid() &&
[email protected]8cc8d492010-02-02 10:40:491453 profile()->GetHostContentSettingsMap()->GetContentSetting(
[email protected]57eda82a2010-05-05 21:28:061454 creator, CONTENT_SETTINGS_TYPE_POPUPS) == CONTENT_SETTING_ALLOW) {
[email protected]8cc8d492010-02-02 10:40:491455 AddNewContents(new_contents, NEW_POPUP, initial_pos, true);
1456 } else {
1457 if (!blocked_popups_)
1458 blocked_popups_ = new BlockedPopupContainer(this);
1459 blocked_popups_->AddTabContents(new_contents, initial_pos);
1460 }
[email protected]b9681312008-11-07 00:08:261461}
[email protected]616ed5a2008-11-21 22:27:241462
1463namespace {
1464bool TransitionIsReload(PageTransition::Type transition) {
1465 return PageTransition::StripQualifier(transition) == PageTransition::RELOAD;
1466}
1467}
1468
1469void TabContents::ExpireInfoBars(
1470 const NavigationController::LoadCommittedDetails& details) {
1471 // Only hide InfoBars when the user has done something that makes the main
1472 // frame load. We don't want various automatic or subframe navigations making
1473 // it disappear.
1474 if (!details.is_user_initiated_main_frame_load())
1475 return;
1476
[email protected]f86a07022008-11-25 01:06:051477 for (int i = infobar_delegate_count() - 1; i >= 0; --i) {
[email protected]616ed5a2008-11-21 22:27:241478 InfoBarDelegate* delegate = GetInfoBarDelegateAt(i);
[email protected]f86a07022008-11-25 01:06:051479 if (delegate->ShouldExpire(details))
[email protected]616ed5a2008-11-21 22:27:241480 RemoveInfoBar(delegate);
[email protected]616ed5a2008-11-21 22:27:241481 }
1482}
[email protected]fdd61c62009-04-22 19:22:571483
[email protected]96d185d2009-04-24 03:28:541484DOMUI* TabContents::GetDOMUIForCurrentState() {
1485 // When there is a pending navigation entry, we want to use the pending DOMUI
1486 // that goes along with it to control the basic flags. For example, we want to
1487 // show the pending URL in the URL bar, so we want the display_url flag to
1488 // be from the pending entry.
1489 //
1490 // The confusion comes because there are multiple possibilities for the
1491 // initial load in a tab as a side effect of the way the RenderViewHostManager
1492 // works.
1493 //
1494 // - For the very first tab the load looks "normal". The new tab DOM UI is
1495 // the pending one, and we want it to apply here.
1496 //
1497 // - For subsequent new tabs, they'll get a new SiteInstance which will then
1498 // get switched to the one previously associated with the new tab pages.
1499 // This switching will cause the manager to commit the RVH/DOMUI. So we'll
1500 // have a committed DOM UI in this case.
1501 //
1502 // This condition handles all of these cases:
1503 //
1504 // - First load in first tab: no committed nav entry + pending nav entry +
1505 // pending dom ui:
1506 // -> Use pending DOM UI if any.
1507 //
1508 // - First load in second tab: no committed nav entry + pending nav entry +
1509 // no pending DOM UI:
1510 // -> Use the committed DOM UI if any.
1511 //
1512 // - Second navigation in any tab: committed nav entry + pending nav entry:
1513 // -> Use pending DOM UI if any.
1514 //
1515 // - Normal state with no load: committed nav entry + no pending nav entry:
1516 // -> Use committed DOM UI.
1517 if (controller_.pending_entry() &&
1518 (controller_.GetLastCommittedEntry() ||
1519 render_manager_.pending_dom_ui()))
1520 return render_manager_.pending_dom_ui();
1521 return render_manager_.dom_ui();
1522}
[email protected]420ae012009-04-24 05:16:321523
1524void TabContents::DidNavigateMainFramePostCommit(
1525 const NavigationController::LoadCommittedDetails& details,
1526 const ViewHostMsg_FrameNavigate_Params& params) {
[email protected]c2e74fe82009-09-03 17:57:441527 if (opener_dom_ui_type_ != DOMUIFactory::kNoDOMUI) {
1528 // If this is a window.open navigation, use the same DOMUI as the renderer
1529 // that opened the window, as long as both renderers have the same
1530 // privileges.
1531 if (opener_dom_ui_type_ == DOMUIFactory::GetDOMUIType(GetURL())) {
1532 DOMUI* dom_ui = DOMUIFactory::CreateDOMUIForURL(this, GetURL());
1533 // dom_ui might be NULL if the URL refers to a non-existent extension.
1534 if (dom_ui) {
1535 render_manager_.SetDOMUIPostCommit(dom_ui);
1536 dom_ui->RenderViewCreated(render_view_host());
1537 }
1538 }
1539 opener_dom_ui_type_ = DOMUIFactory::kNoDOMUI;
1540 }
1541
[email protected]420ae012009-04-24 05:16:321542 if (details.is_user_initiated_main_frame_load()) {
1543 // Clear the status bubble. This is a workaround for a bug where WebKit
1544 // doesn't let us know that the cursor left an element during a
1545 // transition (this is also why the mouse cursor remains as a hand after
1546 // clicking on a link); see bugs 1184641 and 980803. We don't want to
1547 // clear the bubble when a user navigates to a named anchor in the same
1548 // page.
1549 UpdateTargetURL(details.entry->page_id(), GURL());
1550
1551 // UpdateHelpersForDidNavigate will handle the case where the password_form
1552 // origin is valid.
1553 // TODO(brettw) bug 1343111: Password manager stuff in here needs to be
1554 // cleaned up and covered by tests.
1555 if (!params.password_form.origin.is_valid())
1556 GetPasswordManager()->DidNavigate();
1557 }
1558
1559 // The keyword generator uses the navigation entries, so must be called after
1560 // the commit.
1561 GenerateKeywordIfNecessary(params);
1562
1563 // Allow the new page to set the title again.
1564 received_page_title_ = false;
1565
1566 // Get the favicon, either from history or request it from the net.
1567 fav_icon_helper_.FetchFavIcon(details.entry->url());
1568
[email protected]0de80162010-02-03 04:52:351569 // Clear all page actions, blocked content notifications and browser actions
1570 // for this tab, unless this is an in-page navigation.
[email protected]a6e82fc2010-02-24 22:28:141571 if (!details.is_in_page) {
[email protected]92c6f9b92009-10-24 04:35:081572 ExtensionsService* service = profile()->GetExtensionsService();
1573 if (service) {
1574 for (size_t i = 0; i < service->extensions()->size(); ++i) {
[email protected]5d246db22009-10-27 06:17:571575 ExtensionAction* browser_action =
[email protected]92c6f9b92009-10-24 04:35:081576 service->extensions()->at(i)->browser_action();
[email protected]56ce6e52009-10-27 00:10:521577 if (browser_action) {
1578 browser_action->ClearAllValuesForTab(controller().session_id().id());
1579 NotificationService::current()->Notify(
1580 NotificationType::EXTENSION_BROWSER_ACTION_UPDATED,
[email protected]5d246db22009-10-27 06:17:571581 Source<ExtensionAction>(browser_action),
[email protected]56ce6e52009-10-27 00:10:521582 NotificationService::NoDetails());
1583 }
[email protected]92c6f9b92009-10-24 04:35:081584
[email protected]5d246db22009-10-27 06:17:571585 ExtensionAction* page_action =
[email protected]56ce6e52009-10-27 00:10:521586 service->extensions()->at(i)->page_action();
1587 if (page_action) {
1588 page_action->ClearAllValuesForTab(controller().session_id().id());
1589 PageActionStateChanged();
1590 }
[email protected]92c6f9b92009-10-24 04:35:081591 }
[email protected]aece2c7f2009-08-27 20:43:171592 }
[email protected]0de80162010-02-03 04:52:351593
1594 // Close blocked popups.
1595 if (blocked_popups_) {
[email protected]0fbd70332010-06-01 19:28:341596 AutoReset<bool> auto_reset(&dont_notify_render_view_, true);
[email protected]0de80162010-02-03 04:52:351597 blocked_popups_->Destroy();
[email protected]da7b5262010-02-25 21:12:461598 blocked_popups_ = NULL;
[email protected]0de80162010-02-03 04:52:351599 }
1600
1601 // Clear "blocked" flags.
1602 ClearBlockedContentSettings();
[email protected]777a7b62010-05-11 13:28:161603 geolocation_settings_state_.DidNavigate(details);
[email protected]0de80162010-02-03 04:52:351604 if (delegate_)
[email protected]20ad6a92010-04-21 14:07:241605 delegate_->OnContentSettingsChange(this);
[email protected]f17a0ee2010-05-17 17:38:471606
1607 // Once the main frame is navigated, we're no longer considered to have
1608 // displayed insecure content.
1609 displayed_insecure_content_ = false;
[email protected]aece2c7f2009-08-27 20:43:171610 }
[email protected]ce5c4502009-05-06 16:46:111611
[email protected]8cc8d492010-02-02 10:40:491612 // Close constrained windows if necessary.
1613 if (!net::RegistryControlledDomainService::SameDomainOrHost(
1614 details.previous_url, details.entry->url()))
1615 CloseConstrainedWindows();
1616
[email protected]420ae012009-04-24 05:16:321617 // Update the starred state.
1618 UpdateStarredStateForCurrentURL();
[email protected]c07c9752010-03-12 05:57:531619
1620 // Clear the cache of forms in AutoFill.
1621 if (autofill_manager_.get())
1622 autofill_manager_->Reset();
[email protected]a888b29e62010-04-01 13:38:571623
1624 // The url likely changed, see if there is an extension whose extent contains
1625 // the current page.
[email protected]98aa0b52010-05-06 17:03:081626 UpdateExtensionAppForCurrentPage();
[email protected]420ae012009-04-24 05:16:321627}
1628
1629void TabContents::DidNavigateAnyFramePostCommit(
1630 RenderViewHost* render_view_host,
1631 const NavigationController::LoadCommittedDetails& details,
1632 const ViewHostMsg_FrameNavigate_Params& params) {
1633 // If we navigate, start showing messages again. This does nothing to prevent
1634 // a malicious script from spamming messages, since the script could just
1635 // reload the page to stop blocking.
1636 suppress_javascript_messages_ = false;
1637
[email protected]420ae012009-04-24 05:16:321638 // Notify the password manager of the navigation or form submit.
1639 // TODO(brettw) bug 1343111: Password manager stuff in here needs to be
1640 // cleaned up and covered by tests.
1641 if (params.password_form.origin.is_valid())
1642 GetPasswordManager()->ProvisionallySavePassword(params.password_form);
[email protected]3b1c1812010-02-12 21:53:551643
1644 // Let the LanguageState clear its state.
[email protected]34cec8d82010-03-05 18:27:011645 bool reload = details.entry->transition_type() == PageTransition::RELOAD ||
1646 details.type == NavigationType::SAME_PAGE;
1647 language_state_.DidNavigate(reload, details.is_in_page);
[email protected]420ae012009-04-24 05:16:321648}
1649
[email protected]8cc8d492010-02-02 10:40:491650void TabContents::CloseConstrainedWindows() {
1651 // Clear out any constrained windows since we are leaving this page entirely.
[email protected]420ae012009-04-24 05:16:321652 // We use indices instead of iterators in case CloseWindow does something
1653 // that may invalidate an iterator.
1654 int size = static_cast<int>(child_windows_.size());
1655 for (int i = size - 1; i >= 0; --i) {
1656 ConstrainedWindow* window = child_windows_[i];
[email protected]fa1cf0b82010-01-15 21:49:441657 if (window) {
[email protected]420ae012009-04-24 05:16:321658 window->CloseConstrainedWindow();
[email protected]fa1cf0b82010-01-15 21:49:441659 BlockTabContent(false);
1660 }
[email protected]420ae012009-04-24 05:16:321661 }
1662}
1663
1664void TabContents::UpdateStarredStateForCurrentURL() {
1665 BookmarkModel* model = profile()->GetBookmarkModel();
1666 const bool old_state = is_starred_;
1667 is_starred_ = (model && model->IsBookmarked(GetURL()));
1668
1669 if (is_starred_ != old_state && delegate())
1670 delegate()->URLStarredChanged(this, is_starred_);
1671}
1672
1673void TabContents::UpdateAlternateErrorPageURL() {
1674 GURL url = GetAlternateErrorPageURL();
1675 render_view_host()->SetAlternateErrorPageURL(url);
1676}
1677
1678void TabContents::UpdateWebPreferences() {
1679 render_view_host()->UpdateWebPreferences(GetWebkitPrefs());
1680}
1681
1682void TabContents::UpdateMaxPageIDIfNecessary(SiteInstance* site_instance,
1683 RenderViewHost* rvh) {
1684 // If we are creating a RVH for a restored controller, then we might
1685 // have more page IDs than the SiteInstance's current max page ID. We must
1686 // make sure that the max page ID is larger than any restored page ID.
1687 // Note that it is ok for conflicting page IDs to exist in another tab
1688 // (i.e., NavigationController), but if any page ID is larger than the max,
1689 // the back/forward list will get confused.
1690 int max_restored_page_id = controller_.max_restored_page_id();
1691 if (max_restored_page_id > 0) {
1692 int curr_max_page_id = site_instance->max_page_id();
1693 if (max_restored_page_id > curr_max_page_id) {
1694 // Need to update the site instance immediately.
1695 site_instance->UpdateMaxPageID(max_restored_page_id);
1696
1697 // Also tell the renderer to update its internal representation. We
1698 // need to reserve enough IDs to make all restored page IDs less than
1699 // the max.
1700 if (curr_max_page_id < 0)
1701 curr_max_page_id = 0;
1702 rvh->ReservePageIDRange(max_restored_page_id - curr_max_page_id);
1703 }
1704 }
1705}
1706
1707void TabContents::UpdateHistoryForNavigation(
[email protected]ebe89e062009-08-13 23:16:541708 const GURL& virtual_url,
[email protected]befd8d822009-07-01 04:51:471709 const NavigationController::LoadCommittedDetails& details,
[email protected]420ae012009-04-24 05:16:321710 const ViewHostMsg_FrameNavigate_Params& params) {
1711 if (profile()->IsOffTheRecord())
1712 return;
1713
1714 // Add to history service.
1715 HistoryService* hs = profile()->GetHistoryService(Profile::IMPLICIT_ACCESS);
1716 if (hs) {
1717 if (PageTransition::IsMainFrame(params.transition) &&
[email protected]ebe89e062009-08-13 23:16:541718 virtual_url != params.url) {
1719 // Hack on the "virtual" URL so that it will appear in history. For some
[email protected]420ae012009-04-24 05:16:321720 // types of URLs, we will display a magic URL that is different from where
1721 // the page is actually navigated. We want the user to see in history
[email protected]ebe89e062009-08-13 23:16:541722 // what they saw in the URL bar, so we add the virtual URL as a redirect.
1723 // This only applies to the main frame, as the virtual URL doesn't apply
[email protected]420ae012009-04-24 05:16:321724 // to sub-frames.
1725 std::vector<GURL> redirects = params.redirects;
1726 if (!redirects.empty())
[email protected]ebe89e062009-08-13 23:16:541727 redirects.back() = virtual_url;
1728 hs->AddPage(virtual_url, this, params.page_id, params.referrer,
[email protected]befd8d822009-07-01 04:51:471729 params.transition, redirects, details.did_replace_entry);
[email protected]420ae012009-04-24 05:16:321730 } else {
1731 hs->AddPage(params.url, this, params.page_id, params.referrer,
[email protected]befd8d822009-07-01 04:51:471732 params.transition, params.redirects,
1733 details.did_replace_entry);
[email protected]420ae012009-04-24 05:16:321734 }
1735 }
1736}
1737
1738bool TabContents::UpdateTitleForEntry(NavigationEntry* entry,
1739 const std::wstring& title) {
1740 // For file URLs without a title, use the pathname instead. In the case of a
1741 // synthesized title, we don't want the update to count toward the "one set
1742 // per page of the title to history."
1743 std::wstring final_title;
1744 bool explicit_set;
1745 if (entry->url().SchemeIsFile() && title.empty()) {
1746 final_title = UTF8ToWide(entry->url().ExtractFileName());
1747 explicit_set = false; // Don't count synthetic titles toward the set limit.
1748 } else {
1749 TrimWhitespace(title, TRIM_ALL, &final_title);
1750 explicit_set = true;
1751 }
1752
1753 if (final_title == UTF16ToWideHack(entry->title()))
1754 return false; // Nothing changed, don't bother.
1755
1756 entry->set_title(WideToUTF16Hack(final_title));
1757
1758 // Update the history system for this page.
1759 if (!profile()->IsOffTheRecord() && !received_page_title_) {
1760 HistoryService* hs =
1761 profile()->GetHistoryService(Profile::IMPLICIT_ACCESS);
1762 if (hs)
[email protected]ebe89e062009-08-13 23:16:541763 hs->SetPageTitle(entry->virtual_url(), final_title);
[email protected]420ae012009-04-24 05:16:321764
1765 // Don't allow the title to be saved again for explicitly set ones.
1766 received_page_title_ = explicit_set;
1767 }
1768
1769 // Lastly, set the title for the view.
1770 view_->SetPageTitle(final_title);
1771
[email protected]cbc0e1b2010-04-12 18:33:041772 NotificationService::current()->Notify(
1773 NotificationType::TAB_CONTENTS_TITLE_UPDATED,
1774 Source<TabContents>(this),
1775 NotificationService::NoDetails());
1776
[email protected]420ae012009-04-24 05:16:321777 return true;
1778}
1779
1780void TabContents::NotifySwapped() {
1781 // After sending out a swap notification, we need to send a disconnect
1782 // notification so that clients that pick up a pointer to |this| can NULL the
1783 // pointer. See Bug 1230284.
1784 notify_disconnection_ = true;
1785 NotificationService::current()->Notify(
[email protected]57c6a652009-05-04 07:58:341786 NotificationType::TAB_CONTENTS_SWAPPED,
[email protected]d82ed61e2009-06-16 02:46:221787 Source<TabContents>(this),
[email protected]420ae012009-04-24 05:16:321788 NotificationService::NoDetails());
1789}
1790
1791void TabContents::NotifyConnected() {
1792 notify_disconnection_ = true;
1793 NotificationService::current()->Notify(
[email protected]57c6a652009-05-04 07:58:341794 NotificationType::TAB_CONTENTS_CONNECTED,
[email protected]d82ed61e2009-06-16 02:46:221795 Source<TabContents>(this),
[email protected]420ae012009-04-24 05:16:321796 NotificationService::NoDetails());
1797}
1798
1799void TabContents::NotifyDisconnected() {
1800 if (!notify_disconnection_)
1801 return;
1802
1803 notify_disconnection_ = false;
1804 NotificationService::current()->Notify(
[email protected]57c6a652009-05-04 07:58:341805 NotificationType::TAB_CONTENTS_DISCONNECTED,
[email protected]d82ed61e2009-06-16 02:46:221806 Source<TabContents>(this),
[email protected]420ae012009-04-24 05:16:321807 NotificationService::NoDetails());
1808}
1809
1810void TabContents::GenerateKeywordIfNecessary(
1811 const ViewHostMsg_FrameNavigate_Params& params) {
1812 if (!params.searchable_form_url.is_valid())
1813 return;
1814
1815 if (profile()->IsOffTheRecord())
1816 return;
1817
1818 int last_index = controller_.last_committed_entry_index();
1819 // When there was no previous page, the last index will be 0. This is
1820 // normally due to a form submit that opened in a new tab.
1821 // TODO(brettw) bug 916126: we should support keywords when form submits
1822 // happen in new tabs.
1823 if (last_index <= 0)
1824 return;
1825 const NavigationEntry* previous_entry =
1826 controller_.GetEntryAtIndex(last_index - 1);
1827 if (IsFormSubmit(previous_entry)) {
1828 // Only generate a keyword if the previous page wasn't itself a form
1829 // submit.
1830 return;
1831 }
1832
1833 GURL keyword_url = previous_entry->user_typed_url().is_valid() ?
1834 previous_entry->user_typed_url() : previous_entry->url();
1835 std::wstring keyword =
1836 TemplateURLModel::GenerateKeyword(keyword_url, true); // autodetected
1837 if (keyword.empty())
1838 return;
1839
1840 TemplateURLModel* url_model = profile()->GetTemplateURLModel();
1841 if (!url_model)
1842 return;
1843
1844 if (!url_model->loaded()) {
1845 url_model->Load();
1846 return;
1847 }
1848
1849 const TemplateURL* current_url;
1850 std::wstring url = UTF8ToWide(params.searchable_form_url.spec());
1851 if (!url_model->CanReplaceKeyword(keyword, url, &current_url))
1852 return;
1853
1854 if (current_url) {
1855 if (current_url->originating_url().is_valid()) {
1856 // The existing keyword was generated from an OpenSearch description
1857 // document, don't regenerate.
1858 return;
1859 }
1860 url_model->Remove(current_url);
1861 }
1862 TemplateURL* new_url = new TemplateURL();
1863 new_url->set_keyword(keyword);
1864 new_url->set_short_name(keyword);
1865 new_url->SetURL(url, 0, 0);
1866 new_url->add_input_encoding(params.searchable_form_encoding);
1867 DCHECK(controller_.GetLastCommittedEntry());
1868 const GURL& favicon_url =
1869 controller_.GetLastCommittedEntry()->favicon().url();
1870 if (favicon_url.is_valid()) {
1871 new_url->SetFavIconURL(favicon_url);
1872 } else {
1873 // The favicon url isn't valid. This means there really isn't a favicon,
1874 // or the favicon url wasn't obtained before the load started. This assumes
1875 // the later.
1876 // TODO(sky): Need a way to set the favicon that doesn't involve generating
1877 // its url.
1878 new_url->SetFavIconURL(TemplateURL::GenerateFaviconURL(params.referrer));
1879 }
1880 new_url->set_safe_for_autoreplace(true);
1881 url_model->Add(new_url);
1882}
1883
[email protected]bf5c2ff392009-07-08 16:24:331884void TabContents::OnUserGesture() {
1885 // See comment in RenderViewHostDelegate::OnUserGesture as to why we do this.
1886 DownloadRequestManager* drm = g_browser_process->download_request_manager();
1887 if (drm)
1888 drm->OnUserGesture(this);
[email protected]e7eaedde2009-09-25 20:09:491889 ExternalProtocolHandler::OnUserGesture();
[email protected]bf5c2ff392009-07-08 16:24:331890 controller_.OnUserGesture();
1891}
1892
1893void TabContents::OnFindReply(int request_id,
1894 int number_of_matches,
1895 const gfx::Rect& selection_rect,
1896 int active_match_ordinal,
1897 bool final_update) {
[email protected]3ce7ced2009-07-24 18:52:421898 // Ignore responses for requests that have been aborted.
1899 if (find_op_aborted_)
1900 return;
1901
[email protected]bf5c2ff392009-07-08 16:24:331902 // Ignore responses for requests other than the one we have most recently
1903 // issued. That way we won't act on stale results when the user has
1904 // already typed in another query.
1905 if (request_id != current_find_request_id_)
1906 return;
1907
1908 if (number_of_matches == -1)
1909 number_of_matches = last_search_result_.number_of_matches();
1910 if (active_match_ordinal == -1)
1911 active_match_ordinal = last_search_result_.active_match_ordinal();
1912
1913 gfx::Rect selection = selection_rect;
1914 if (selection.IsEmpty())
1915 selection = last_search_result_.selection_rect();
1916
1917 // Notify the UI, automation and any other observers that a find result was
1918 // found.
1919 last_search_result_ = FindNotificationDetails(request_id, number_of_matches,
1920 selection, active_match_ordinal,
1921 final_update);
1922 NotificationService::current()->Notify(
1923 NotificationType::FIND_RESULT_AVAILABLE,
1924 Source<TabContents>(this),
1925 Details<FindNotificationDetails>(&last_search_result_));
1926}
1927
1928void TabContents::GoToEntryAtOffset(int offset) {
[email protected]f9cc4c452009-10-13 14:56:381929 if (!delegate_ || delegate_->OnGoToEntryOffset(offset))
1930 controller_.GoToOffset(offset);
[email protected]bf5c2ff392009-07-08 16:24:331931}
1932
[email protected]bf5c2ff392009-07-08 16:24:331933void TabContents::OnMissingPluginStatus(int status) {
1934#if defined(OS_WIN)
1935// TODO(PORT): pull in when plug-ins work
1936 GetPluginInstaller()->OnMissingPluginStatus(status);
1937#endif
1938}
1939
1940void TabContents::OnCrashedPlugin(const FilePath& plugin_path) {
[email protected]bf5c2ff392009-07-08 16:24:331941 DCHECK(!plugin_path.value().empty());
1942
1943 std::wstring plugin_name = plugin_path.ToWStringHack();
[email protected]d32d46182009-07-23 00:09:351944#if defined(OS_WIN) || defined(OS_MACOSX)
[email protected]bf5c2ff392009-07-08 16:24:331945 scoped_ptr<FileVersionInfo> version_info(
1946 FileVersionInfo::CreateFileVersionInfo(plugin_path));
1947 if (version_info.get()) {
1948 const std::wstring& product_name = version_info->product_name();
[email protected]996fd702009-09-04 19:12:371949 if (!product_name.empty()) {
[email protected]bf5c2ff392009-07-08 16:24:331950 plugin_name = product_name;
[email protected]996fd702009-09-04 19:12:371951#if defined(OS_MACOSX)
1952 // Many plugins on the Mac have .plugin in the actual name, which looks
1953 // terrible, so look for that and strip it off if present.
1954 const std::wstring plugin_extension(L".plugin");
1955 if (EndsWith(plugin_name, plugin_extension, true))
1956 plugin_name.erase(plugin_name.length() - plugin_extension.length());
1957#endif // OS_MACOSX
1958 }
[email protected]bf5c2ff392009-07-08 16:24:331959 }
[email protected]4a560ed2009-07-13 23:35:261960#else
1961 NOTIMPLEMENTED() << " convert plugin path to plugin name";
1962#endif
[email protected]bf5c2ff392009-07-08 16:24:331963 AddInfoBar(new SimpleAlertInfoBarDelegate(
1964 this, l10n_util::GetStringF(IDS_PLUGIN_CRASHED_PROMPT, plugin_name),
[email protected]938e1f92010-04-01 18:09:421965 NULL, true));
[email protected]bf5c2ff392009-07-08 16:24:331966}
1967
1968void TabContents::OnCrashedWorker() {
1969 AddInfoBar(new SimpleAlertInfoBarDelegate(
1970 this, l10n_util::GetString(IDS_WEBWORKER_CRASHED_PROMPT),
[email protected]938e1f92010-04-01 18:09:421971 NULL, true));
[email protected]bf5c2ff392009-07-08 16:24:331972}
1973
1974void TabContents::OnDidGetApplicationInfo(
1975 int32 page_id,
1976 const webkit_glue::WebApplicationInfo& info) {
[email protected]ed5431872009-11-17 08:39:511977 web_app_info_ = info;
[email protected]bf5c2ff392009-07-08 16:24:331978
[email protected]ed5431872009-11-17 08:39:511979 if (delegate())
1980 delegate()->OnDidGetApplicationInfo(this, page_id);
[email protected]bf5c2ff392009-07-08 16:24:331981}
1982
[email protected]a2cf65eb2010-01-18 08:20:381983void TabContents::OnPageContents(const GURL& url,
1984 int renderer_process_id,
1985 int32 page_id,
[email protected]e5106202010-06-11 21:12:361986 const string16& contents,
[email protected]a8a81292010-01-21 00:32:451987 const std::string& language) {
[email protected]a2cf65eb2010-01-18 08:20:381988 // Don't index any https pages. People generally don't want their bank
1989 // accounts, etc. indexed on their computer, especially since some of these
1990 // things are not marked cachable.
1991 // TODO(brettw) we may want to consider more elaborate heuristics such as
1992 // the cachability of the page. We may also want to consider subframes (this
1993 // test will still index subframes if the subframe is SSL).
[email protected]ccd40a52010-05-11 16:15:271994 // TODO(zelidrag) bug chromium-os:2808 - figure out if we want to reenable
1995 // content indexing for chromeos in some future releases.
1996#if !defined(OS_CHROMEOS)
[email protected]a2cf65eb2010-01-18 08:20:381997 if (!url.SchemeIsSecure()) {
1998 Profile* p = profile();
1999 if (p && !p->IsOffTheRecord()) {
2000 HistoryService* hs = p->GetHistoryService(Profile::IMPLICIT_ACCESS);
2001 if (hs)
2002 hs->SetPageContents(url, contents);
2003 }
2004 }
[email protected]ccd40a52010-05-11 16:15:272005#endif
[email protected]a8a81292010-01-21 00:32:452006
[email protected]3b1c1812010-02-12 21:53:552007 language_state_.LanguageDetermined(language);
[email protected]a8a81292010-01-21 00:32:452008
2009 std::string lang = language;
2010 NotificationService::current()->Notify(
2011 NotificationType::TAB_LANGUAGE_DETERMINED,
[email protected]7e0831b2010-02-01 08:45:152012 Source<TabContents>(this),
[email protected]a8a81292010-01-21 00:32:452013 Details<std::string>(&lang));
[email protected]a2cf65eb2010-01-18 08:20:382014}
2015
[email protected]7e0831b2010-02-01 08:45:152016void TabContents::OnPageTranslated(int32 page_id,
2017 const std::string& original_lang,
[email protected]152b8ba32010-03-29 19:40:162018 const std::string& translated_lang,
2019 TranslateErrors::Type error_type) {
[email protected]3b1c1812010-02-12 21:53:552020 language_state_.set_current_language(translated_lang);
2021 language_state_.set_translation_pending(false);
[email protected]152b8ba32010-03-29 19:40:162022 PageTranslatedDetails details(original_lang, translated_lang, error_type);
[email protected]7e0831b2010-02-01 08:45:152023 NotificationService::current()->Notify(
2024 NotificationType::PAGE_TRANSLATED,
2025 Source<TabContents>(this),
[email protected]152b8ba32010-03-29 19:40:162026 Details<PageTranslatedDetails>(&details));
[email protected]7e0831b2010-02-01 08:45:152027}
2028
[email protected]bf5c2ff392009-07-08 16:24:332029void TabContents::DidStartProvisionalLoadForFrame(
2030 RenderViewHost* render_view_host,
2031 bool is_main_frame,
2032 const GURL& url) {
2033 ProvisionalLoadDetails details(is_main_frame,
2034 controller_.IsURLInPageNavigation(url),
2035 url, std::string(), false);
2036 NotificationService::current()->Notify(
2037 NotificationType::FRAME_PROVISIONAL_LOAD_START,
2038 Source<NavigationController>(&controller_),
2039 Details<ProvisionalLoadDetails>(&details));
2040}
2041
2042void TabContents::DidStartReceivingResourceResponse(
[email protected]3dbb80b2010-02-09 22:41:202043 const ResourceRequestDetails& details) {
[email protected]bf5c2ff392009-07-08 16:24:332044 NotificationService::current()->Notify(
2045 NotificationType::RESOURCE_RESPONSE_STARTED,
2046 Source<NavigationController>(&controller()),
[email protected]3dbb80b2010-02-09 22:41:202047 Details<const ResourceRequestDetails>(&details));
[email protected]bf5c2ff392009-07-08 16:24:332048}
2049
[email protected]3dbb80b2010-02-09 22:41:202050void TabContents::DidRedirectResource(
2051 const ResourceRedirectDetails& details) {
[email protected]bf5c2ff392009-07-08 16:24:332052 NotificationService::current()->Notify(
2053 NotificationType::RESOURCE_RECEIVED_REDIRECT,
2054 Source<NavigationController>(&controller()),
[email protected]3dbb80b2010-02-09 22:41:202055 Details<const ResourceRequestDetails>(&details));
[email protected]bf5c2ff392009-07-08 16:24:332056}
2057
2058void TabContents::DidLoadResourceFromMemoryCache(
2059 const GURL& url,
2060 const std::string& frame_origin,
2061 const std::string& main_frame_origin,
2062 const std::string& security_info) {
2063 // Send out a notification that we loaded a resource from our memory cache.
2064 int cert_id = 0, cert_status = 0, security_bits = 0;
2065 SSLManager::DeserializeSecurityInfo(security_info,
2066 &cert_id, &cert_status,
2067 &security_bits);
2068 LoadFromMemoryCacheDetails details(url, frame_origin, main_frame_origin,
[email protected]8cb5d5b2010-02-09 11:36:162069 GetRenderProcessHost()->id(), cert_id,
2070 cert_status);
[email protected]bf5c2ff392009-07-08 16:24:332071
2072 NotificationService::current()->Notify(
2073 NotificationType::LOAD_FROM_MEMORY_CACHE,
2074 Source<NavigationController>(&controller_),
2075 Details<LoadFromMemoryCacheDetails>(&details));
2076}
2077
[email protected]e3d60e5d2009-09-25 21:08:292078void TabContents::DidDisplayInsecureContent() {
[email protected]f17a0ee2010-05-17 17:38:472079 displayed_insecure_content_ = true;
2080 SSLManager::NotifySSLInternalStateChanged();
[email protected]e3d60e5d2009-09-25 21:08:292081}
2082
2083void TabContents::DidRunInsecureContent(const std::string& security_origin) {
[email protected]09843b5f2009-09-26 08:30:592084 controller_.ssl_manager()->DidRunInsecureContent(security_origin);
[email protected]e3d60e5d2009-09-25 21:08:292085}
2086
[email protected]bf5c2ff392009-07-08 16:24:332087void TabContents::DidFailProvisionalLoadWithError(
2088 RenderViewHost* render_view_host,
2089 bool is_main_frame,
2090 int error_code,
2091 const GURL& url,
2092 bool showing_repost_interstitial) {
2093 if (net::ERR_ABORTED == error_code) {
2094 // EVIL HACK ALERT! Ignore failed loads when we're showing interstitials.
2095 // This means that the interstitial won't be torn down properly, which is
2096 // bad. But if we have an interstitial, go back to another tab type, and
2097 // then load the same interstitial again, we could end up getting the first
2098 // interstitial's "failed" message (as a result of the cancel) when we're on
2099 // the second one.
2100 //
2101 // We can't tell this apart, so we think we're tearing down the current page
2102 // which will cause a crash later one. There is also some code in
2103 // RenderViewHostManager::RendererAbortedProvisionalLoad that is commented
2104 // out because of this problem.
2105 //
2106 // http://code.google.com/p/chromium/issues/detail?id=2855
2107 // Because this will not tear down the interstitial properly, if "back" is
2108 // back to another tab type, the interstitial will still be somewhat alive
2109 // in the previous tab type. If you navigate somewhere that activates the
2110 // tab with the interstitial again, you'll see a flash before the new load
2111 // commits of the interstitial page.
2112 if (showing_interstitial_page()) {
2113 LOG(WARNING) << "Discarding message during interstitial.";
2114 return;
2115 }
2116
2117 // This will discard our pending entry if we cancelled the load (e.g., if we
2118 // decided to download the file instead of load it). Only discard the
2119 // pending entry if the URLs match, otherwise the user initiated a navigate
2120 // before the page loaded so that the discard would discard the wrong entry.
2121 NavigationEntry* pending_entry = controller_.pending_entry();
2122 if (pending_entry && pending_entry->url() == url) {
2123 controller_.DiscardNonCommittedEntries();
2124 // Update the URL display.
2125 NotifyNavigationStateChanged(TabContents::INVALIDATE_URL);
2126 }
2127
2128 render_manager_.RendererAbortedProvisionalLoad(render_view_host);
2129 }
2130
2131 // Send out a notification that we failed a provisional load with an error.
2132 ProvisionalLoadDetails details(is_main_frame,
2133 controller_.IsURLInPageNavigation(url),
2134 url, std::string(), false);
2135 details.set_error_code(error_code);
2136
2137 NotificationService::current()->Notify(
2138 NotificationType::FAIL_PROVISIONAL_LOAD_WITH_ERROR,
2139 Source<NavigationController>(&controller_),
2140 Details<ProvisionalLoadDetails>(&details));
2141}
2142
2143void TabContents::DocumentLoadedInFrame() {
2144 controller_.DocumentLoadedInFrame();
[email protected]f017d8d2010-06-10 00:22:562145
2146 render_view_host()->SetDocumentLoaded(true);
[email protected]bf5c2ff392009-07-08 16:24:332147}
2148
[email protected]0de80162010-02-03 04:52:352149void TabContents::OnContentBlocked(ContentSettingsType type) {
[email protected]b1235062010-03-25 17:31:272150 // TODO(joth): remove once fully implemented.
2151 DCHECK(type != CONTENT_SETTINGS_TYPE_GEOLOCATION);
[email protected]0de80162010-02-03 04:52:352152 content_blocked_[type] = true;
2153 if (delegate_)
[email protected]20ad6a92010-04-21 14:07:242154 delegate_->OnContentSettingsChange(this);
[email protected]0de80162010-02-03 04:52:352155}
2156
[email protected]614c0e12010-03-25 10:12:562157void TabContents::OnGeolocationPermissionSet(const GURL& requesting_origin,
2158 bool allowed) {
[email protected]777a7b62010-05-11 13:28:162159 geolocation_settings_state_.OnGeolocationPermissionSet(requesting_origin,
2160 allowed);
[email protected]614c0e12010-03-25 10:12:562161 if (delegate_)
[email protected]20ad6a92010-04-21 14:07:242162 delegate_->OnContentSettingsChange(this);
[email protected]614c0e12010-03-25 10:12:562163}
2164
[email protected]8d3347f2009-07-09 22:00:212165RenderViewHostDelegate::View* TabContents::GetViewDelegate() {
[email protected]420ae012009-04-24 05:16:322166 return view_.get();
2167}
2168
[email protected]8d3347f2009-07-09 22:00:212169RenderViewHostDelegate::RendererManagement*
2170TabContents::GetRendererManagementDelegate() {
2171 return &render_manager_;
2172}
2173
[email protected]bf5c2ff392009-07-08 16:24:332174RenderViewHostDelegate::BrowserIntegration*
[email protected]8d3347f2009-07-09 22:00:212175 TabContents::GetBrowserIntegrationDelegate() {
2176 return this;
[email protected]bf5c2ff392009-07-08 16:24:332177}
2178
[email protected]8d3347f2009-07-09 22:00:212179RenderViewHostDelegate::Resource* TabContents::GetResourceDelegate() {
2180 return this;
[email protected]bf5c2ff392009-07-08 16:24:332181}
2182
[email protected]8d3347f2009-07-09 22:00:212183RenderViewHostDelegate::Save* TabContents::GetSaveDelegate() {
[email protected]420ae012009-04-24 05:16:322184 return save_package_.get(); // May be NULL, but we can return NULL.
2185}
2186
[email protected]8d3347f2009-07-09 22:00:212187RenderViewHostDelegate::Printing* TabContents::GetPrintingDelegate() {
2188 return &printing_;
2189}
2190
2191RenderViewHostDelegate::FavIcon* TabContents::GetFavIconDelegate() {
2192 return &fav_icon_helper_;
2193}
2194
[email protected]e8dbd674b2010-03-11 18:34:402195RenderViewHostDelegate::Autocomplete* TabContents::GetAutocompleteDelegate() {
[email protected]6db0def92010-03-02 19:55:452196 if (autocomplete_history_manager_.get() == NULL)
2197 autocomplete_history_manager_.reset(new AutocompleteHistoryManager(this));
2198 return autocomplete_history_manager_.get();
[email protected]bf5c2ff392009-07-08 16:24:332199}
2200
[email protected]21674df2009-10-28 19:51:212201RenderViewHostDelegate::AutoFill* TabContents::GetAutoFillDelegate() {
[email protected]cf28ec52010-04-09 22:56:342202 return GetAutoFillManager();
[email protected]21674df2009-10-28 19:51:212203}
2204
[email protected]fd571bb2010-03-19 01:23:542205AutomationResourceRoutingDelegate*
2206TabContents::GetAutomationResourceRoutingDelegate() {
2207 return delegate();
2208}
2209
[email protected]ced90ae12010-02-20 02:06:162210RenderViewHostDelegate::BookmarkDrag* TabContents::GetBookmarkDragDelegate() {
2211 return bookmark_drag_;
2212}
2213
2214void TabContents::SetBookmarkDragDelegate(
2215 RenderViewHostDelegate::BookmarkDrag* bookmark_drag) {
2216 bookmark_drag_ = bookmark_drag;
2217}
2218
[email protected]93623c5d2009-12-10 21:40:322219RendererPreferences TabContents::GetRendererPrefs(Profile* profile) const {
[email protected]840b1512009-07-21 16:53:462220 return renderer_preferences_;
[email protected]80d96fa2009-06-10 22:34:512221}
2222
[email protected]57c6a652009-05-04 07:58:342223TabContents* TabContents::GetAsTabContents() {
2224 return this;
2225}
2226
[email protected]7b291f92009-08-14 05:43:532227ViewType::Type TabContents::GetRenderViewType() const {
2228 return ViewType::TAB_CONTENTS;
2229}
2230
2231int TabContents::GetBrowserWindowID() const {
2232 return controller().window_id().id();
2233}
2234
[email protected]420ae012009-04-24 05:16:322235void TabContents::RenderViewCreated(RenderViewHost* render_view_host) {
[email protected]2e4633c2009-07-09 16:58:062236 NotificationService::current()->Notify(
2237 NotificationType::RENDER_VIEW_HOST_CREATED_FOR_TAB,
2238 Source<TabContents>(this),
2239 Details<RenderViewHost>(render_view_host));
[email protected]420ae012009-04-24 05:16:322240 NavigationEntry* entry = controller_.GetActiveEntry();
2241 if (!entry)
2242 return;
2243
2244 // When we're creating views, we're still doing initial setup, so we always
2245 // use the pending DOM UI rather than any possibly existing committed one.
2246 if (render_manager_.pending_dom_ui()) {
2247 render_manager_.pending_dom_ui()->RenderViewCreated(render_view_host);
2248 }
2249
2250 if (entry->IsViewSourceMode()) {
2251 // Put the renderer in view source mode.
2252 render_view_host->Send(
2253 new ViewMsg_EnableViewSourceMode(render_view_host->routing_id()));
2254 }
[email protected]0666aef2009-05-13 19:48:082255
2256 view()->RenderViewCreated(render_view_host);
[email protected]420ae012009-04-24 05:16:322257}
2258
2259void TabContents::RenderViewReady(RenderViewHost* rvh) {
2260 if (rvh != render_view_host()) {
2261 // Don't notify the world, since this came from a renderer in the
2262 // background.
2263 return;
2264 }
2265
2266 NotifyConnected();
[email protected]9d8a4642009-07-29 17:25:302267 bool was_crashed = is_crashed();
[email protected]420ae012009-04-24 05:16:322268 SetIsCrashed(false);
[email protected]9d8a4642009-07-29 17:25:302269
2270 // Restore the focus to the tab (otherwise the focus will be on the top
2271 // window).
2272 if (was_crashed && !FocusLocationBarByDefault())
2273 Focus();
[email protected]420ae012009-04-24 05:16:322274}
2275
2276void TabContents::RenderViewGone(RenderViewHost* rvh) {
2277 // Ask the print preview if this renderer was valuable.
2278 if (!printing_.OnRenderViewGone(rvh))
2279 return;
2280 if (rvh != render_view_host()) {
2281 // The pending page's RenderViewHost is gone.
2282 return;
2283 }
2284
2285 SetIsLoading(false, NULL);
2286 NotifyDisconnected();
2287 SetIsCrashed(true);
2288
[email protected]ff9efc62010-02-18 22:10:542289 // Remove all infobars.
[email protected]e5430c92010-02-18 22:39:212290 for (int i = infobar_delegate_count() - 1; i >=0 ; --i)
[email protected]ff9efc62010-02-18 22:10:542291 RemoveInfoBar(GetInfoBarDelegateAt(i));
2292
[email protected]8e537302009-06-10 21:19:582293 // Tell the view that we've crashed so it can prepare the sad tab page.
[email protected]cf68b092010-01-15 20:05:552294 // Only do this if we're not in browser shutdown, so that TabContents
2295 // objects that are not in a browser (e.g., HTML dialogs) and thus are
2296 // visible do not flash a sad tab page.
2297 if (browser_shutdown::GetShutdownType() == browser_shutdown::NOT_VALID)
2298 view_->OnTabCrashed();
[email protected]420ae012009-04-24 05:16:322299
2300 // Hide any visible hung renderer warning for this web contents' process.
[email protected]e7b8d832009-11-20 22:41:002301 hung_renderer_dialog::HideForTabContents(this);
[email protected]420ae012009-04-24 05:16:322302}
2303
[email protected]2e4633c2009-07-09 16:58:062304void TabContents::RenderViewDeleted(RenderViewHost* rvh) {
2305 NotificationService::current()->Notify(
2306 NotificationType::RENDER_VIEW_HOST_DELETED,
2307 Source<TabContents>(this),
2308 Details<RenderViewHost>(rvh));
[email protected]fb7b79f72009-11-06 18:00:482309 render_manager_.RenderViewDeleted(rvh);
[email protected]2e4633c2009-07-09 16:58:062310}
2311
[email protected]420ae012009-04-24 05:16:322312void TabContents::DidNavigate(RenderViewHost* rvh,
2313 const ViewHostMsg_FrameNavigate_Params& params) {
[email protected]8030f012009-09-25 18:09:372314 int extra_invalidate_flags = 0;
2315
[email protected]f017d8d2010-06-10 00:22:562316 render_view_host()->SetDocumentLoaded(false);
[email protected]b3df5a42010-05-11 14:31:092317
[email protected]8030f012009-09-25 18:09:372318 if (PageTransition::IsMainFrame(params.transition)) {
[email protected]20ede072009-10-06 00:28:352319 bool was_bookmark_bar_visible = ShouldShowBookmarkBar();
[email protected]8030f012009-09-25 18:09:372320 bool was_extension_shelf_visible = IsExtensionShelfAlwaysVisible();
2321
[email protected]420ae012009-04-24 05:16:322322 render_manager_.DidNavigateMainFrame(rvh);
2323
[email protected]20ede072009-10-06 00:28:352324 if (was_bookmark_bar_visible != ShouldShowBookmarkBar())
[email protected]8030f012009-09-25 18:09:372325 extra_invalidate_flags |= INVALIDATE_BOOKMARK_BAR;
2326 if (was_extension_shelf_visible != IsExtensionShelfAlwaysVisible())
2327 extra_invalidate_flags |= INVALIDATE_EXTENSION_SHELF;
2328 }
2329
[email protected]420ae012009-04-24 05:16:322330 // Update the site of the SiteInstance if it doesn't have one yet.
2331 if (!GetSiteInstance()->has_site())
2332 GetSiteInstance()->SetSite(params.url);
2333
2334 // Need to update MIME type here because it's referred to in
2335 // UpdateNavigationCommands() called by RendererDidNavigate() to
2336 // determine whether or not to enable the encoding menu.
2337 // It's updated only for the main frame. For a subframe,
2338 // RenderView::UpdateURL does not set params.contents_mime_type.
2339 // (see http://code.google.com/p/chromium/issues/detail?id=2929 )
2340 // TODO(jungshik): Add a test for the encoding menu to avoid
2341 // regressing it again.
2342 if (PageTransition::IsMainFrame(params.transition))
2343 contents_mime_type_ = params.contents_mime_type;
2344
2345 NavigationController::LoadCommittedDetails details;
[email protected]8030f012009-09-25 18:09:372346 bool did_navigate = controller_.RendererDidNavigate(
2347 params, extra_invalidate_flags, &details);
[email protected]3e90d4a2009-07-03 17:38:392348
2349 // Update history. Note that this needs to happen after the entry is complete,
2350 // which WillNavigate[Main,Sub]Frame will do before this function is called.
[email protected]2e29d922009-10-22 22:13:352351 if (params.should_update_history &&
2352 (!delegate() || delegate()->ShouldAddNavigationsToHistory())) {
[email protected]3e90d4a2009-07-03 17:38:392353 // Most of the time, the displayURL matches the loaded URL, but for about:
2354 // URLs, we use a data: URL as the real value. We actually want to save
2355 // the about: URL to the history db and keep the data: URL hidden. This is
2356 // what the TabContents' URL getter does.
2357 UpdateHistoryForNavigation(GetURL(), details, params);
2358 }
2359
[email protected]76543b92009-08-31 17:27:452360 if (!did_navigate)
2361 return; // No navigation happened.
[email protected]420ae012009-04-24 05:16:322362
2363 // DO NOT ADD MORE STUFF TO THIS FUNCTION! Your component should either listen
2364 // for the appropriate notification (best) or you can add it to
2365 // DidNavigateMainFramePostCommit / DidNavigateAnyFramePostCommit (only if
2366 // necessary, please).
2367
2368 // Run post-commit tasks.
2369 if (details.is_main_frame)
2370 DidNavigateMainFramePostCommit(details, params);
2371 DidNavigateAnyFramePostCommit(rvh, details, params);
2372}
2373
2374void TabContents::UpdateState(RenderViewHost* rvh,
2375 int32 page_id,
2376 const std::string& state) {
2377 DCHECK(rvh == render_view_host());
2378
2379 // We must be prepared to handle state updates for any page, these occur
2380 // when the user is scrolling and entering form data, as well as when we're
2381 // leaving a page, in which case our state may have already been moved to
2382 // the next page. The navigation controller will look up the appropriate
2383 // NavigationEntry and update it when it is notified via the delegate.
2384
2385 int entry_index = controller_.GetEntryIndexWithPageID(
2386 GetSiteInstance(), page_id);
2387 if (entry_index < 0)
2388 return;
2389 NavigationEntry* entry = controller_.GetEntryAtIndex(entry_index);
2390
2391 if (state == entry->content_state())
2392 return; // Nothing to update.
2393 entry->set_content_state(state);
2394 controller_.NotifyEntryChanged(entry, entry_index);
2395}
2396
2397void TabContents::UpdateTitle(RenderViewHost* rvh,
2398 int32 page_id, const std::wstring& title) {
2399 // If we have a title, that's a pretty good indication that we've started
2400 // getting useful data.
2401 SetNotWaitingForResponse();
2402
2403 DCHECK(rvh == render_view_host());
2404 NavigationEntry* entry = controller_.GetEntryWithPageID(GetSiteInstance(),
2405 page_id);
2406 if (!entry || !UpdateTitleForEntry(entry, title))
2407 return;
2408
2409 // Broadcast notifications when the UI should be updated.
2410 if (entry == controller_.GetEntryAtOffset(0))
[email protected]f1cd5e82009-10-23 17:19:032411 NotifyNavigationStateChanged(INVALIDATE_TITLE);
[email protected]420ae012009-04-24 05:16:322412}
2413
[email protected]420ae012009-04-24 05:16:322414void TabContents::UpdateEncoding(RenderViewHost* render_view_host,
[email protected]41fc0322009-09-04 22:23:402415 const std::string& encoding) {
[email protected]420ae012009-04-24 05:16:322416 set_encoding(encoding);
2417}
2418
2419void TabContents::UpdateTargetURL(int32 page_id, const GURL& url) {
2420 if (delegate())
2421 delegate()->UpdateTargetURL(this, url);
2422}
2423
2424void TabContents::UpdateThumbnail(const GURL& url,
2425 const SkBitmap& bitmap,
2426 const ThumbnailScore& score) {
2427 // Tell History about this thumbnail
[email protected]523623c2010-05-19 16:03:422428 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kTopSites)) {
[email protected]72d0fc72009-07-09 17:30:492429 if (!profile()->IsOffTheRecord())
[email protected]523623c2010-05-19 16:03:422430 profile()->GetTopSites()->SetPageThumbnail(url, bitmap, score);
[email protected]449478302009-06-09 20:04:282431 } else {
2432 HistoryService* hs;
2433 if (!profile()->IsOffTheRecord() &&
2434 (hs = profile()->GetHistoryService(Profile::IMPLICIT_ACCESS))) {
2435 hs->SetPageThumbnail(url, bitmap, score);
2436 }
[email protected]420ae012009-04-24 05:16:322437 }
2438}
2439
[email protected]c4e98902010-06-01 10:20:142440void TabContents::UpdateInspectorSetting(const std::string& key,
2441 const std::string& value) {
2442 DictionaryValue* inspector_settings =
2443 profile()->GetPrefs()->GetMutableDictionary(
2444 prefs::kWebKitInspectorSettings);
[email protected]628cf5a52010-06-07 14:25:332445 inspector_settings->SetWithoutPathExpansion(UTF8ToWide(key),
2446 Value::CreateStringValue(value));
[email protected]0df30122009-06-03 12:13:082447}
2448
[email protected]45aafc92010-06-07 14:18:532449void TabContents::ClearInspectorSettings() {
2450 DictionaryValue* inspector_settings =
2451 profile()->GetPrefs()->GetMutableDictionary(
2452 prefs::kWebKitInspectorSettings);
2453 inspector_settings->Clear();
2454}
2455
[email protected]420ae012009-04-24 05:16:322456void TabContents::Close(RenderViewHost* rvh) {
[email protected]07707302009-11-06 00:50:292457 // The UI may be in an event-tracking loop, such as between the
2458 // mouse-down and mouse-up in text selection or a button click.
2459 // Defer the close until after tracking is complete, so that we
2460 // don't free objects out from under the UI.
2461 // TODO(shess): This could probably be integrated with the
2462 // IsDoingDrag() test below. Punting for now because I need more
2463 // research to understand how this impacts platforms other than Mac.
2464 // TODO(shess): This could get more fine-grained. For instance,
2465 // closing a tab in another window while selecting text in the
2466 // current window's Omnibox should be just fine.
2467 if (view()->IsEventTracking()) {
2468 view()->CloseTabAfterEventTracking();
2469 return;
2470 }
2471
[email protected]24a4d1062009-07-10 23:10:422472 // If we close the tab while we're in the middle of a drag, we'll crash.
2473 // Instead, cancel the drag and close it as soon as the drag ends.
2474 if (view()->IsDoingDrag()) {
2475 view()->CancelDragAndCloseTab();
2476 return;
2477 }
2478
[email protected]420ae012009-04-24 05:16:322479 // Ignore this if it comes from a RenderViewHost that we aren't showing.
2480 if (delegate() && rvh == render_view_host())
2481 delegate()->CloseContents(this);
2482}
2483
2484void TabContents::RequestMove(const gfx::Rect& new_bounds) {
2485 if (delegate() && delegate()->IsPopup(this))
2486 delegate()->MoveContents(this, new_bounds);
2487}
2488
[email protected]7ab1e7d62009-10-14 23:32:012489void TabContents::DidStartLoading() {
[email protected]420ae012009-04-24 05:16:322490 SetIsLoading(true, NULL);
2491}
2492
[email protected]7ab1e7d62009-10-14 23:32:012493void TabContents::DidStopLoading() {
[email protected]420ae012009-04-24 05:16:322494 scoped_ptr<LoadNotificationDetails> details;
2495
2496 NavigationEntry* entry = controller_.GetActiveEntry();
2497 // An entry may not exist for a stop when loading an initial blank page or
2498 // if an iframe injected by script into a blank page finishes loading.
2499 if (entry) {
[email protected]420ae012009-04-24 05:16:322500 base::TimeDelta elapsed = base::TimeTicks::Now() - current_load_start_;
2501
2502 details.reset(new LoadNotificationDetails(
[email protected]ebe89e062009-08-13 23:16:542503 entry->virtual_url(),
[email protected]420ae012009-04-24 05:16:322504 entry->transition_type(),
2505 elapsed,
2506 &controller_,
2507 controller_.GetCurrentEntryIndex()));
2508 }
2509
2510 // Tell PasswordManager we've finished a page load, which serves as a
2511 // green light to save pending passwords and reset itself.
2512 GetPasswordManager()->DidStopLoading();
2513
2514 SetIsLoading(false, details.get());
2515}
2516
[email protected]420ae012009-04-24 05:16:322517void TabContents::DidRedirectProvisionalLoad(int32 page_id,
2518 const GURL& source_url,
2519 const GURL& target_url) {
2520 NavigationEntry* entry;
2521 if (page_id == -1)
2522 entry = controller_.pending_entry();
2523 else
2524 entry = controller_.GetEntryWithPageID(GetSiteInstance(), page_id);
2525 if (!entry || entry->url() != source_url)
2526 return;
2527 entry->set_url(target_url);
2528}
2529
[email protected]420ae012009-04-24 05:16:322530void TabContents::RequestOpenURL(const GURL& url, const GURL& referrer,
2531 WindowOpenDisposition disposition) {
2532 if (render_manager_.dom_ui()) {
2533 // When we're a DOM UI, it will provide a page transition type for us (this
2534 // is so the new tab page can specify AUTO_BOOKMARK for automatically
2535 // generated suggestions).
2536 //
2537 // Note also that we hide the referrer for DOM UI pages. We don't really
[email protected]60e448982009-05-06 04:21:162538 // want web sites to see a referrer of "chrome://blah" (and some
2539 // chrome: URLs might have search terms or other stuff we don't want to
[email protected]420ae012009-04-24 05:16:322540 // send to the site), so we send no referrer.
2541 OpenURL(url, GURL(), disposition,
2542 render_manager_.dom_ui()->link_transition_type());
2543 } else {
2544 OpenURL(url, referrer, disposition, PageTransition::LINK);
2545 }
2546}
2547
[email protected]1ee614862009-07-06 20:29:182548void TabContents::DomOperationResponse(const std::string& json_string,
2549 int automation_id) {
2550}
2551
[email protected]420ae012009-04-24 05:16:322552void TabContents::ProcessDOMUIMessage(const std::string& message,
[email protected]438c97d2010-05-21 23:30:152553 const ListValue* content,
[email protected]bb64b512010-04-02 21:01:392554 const GURL& source_url,
[email protected]811bfe32009-07-01 08:46:252555 int request_id,
2556 bool has_callback) {
[email protected]420ae012009-04-24 05:16:322557 if (!render_manager_.dom_ui()) {
[email protected]c2e74fe82009-09-03 17:57:442558 // This can happen if someone uses window.open() to open an extension URL
2559 // from a non-extension context.
2560 render_view_host()->BlockExtensionRequest(request_id);
[email protected]420ae012009-04-24 05:16:322561 return;
2562 }
[email protected]bb64b512010-04-02 21:01:392563 render_manager_.dom_ui()->ProcessDOMUIMessage(message, content, source_url,
2564 request_id,
[email protected]811bfe32009-07-01 08:46:252565 has_callback);
[email protected]420ae012009-04-24 05:16:322566}
2567
2568void TabContents::ProcessExternalHostMessage(const std::string& message,
2569 const std::string& origin,
2570 const std::string& target) {
2571 if (delegate())
2572 delegate()->ForwardMessageToExternalHost(message, origin, target);
2573}
2574
[email protected]cdaf8d02010-03-30 19:52:472575void TabContents::RunFileChooser(
2576 const ViewHostMsg_RunFileChooser_Params &params) {
[email protected]420ae012009-04-24 05:16:322577 if (!select_file_dialog_.get())
2578 select_file_dialog_ = SelectFileDialog::Create(this);
[email protected]cdaf8d02010-03-30 19:52:472579
2580 SelectFileDialog::Type dialog_type;
2581 switch (params.mode) {
2582 case ViewHostMsg_RunFileChooser_Params::Open:
2583 dialog_type = SelectFileDialog::SELECT_OPEN_FILE;
2584 break;
2585 case ViewHostMsg_RunFileChooser_Params::OpenMultiple:
2586 dialog_type = SelectFileDialog::SELECT_OPEN_MULTI_FILE;
2587 break;
2588 case ViewHostMsg_RunFileChooser_Params::Save:
2589 dialog_type = SelectFileDialog::SELECT_SAVEAS_FILE;
2590 break;
2591 default:
[email protected]bed31952010-03-30 20:07:592592 dialog_type = SelectFileDialog::SELECT_OPEN_FILE; // Prevent warning.
[email protected]cdaf8d02010-03-30 19:52:472593 NOTREACHED();
2594 }
[email protected]35896a32010-06-09 08:42:512595 FilePath default_file_name = params.default_file_name;
2596 if (default_file_name.empty())
2597 default_file_name = profile()->last_selected_directory();
[email protected]cdaf8d02010-03-30 19:52:472598 select_file_dialog_->SelectFile(dialog_type, params.title,
[email protected]35896a32010-06-09 08:42:512599 default_file_name,
[email protected]420ae012009-04-24 05:16:322600 NULL, 0, FILE_PATH_LITERAL(""),
2601 view_->GetTopLevelNativeWindow(), NULL);
2602}
2603
2604void TabContents::RunJavaScriptMessage(
2605 const std::wstring& message,
2606 const std::wstring& default_prompt,
2607 const GURL& frame_url,
2608 const int flags,
2609 IPC::Message* reply_msg,
2610 bool* did_suppress_message) {
2611 // Suppress javascript messages when requested and when inside a constrained
2612 // popup window (because that activates them and breaks them out of the
2613 // constrained window jail).
[email protected]91ed49a2009-07-07 21:29:552614 // Also suppress messages when showing an interstitial. The interstitial is
2615 // shown over the previous page, we don't want the hidden page dialogs to
2616 // interfere with the interstitial.
2617 bool suppress_this_message = suppress_javascript_messages_ ||
2618 showing_interstitial_page();
[email protected]420ae012009-04-24 05:16:322619 if (delegate())
2620 suppress_this_message |=
[email protected]b6c874582009-05-08 19:38:312621 (delegate()->GetConstrainingContents(this) != this);
[email protected]420ae012009-04-24 05:16:322622
2623 *did_suppress_message = suppress_this_message;
2624
2625 if (!suppress_this_message) {
2626 base::TimeDelta time_since_last_message(
2627 base::TimeTicks::Now() - last_javascript_message_dismissal_);
2628 bool show_suppress_checkbox = false;
2629 // Show a checkbox offering to suppress further messages if this message is
2630 // being displayed within kJavascriptMessageExpectedDelay of the last one.
2631 if (time_since_last_message <
2632 base::TimeDelta::FromMilliseconds(kJavascriptMessageExpectedDelay))
2633 show_suppress_checkbox = true;
2634
[email protected]d82ed61e2009-06-16 02:46:222635 RunJavascriptMessageBox(this, frame_url, flags, message, default_prompt,
[email protected]420ae012009-04-24 05:16:322636 show_suppress_checkbox, reply_msg);
2637 } else {
2638 // If we are suppressing messages, just reply as is if the user immediately
2639 // pressed "Cancel".
[email protected]beb440c2009-11-06 04:08:542640 OnMessageBoxClosed(reply_msg, false, std::wstring());
[email protected]420ae012009-04-24 05:16:322641 }
2642}
2643
2644void TabContents::RunBeforeUnloadConfirm(const std::wstring& message,
2645 IPC::Message* reply_msg) {
[email protected]7ab1e7d62009-10-14 23:32:012646 is_showing_before_unload_dialog_ = true;
[email protected]d82ed61e2009-06-16 02:46:222647 RunBeforeUnloadDialog(this, message, reply_msg);
[email protected]420ae012009-04-24 05:16:322648}
2649
2650void TabContents::ShowModalHTMLDialog(const GURL& url, int width, int height,
2651 const std::string& json_arguments,
2652 IPC::Message* reply_msg) {
2653 if (delegate()) {
2654 HtmlDialogUIDelegate* dialog_delegate =
2655 new ModalHtmlDialogDelegate(url, width, height, json_arguments,
[email protected]d82ed61e2009-06-16 02:46:222656 reply_msg, this);
[email protected]420ae012009-04-24 05:16:322657 delegate()->ShowHtmlDialog(dialog_delegate, NULL);
2658 }
2659}
2660
[email protected]4d44a1c2010-04-28 19:20:412661void TabContents::PasswordFormsFound(
[email protected]ed3fb032009-06-16 19:50:562662 const std::vector<webkit_glue::PasswordForm>& forms) {
[email protected]4d44a1c2010-04-28 19:20:412663 GetPasswordManager()->PasswordFormsFound(forms);
2664}
2665
2666void TabContents::PasswordFormsVisible(
2667 const std::vector<webkit_glue::PasswordForm>& visible_forms) {
2668 GetPasswordManager()->PasswordFormsVisible(visible_forms);
[email protected]420ae012009-04-24 05:16:322669}
2670
[email protected]420ae012009-04-24 05:16:322671// Checks to see if we should generate a keyword based on the OSDD, and if
2672// necessary uses TemplateURLFetcher to download the OSDD and create a keyword.
2673void TabContents::PageHasOSDD(RenderViewHost* render_view_host,
2674 int32 page_id, const GURL& url,
2675 bool autodetected) {
2676 // Make sure page_id is the current page, and the TemplateURLModel is loaded.
2677 DCHECK(url.is_valid());
2678 if (!IsActiveEntry(page_id))
2679 return;
2680 TemplateURLModel* url_model = profile()->GetTemplateURLModel();
2681 if (!url_model)
2682 return;
2683 if (!url_model->loaded()) {
2684 url_model->Load();
2685 return;
2686 }
2687 if (!profile()->GetTemplateURLFetcher())
2688 return;
2689
2690 if (profile()->IsOffTheRecord())
2691 return;
2692
2693 const NavigationEntry* entry = controller_.GetLastCommittedEntry();
2694 DCHECK(entry);
2695
2696 const NavigationEntry* base_entry = entry;
2697 if (IsFormSubmit(base_entry)) {
2698 // If the current page is a form submit, find the last page that was not
2699 // a form submit and use its url to generate the keyword from.
2700 int index = controller_.last_committed_entry_index() - 1;
2701 while (index >= 0 && IsFormSubmit(controller_.GetEntryAtIndex(index)))
2702 index--;
2703 if (index >= 0)
2704 base_entry = controller_.GetEntryAtIndex(index);
2705 else
2706 base_entry = NULL;
2707 }
2708
2709 // We want to use the user typed URL if available since that represents what
2710 // the user typed to get here, and fall back on the regular URL if not.
2711 if (!base_entry)
2712 return;
2713 GURL keyword_url = base_entry->user_typed_url().is_valid() ?
2714 base_entry->user_typed_url() : base_entry->url();
2715 if (!keyword_url.is_valid())
2716 return;
2717 std::wstring keyword = TemplateURLModel::GenerateKeyword(keyword_url,
2718 autodetected);
[email protected]a88dbdd52010-01-15 19:25:532719
2720 // For JS added OSDD empty keyword is OK because we will generate keyword
2721 // later from OSDD content.
2722 if (autodetected && keyword.empty())
[email protected]420ae012009-04-24 05:16:322723 return;
2724 const TemplateURL* template_url =
2725 url_model->GetTemplateURLForKeyword(keyword);
2726 if (template_url && (!template_url->safe_for_autoreplace() ||
2727 template_url->originating_url() == url)) {
2728 // Either there is a user created TemplateURL for this keyword, or the
2729 // keyword has the same OSDD url and we've parsed it.
2730 return;
2731 }
2732
2733 // Download the OpenSearch description document. If this is successful a
2734 // new keyword will be created when done.
[email protected]420ae012009-04-24 05:16:322735 profile()->GetTemplateURLFetcher()->ScheduleDownload(
2736 keyword,
2737 url,
2738 base_entry->favicon().url(),
[email protected]d0cc9fb52009-06-23 02:26:162739 this,
[email protected]420ae012009-04-24 05:16:322740 autodetected);
2741}
2742
[email protected]420ae012009-04-24 05:16:322743GURL TabContents::GetAlternateErrorPageURL() const {
2744 GURL url;
2745 // Disable alternate error pages when in OffTheRecord/Incognito mode.
2746 if (profile()->IsOffTheRecord())
2747 return url;
2748
2749 PrefService* prefs = profile()->GetPrefs();
2750 DCHECK(prefs);
2751 if (prefs->GetBoolean(prefs::kAlternateErrorPagesEnabled)) {
[email protected]a33457b82009-09-21 23:07:152752 url = google_util::AppendGoogleLocaleParam(
2753 GURL(google_util::kLinkDoctorBaseURL));
[email protected]420ae012009-04-24 05:16:322754 url = google_util::AppendGoogleTLDParam(url);
2755 }
2756 return url;
2757}
2758
2759WebPreferences TabContents::GetWebkitPrefs() {
[email protected]6c32ce72010-03-08 05:18:062760 Profile* profile = render_view_host()->process()->profile();
[email protected]7ccddb8c2009-08-04 17:36:552761 bool is_dom_ui = false;
[email protected]6c32ce72010-03-08 05:18:062762 return RenderViewHostDelegateHelper::GetWebkitPrefs(profile, is_dom_ui);
[email protected]420ae012009-04-24 05:16:322763}
2764
[email protected]fa1cf0b82010-01-15 21:49:442765void TabContents::OnIgnoredUIEvent() {
2766 if (constrained_window_count()) {
2767 ConstrainedWindow* window = *constrained_window_begin();
2768 window->FocusConstrainedWindow();
2769 }
2770}
2771
[email protected]420ae012009-04-24 05:16:322772void TabContents::OnJSOutOfMemory() {
2773 AddInfoBar(new SimpleAlertInfoBarDelegate(
[email protected]938e1f92010-04-01 18:09:422774 this, l10n_util::GetString(IDS_JS_OUT_OF_MEMORY_PROMPT), NULL, true));
[email protected]420ae012009-04-24 05:16:322775}
2776
[email protected]420ae012009-04-24 05:16:322777void TabContents::OnCrossSiteResponse(int new_render_process_host_id,
2778 int new_request_id) {
[email protected]57c6a652009-05-04 07:58:342779 // Allows the TabContents to react when a cross-site response is ready to be
[email protected]420ae012009-04-24 05:16:322780 // delivered to a pending RenderViewHost. We must first run the onunload
2781 // handler of the old RenderViewHost before we can allow it to proceed.
2782 render_manager_.OnCrossSiteResponse(new_render_process_host_id,
2783 new_request_id);
2784}
2785
2786bool TabContents::CanBlur() const {
2787 return delegate() ? delegate()->CanBlur() : true;
2788}
2789
2790gfx::Rect TabContents::GetRootWindowResizerRect() const {
2791 if (delegate())
2792 return delegate()->GetRootWindowResizerRect();
2793 return gfx::Rect();
2794}
2795
2796void TabContents::RendererUnresponsive(RenderViewHost* rvh,
2797 bool is_during_unload) {
2798 if (is_during_unload) {
2799 // Hang occurred while firing the beforeunload/unload handler.
2800 // Pretend the handler fired so tab closing continues as if it had.
[email protected]829e7612009-04-25 01:15:112801 rvh->set_sudden_termination_allowed(true);
[email protected]420ae012009-04-24 05:16:322802
2803 if (!render_manager_.ShouldCloseTabOnUnresponsiveRenderer())
2804 return;
2805
2806 // If the tab hangs in the beforeunload/unload handler there's really
2807 // nothing we can do to recover. Pretend the unload listeners have
2808 // all fired and close the tab. If the hang is in the beforeunload handler
2809 // then the user will not have the option of cancelling the close.
2810 Close(rvh);
2811 return;
2812 }
2813
2814 if (render_view_host() && render_view_host()->IsRenderViewLive())
[email protected]e7b8d832009-11-20 22:41:002815 hung_renderer_dialog::ShowForTabContents(this);
[email protected]420ae012009-04-24 05:16:322816}
2817
2818void TabContents::RendererResponsive(RenderViewHost* render_view_host) {
[email protected]e7b8d832009-11-20 22:41:002819 hung_renderer_dialog::HideForTabContents(this);
[email protected]420ae012009-04-24 05:16:322820}
2821
2822void TabContents::LoadStateChanged(const GURL& url,
[email protected]094e5b22009-09-25 04:23:562823 net::LoadState load_state,
2824 uint64 upload_position,
2825 uint64 upload_size) {
[email protected]420ae012009-04-24 05:16:322826 load_state_ = load_state;
[email protected]094e5b22009-09-25 04:23:562827 upload_position_ = upload_position;
2828 upload_size_ = upload_size;
[email protected]d686e812009-06-03 19:10:292829 std::wstring languages =
2830 profile()->GetPrefs()->GetString(prefs::kAcceptLanguages);
[email protected]d686e812009-06-03 19:10:292831 std::string host = url.host();
[email protected]ce85f602009-11-07 01:34:532832 load_state_host_ =
2833 net::IDNToUnicode(host.c_str(), host.size(), languages, NULL);
[email protected]420ae012009-04-24 05:16:322834 if (load_state_ == net::LOAD_STATE_READING_RESPONSE)
2835 SetNotWaitingForResponse();
2836 if (is_loading())
[email protected]c9cd2222009-05-06 05:16:502837 NotifyNavigationStateChanged(INVALIDATE_LOAD | INVALIDATE_TAB);
[email protected]420ae012009-04-24 05:16:322838}
2839
[email protected]1ee614862009-07-06 20:29:182840bool TabContents::IsExternalTabContainer() const {
2841 if (!delegate())
2842 return false;
2843
2844 return delegate()->IsExternalTabContainer();
2845}
2846
[email protected]1ee614862009-07-06 20:29:182847void TabContents::DidInsertCSS() {
2848 // This RVHDelegate function is used for extensions and not us.
[email protected]420ae012009-04-24 05:16:322849}
2850
[email protected]130efb02009-09-18 18:54:352851void TabContents::FocusedNodeChanged() {
2852 NotificationService::current()->Notify(
2853 NotificationType::FOCUS_CHANGED_IN_PAGE,
2854 Source<RenderViewHost>(render_view_host()),
2855 NotificationService::NoDetails());
2856}
2857
[email protected]420ae012009-04-24 05:16:322858void TabContents::FileSelected(const FilePath& path,
2859 int index, void* params) {
[email protected]35896a32010-06-09 08:42:512860 profile()->set_last_selected_directory(path.DirName());
[email protected]cdaf8d02010-03-30 19:52:472861 std::vector<FilePath> files;
2862 files.push_back(path);
2863 render_view_host()->FilesSelectedInChooser(files);
[email protected]420ae012009-04-24 05:16:322864}
2865
2866void TabContents::MultiFilesSelected(const std::vector<FilePath>& files,
2867 void* params) {
[email protected]35896a32010-06-09 08:42:512868 if (!files.empty())
2869 profile()->set_last_selected_directory(files[0].DirName());
[email protected]cdaf8d02010-03-30 19:52:472870 render_view_host()->FilesSelectedInChooser(files);
[email protected]420ae012009-04-24 05:16:322871}
2872
2873void TabContents::FileSelectionCanceled(void* params) {
2874 // If the user cancels choosing a file to upload we pass back an
2875 // empty vector.
[email protected]cdaf8d02010-03-30 19:52:472876 render_view_host()->FilesSelectedInChooser(std::vector<FilePath>());
[email protected]420ae012009-04-24 05:16:322877}
2878
2879void TabContents::BeforeUnloadFiredFromRenderManager(
2880 bool proceed,
2881 bool* proceed_to_fire_unload) {
2882 if (delegate())
2883 delegate()->BeforeUnloadFired(this, proceed, proceed_to_fire_unload);
2884}
2885
2886void TabContents::UpdateRenderViewSizeForRenderManager() {
2887 // TODO(brettw) this is a hack. See TabContentsView::SizeContents.
[email protected]0323ee42010-02-17 22:03:262888 gfx::Size size = view_->GetContainerSize();
2889 // 0x0 isn't a valid window size (minimal window size is 1x1) but it may be
2890 // here during container initialization and normal window size will be set
2891 // later. In case of tab duplication this resizing to 0x0 prevents setting
2892 // normal size later so just ignore it.
2893 if (!size.IsEmpty())
2894 view_->SizeContents(size);
[email protected]420ae012009-04-24 05:16:322895}
2896
2897DOMUI* TabContents::CreateDOMUIForRenderManager(const GURL& url) {
[email protected]d82ed61e2009-06-16 02:46:222898 return DOMUIFactory::CreateDOMUIForURL(this, url);
[email protected]420ae012009-04-24 05:16:322899}
2900
2901NavigationEntry*
2902TabContents::GetLastCommittedNavigationEntryForRenderManager() {
2903 return controller_.GetLastCommittedEntry();
2904}
2905
2906bool TabContents::CreateRenderViewForRenderManager(
2907 RenderViewHost* render_view_host) {
[email protected]420ae012009-04-24 05:16:322908 RenderWidgetHostView* rwh_view = view_->CreateViewForWidget(render_view_host);
[email protected]1a98a932009-11-17 00:12:522909
2910 scoped_refptr<URLRequestContextGetter> request_context = request_context_;
2911 if (!request_context.get())
2912 request_context = profile()->GetRequestContext();
2913
2914 if (!render_view_host->CreateRenderView(request_context))
[email protected]420ae012009-04-24 05:16:322915 return false;
2916
2917 // Now that the RenderView has been created, we need to tell it its size.
2918 rwh_view->SetSize(view_->GetContainerSize());
2919
2920 UpdateMaxPageIDIfNecessary(render_view_host->site_instance(),
2921 render_view_host);
2922 return true;
2923}
2924
2925void TabContents::Observe(NotificationType type,
2926 const NotificationSource& source,
2927 const NotificationDetails& details) {
2928 switch (type.value) {
2929 case NotificationType::BOOKMARK_MODEL_LOADED:
2930 // BookmarkModel finished loading, fall through to update starred state.
2931 case NotificationType::URLS_STARRED: {
2932 // Somewhere, a URL has been starred.
2933 // Ignore notifications for profiles other than our current one.
2934 Profile* source_profile = Source<Profile>(source).ptr();
2935 if (!source_profile || !source_profile->IsSameProfile(profile()))
2936 return;
2937
2938 UpdateStarredStateForCurrentURL();
2939 break;
2940 }
2941 case NotificationType::PREF_CHANGED: {
2942 std::wstring* pref_name_in = Details<std::wstring>(details).ptr();
2943 DCHECK(Source<PrefService>(source).ptr() == profile()->GetPrefs());
2944 if (*pref_name_in == prefs::kAlternateErrorPagesEnabled) {
2945 UpdateAlternateErrorPageURL();
2946 } else if (*pref_name_in == prefs::kDefaultCharset ||
2947 StartsWithASCII(WideToUTF8(*pref_name_in), "webkit.webprefs.", true)
2948 ) {
2949 UpdateWebPreferences();
2950 } else {
2951 NOTREACHED() << "unexpected pref change notification" << *pref_name_in;
2952 }
2953 break;
2954 }
2955 case NotificationType::RENDER_WIDGET_HOST_DESTROYED:
2956 view_->RenderWidgetHostDestroyed(Source<RenderWidgetHost>(source).ptr());
2957 break;
2958
2959 case NotificationType::NAV_ENTRY_COMMITTED: {
2960 DCHECK(&controller_ == Source<NavigationController>(source).ptr());
2961
2962 NavigationController::LoadCommittedDetails& committed_details =
2963 *(Details<NavigationController::LoadCommittedDetails>(details).ptr());
2964 ExpireInfoBars(committed_details);
2965 break;
2966 }
2967
[email protected]d3ba77272009-09-03 00:06:092968#if defined(OS_LINUX)
2969 case NotificationType::BROWSER_THEME_CHANGED: {
[email protected]7ff431e2010-01-07 18:18:542970 renderer_preferences_util::UpdateFromSystemSettings(
2971 &renderer_preferences_, profile());
[email protected]d3ba77272009-09-03 00:06:092972 render_view_host()->SyncRendererPrefs();
2973 break;
2974 }
2975#endif
2976
[email protected]6c32ce72010-03-08 05:18:062977 case NotificationType::USER_STYLE_SHEET_UPDATED:
2978 UpdateWebPreferences();
2979 break;
2980
[email protected]79580c62010-02-02 02:36:252981 case NotificationType::CONTENT_SETTINGS_CHANGED: {
[email protected]0314ae02010-04-08 09:18:292982 Details<const HostContentSettingsMap::ContentSettingsDetails>
[email protected]79580c62010-02-02 02:36:252983 settings_details(details);
[email protected]79580c62010-02-02 02:36:252984 NavigationEntry* entry = controller_.GetActiveEntry();
[email protected]da0c8e92010-02-09 23:25:492985 GURL entry_url;
[email protected]0314ae02010-04-08 09:18:292986 if (entry)
[email protected]da0c8e92010-02-09 23:25:492987 entry_url = entry->url();
[email protected]79580c62010-02-02 02:36:252988 Source<HostContentSettingsMap> content_settings(source);
[email protected]0314ae02010-04-08 09:18:292989 if (settings_details.ptr()->update_all() ||
2990 settings_details.ptr()->pattern().Matches(entry_url)) {
2991 render_view_host()->SendContentSettings(entry_url,
[email protected]da0c8e92010-02-09 23:25:492992 content_settings.ptr()->GetContentSettings(entry_url));
[email protected]79580c62010-02-02 02:36:252993 }
2994 break;
2995 }
2996
[email protected]a888b29e62010-04-01 13:38:572997 case NotificationType::EXTENSION_LOADED: {
[email protected]98aa0b52010-05-06 17:03:082998 if (!extension_app_ && !extension_app_for_current_page_ &&
[email protected]a888b29e62010-04-01 13:38:572999 Source<Profile>(source).ptr() == profile()) {
[email protected]98aa0b52010-05-06 17:03:083000 UpdateExtensionAppForCurrentPage();
3001 if (extension_app_for_current_page_)
[email protected]a888b29e62010-04-01 13:38:573002 NotifyNavigationStateChanged(INVALIDATE_TAB);
3003 }
3004 break;
3005 }
3006
3007 case NotificationType::EXTENSION_UNLOADED:
3008 case NotificationType::EXTENSION_UNLOADED_DISABLED: {
[email protected]98aa0b52010-05-06 17:03:083009 if (extension_app_for_current_page_ ==
[email protected]a888b29e62010-04-01 13:38:573010 Details<Extension>(details).ptr()) {
[email protected]98aa0b52010-05-06 17:03:083011 extension_app_for_current_page_ = NULL;
3012 UpdateExtensionAppForCurrentPage();
[email protected]a888b29e62010-04-01 13:38:573013 NotifyNavigationStateChanged(INVALIDATE_TAB);
3014 }
3015 break;
3016 }
3017
[email protected]420ae012009-04-24 05:16:323018 default:
3019 NOTREACHED();
3020 }
3021}
[email protected]aacd7cc2009-09-02 14:51:103022
[email protected]98aa0b52010-05-06 17:03:083023void TabContents::UpdateExtensionAppIcon(Extension* extension) {
3024 extension_app_icon_.reset();
[email protected]f075fe0a22010-04-26 04:06:433025
[email protected]a888b29e62010-04-01 13:38:573026 if (extension) {
[email protected]98aa0b52010-05-06 17:03:083027 extension_app_image_loader_.reset(new ImageLoadingTracker(this));
3028 extension_app_image_loader_->LoadImage(
[email protected]a888b29e62010-04-01 13:38:573029 extension,
3030 extension->GetIconPath(Extension::EXTENSION_ICON_SMALLISH),
3031 gfx::Size(Extension::EXTENSION_ICON_SMALLISH,
3032 Extension::EXTENSION_ICON_SMALLISH),
3033 ImageLoadingTracker::CACHE);
3034 } else {
[email protected]98aa0b52010-05-06 17:03:083035 extension_app_image_loader_.reset(NULL);
[email protected]a888b29e62010-04-01 13:38:573036 }
3037}
3038
3039Extension* TabContents::GetExtensionContaining(const GURL& url) {
3040 ExtensionsService* extensions_service = profile()->GetExtensionsService();
3041 if (!extensions_service)
3042 return NULL;
3043
3044 Extension* extension = extensions_service->GetExtensionByURL(url);
3045 return extension ?
3046 extension : extensions_service->GetExtensionByWebExtent(url);
3047}
3048
[email protected]98aa0b52010-05-06 17:03:083049void TabContents::UpdateExtensionAppForCurrentPage() {
3050 if (extension_app_) {
[email protected]a888b29e62010-04-01 13:38:573051 // Tab has an explicit app extension; nothing to do.
3052 return;
3053 }
3054
3055 // Check the current extension before iterating through all extensions.
[email protected]98aa0b52010-05-06 17:03:083056 if (extension_app_for_current_page_ &&
3057 extension_app_for_current_page_->web_extent().ContainsURL(GetURL())) {
[email protected]a888b29e62010-04-01 13:38:573058 return;
3059 }
3060
[email protected]98aa0b52010-05-06 17:03:083061 extension_app_for_current_page_ = GetExtensionContaining(GetURL());
3062 UpdateExtensionAppIcon(extension_app_for_current_page_);
[email protected]a888b29e62010-04-01 13:38:573063}
3064
3065void TabContents::OnImageLoaded(SkBitmap* image, ExtensionResource resource,
3066 int index) {
3067 if (image) {
[email protected]98aa0b52010-05-06 17:03:083068 extension_app_icon_ = *image;
[email protected]a888b29e62010-04-01 13:38:573069 NotifyNavigationStateChanged(INVALIDATE_TAB);
3070 }
3071}
3072
[email protected]beb440c2009-11-06 04:08:543073std::wstring TabContents::GetMessageBoxTitle(const GURL& frame_url,
3074 bool is_alert) {
3075 if (!frame_url.has_host())
3076 return l10n_util::GetString(
3077 is_alert ? IDS_JAVASCRIPT_ALERT_DEFAULT_TITLE
3078 : IDS_JAVASCRIPT_MESSAGEBOX_DEFAULT_TITLE);
3079
3080 // We really only want the scheme, hostname, and port.
3081 GURL::Replacements replacements;
3082 replacements.ClearUsername();
3083 replacements.ClearPassword();
3084 replacements.ClearPath();
3085 replacements.ClearQuery();
3086 replacements.ClearRef();
3087 GURL clean_url = frame_url.ReplaceComponents(replacements);
3088
3089 // TODO(brettw) it should be easier than this to do the correct language
3090 // handling without getting the accept language from the profile.
3091 std::wstring base_address = gfx::ElideUrl(clean_url, gfx::Font(), 0,
3092 profile()->GetPrefs()->GetString(prefs::kAcceptLanguages));
3093 // Force URL to have LTR directionality.
[email protected]4a4afe32010-05-05 01:39:563094 base::i18n::GetDisplayStringInLTRDirectionality(&base_address);
[email protected]beb440c2009-11-06 04:08:543095
3096 return l10n_util::GetStringF(
3097 is_alert ? IDS_JAVASCRIPT_ALERT_TITLE : IDS_JAVASCRIPT_MESSAGEBOX_TITLE,
3098 base_address);
3099}
3100
3101gfx::NativeWindow TabContents::GetMessageBoxRootWindow() {
3102 return view_->GetTopLevelNativeWindow();
3103}
3104
3105void TabContents::OnMessageBoxClosed(IPC::Message* reply_msg,
3106 bool success,
3107 const std::wstring& prompt) {
3108 last_javascript_message_dismissal_ = base::TimeTicks::Now();
3109 if (is_showing_before_unload_dialog_ && !success) {
3110 // If a beforeunload dialog is canceled, we need to stop the throbber from
3111 // spinning, since we forced it to start spinning in Navigate.
3112 DidStopLoading();
3113
3114 tab_close_start_time_ = base::TimeTicks();
3115 }
3116 is_showing_before_unload_dialog_ = false;
3117 render_view_host()->JavaScriptMessageBoxClosed(reply_msg, success, prompt);
3118}
3119
3120void TabContents::SetSuppressMessageBoxes(bool suppress_message_boxes) {
3121 set_suppress_javascript_messages(suppress_message_boxes);
3122}
3123
[email protected]41fc0322009-09-04 22:23:403124void TabContents::set_encoding(const std::string& encoding) {
[email protected]aacd7cc2009-09-02 14:51:103125 encoding_ = CharacterEncoding::GetCanonicalEncodingNameByAliasName(encoding);
3126}
[email protected]f45d2a72010-03-08 23:28:353127
3128void TabContents::SetAppIcon(const SkBitmap& app_icon) {
3129 app_icon_ = app_icon;
3130 NotifyNavigationStateChanged(INVALIDATE_TITLE);
3131}
[email protected]ea68c06a2010-04-23 17:25:373132
3133// After a successful *new* login attempt, we take the PasswordFormManager in
3134// provisional_save_manager_ and move it to a SavePasswordInfoBarDelegate while
3135// the user makes up their mind with the "save password" infobar. Note if the
3136// login is one we already know about, the end of the line is
3137// provisional_save_manager_ because we just update it on success and so such
3138// forms never end up in an infobar.
3139class SavePasswordInfoBarDelegate : public ConfirmInfoBarDelegate {
3140 public:
3141 SavePasswordInfoBarDelegate(TabContents* tab_contents,
3142 PasswordFormManager* form_to_save) :
3143 ConfirmInfoBarDelegate(tab_contents),
3144 form_to_save_(form_to_save) {
3145 }
3146
3147 virtual ~SavePasswordInfoBarDelegate() { }
3148
3149 // Overridden from ConfirmInfoBarDelegate:
3150 virtual void InfoBarClosed() {
3151 delete this;
3152 }
3153
3154 virtual std::wstring GetMessageText() const {
3155 return l10n_util::GetString(IDS_PASSWORD_MANAGER_SAVE_PASSWORD_PROMPT);
3156 }
3157
3158 virtual SkBitmap* GetIcon() const {
3159 return ResourceBundle::GetSharedInstance().GetBitmapNamed(
3160 IDR_INFOBAR_SAVE_PASSWORD);
3161 }
3162
3163 virtual int GetButtons() const {
3164 return BUTTON_OK | BUTTON_CANCEL;
3165 }
3166
3167 virtual std::wstring GetButtonLabel(InfoBarButton button) const {
3168 if (button == BUTTON_OK)
3169 return l10n_util::GetString(IDS_PASSWORD_MANAGER_SAVE_BUTTON);
3170 if (button == BUTTON_CANCEL)
3171 return l10n_util::GetString(IDS_PASSWORD_MANAGER_BLACKLIST_BUTTON);
3172 NOTREACHED();
3173 return std::wstring();
3174 }
3175
3176 virtual bool Accept() {
3177 DCHECK(form_to_save_.get());
3178 form_to_save_->Save();
3179 return true;
3180 }
3181
3182 virtual bool Cancel() {
3183 DCHECK(form_to_save_.get());
3184 form_to_save_->PermanentlyBlacklist();
3185 return true;
3186 }
3187
3188 private:
3189 // The PasswordFormManager managing the form we're asking the user about,
3190 // and should update as per her decision.
3191 scoped_ptr<PasswordFormManager> form_to_save_;
3192
3193 DISALLOW_COPY_AND_ASSIGN(SavePasswordInfoBarDelegate);
3194};
3195
3196void TabContents::FillPasswordForm(
3197 const webkit_glue::PasswordFormDomManager::FillData& form_data) {
3198 render_view_host()->FillPasswordForm(form_data);
3199}
3200
3201void TabContents::AddSavePasswordInfoBar(PasswordFormManager* form_to_save) {
3202 AddInfoBar(new SavePasswordInfoBarDelegate(this, form_to_save));
3203}
3204
3205Profile* TabContents::GetProfileForPasswordManager() {
3206 return profile();
3207}
3208
3209bool TabContents::DidLastPageLoadEncounterSSLErrors() {
3210 return controller().ssl_manager()->ProcessedSSLErrorFromRequest();
3211}