1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" 6 7 #include "base/lazy_instance.h" 8 #include "chrome/browser/autocomplete_history_manager.h" 9 #include "chrome/browser/autofill/autofill_manager.h" 10 #include "chrome/browser/automation/automation_tab_helper.h" 11 #include "chrome/browser/bookmarks/bookmark_model.h" 12 #include "chrome/browser/custom_handlers/protocol_handler_registry.h" 13 #include "chrome/browser/custom_handlers/register_protocol_handler_infobar_delegate.h" 14 #include "chrome/browser/extensions/extension_tab_helper.h" 15 #include "chrome/browser/extensions/extension_webnavigation_api.h" 16 #include "chrome/browser/file_select_helper.h" 17 #include "chrome/browser/history/history.h" 18 #include "chrome/browser/history/top_sites.h" 19 #include "chrome/browser/password_manager/password_manager.h" 20 #include "chrome/browser/password_manager_delegate_impl.h" 21 #include "chrome/browser/prefs/pref_service.h" 22 #include "chrome/browser/prerender/prerender_observer.h" 23 #include "chrome/browser/printing/print_preview_message_handler.h" 24 #include "chrome/browser/profiles/profile.h" 25 #include "chrome/browser/tab_contents/simple_alert_infobar_delegate.h" 26 #include "chrome/browser/translate/translate_tab_helper.h" 27 #include "chrome/browser/ui/download/download_tab_helper.h" 28 #include "chrome/browser/ui/find_bar/find_tab_helper.h" 29 #include "chrome/browser/ui/search_engines/search_engine_tab_helper.h" 30 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper_delegate.h" 31 #include "chrome/common/pref_names.h" 32 #include "chrome/common/render_messages.h" 33 #include "content/browser/tab_contents/tab_contents.h" 34 #include "content/common/notification_service.h" 35 #include "content/common/view_messages.h" 36 #include "grit/generated_resources.h" 37 #include "grit/locale_settings.h" 38 #include "grit/platform_locale_settings.h" 39 #include "ui/base/l10n/l10n_util.h" 40 #include "webkit/glue/webpreferences.h" 41 42 static base::LazyInstance<PropertyAccessor<TabContentsWrapper*> > 43 g_tab_contents_wrapper_property_accessor(base::LINKER_INITIALIZED); 44 45 //////////////////////////////////////////////////////////////////////////////// 46 // TabContentsWrapper, public: 47 48 TabContentsWrapper::TabContentsWrapper(TabContents* contents) 49 : TabContentsObserver(contents), 50 delegate_(NULL), 51 is_starred_(false), 52 tab_contents_(contents) { 53 DCHECK(contents); 54 // Stash this in the property bag so it can be retrieved without having to 55 // go to a Browser. 56 property_accessor()->SetProperty(contents->property_bag(), this); 57 58 // Create the tab helpers. 59 autocomplete_history_manager_.reset(new AutocompleteHistoryManager(contents)); 60 autofill_manager_.reset(new AutofillManager(contents)); 61 automation_tab_helper_.reset(new AutomationTabHelper(contents)); 62 download_tab_helper_.reset(new DownloadTabHelper(contents)); 63 extension_tab_helper_.reset(new ExtensionTabHelper(this)); 64 find_tab_helper_.reset(new FindTabHelper(contents)); 65 password_manager_delegate_.reset(new PasswordManagerDelegateImpl(contents)); 66 password_manager_.reset( 67 new PasswordManager(contents, password_manager_delegate_.get())); 68 search_engine_tab_helper_.reset(new SearchEngineTabHelper(contents)); 69 translate_tab_helper_.reset(new TranslateTabHelper(contents)); 70 print_view_manager_.reset(new printing::PrintViewManager(contents)); 71 72 // Register for notifications about URL starredness changing on any profile. 73 registrar_.Add(this, NotificationType::URLS_STARRED, 74 NotificationService::AllSources()); 75 registrar_.Add(this, NotificationType::BOOKMARK_MODEL_LOADED, 76 NotificationService::AllSources()); 77 78 // Create the per-tab observers. 79 file_select_observer_.reset(new FileSelectObserver(contents)); 80 prerender_observer_.reset(new prerender::PrerenderObserver(contents)); 81 print_preview_.reset(new printing::PrintPreviewMessageHandler(contents)); 82 webnavigation_observer_.reset( 83 new ExtensionWebNavigationTabObserver(contents)); 84 } 85 86 TabContentsWrapper::~TabContentsWrapper() { 87 // We don't want any notifications while we're running our destructor. 88 registrar_.RemoveAll(); 89 } 90 91 PropertyAccessor<TabContentsWrapper*>* TabContentsWrapper::property_accessor() { 92 return g_tab_contents_wrapper_property_accessor.Pointer(); 93 } 94 95 void TabContentsWrapper::RegisterUserPrefs(PrefService* prefs) { 96 prefs->RegisterBooleanPref(prefs::kAlternateErrorPagesEnabled, true); 97 98 WebPreferences pref_defaults; 99 prefs->RegisterBooleanPref(prefs::kWebKitJavascriptEnabled, 100 pref_defaults.javascript_enabled); 101 prefs->RegisterBooleanPref(prefs::kWebKitWebSecurityEnabled, 102 pref_defaults.web_security_enabled); 103 prefs->RegisterBooleanPref( 104 prefs::kWebKitJavascriptCanOpenWindowsAutomatically, true); 105 prefs->RegisterBooleanPref(prefs::kWebKitLoadsImagesAutomatically, 106 pref_defaults.loads_images_automatically); 107 prefs->RegisterBooleanPref(prefs::kWebKitPluginsEnabled, 108 pref_defaults.plugins_enabled); 109 prefs->RegisterBooleanPref(prefs::kWebKitDomPasteEnabled, 110 pref_defaults.dom_paste_enabled); 111 prefs->RegisterBooleanPref(prefs::kWebKitShrinksStandaloneImagesToFit, 112 pref_defaults.shrinks_standalone_images_to_fit); 113 prefs->RegisterDictionaryPref(prefs::kWebKitInspectorSettings); 114 prefs->RegisterBooleanPref(prefs::kWebKitTextAreasAreResizable, 115 pref_defaults.text_areas_are_resizable); 116 prefs->RegisterBooleanPref(prefs::kWebKitJavaEnabled, 117 pref_defaults.java_enabled); 118 prefs->RegisterBooleanPref(prefs::kWebkitTabsToLinks, 119 pref_defaults.tabs_to_links); 120 121 prefs->RegisterLocalizedStringPref(prefs::kAcceptLanguages, 122 IDS_ACCEPT_LANGUAGES); 123 prefs->RegisterLocalizedStringPref(prefs::kDefaultCharset, 124 IDS_DEFAULT_ENCODING); 125 prefs->RegisterLocalizedStringPref(prefs::kWebKitStandardFontFamily, 126 IDS_STANDARD_FONT_FAMILY); 127 prefs->RegisterLocalizedStringPref(prefs::kWebKitFixedFontFamily, 128 IDS_FIXED_FONT_FAMILY); 129 prefs->RegisterLocalizedStringPref(prefs::kWebKitSerifFontFamily, 130 IDS_SERIF_FONT_FAMILY); 131 prefs->RegisterLocalizedStringPref(prefs::kWebKitSansSerifFontFamily, 132 IDS_SANS_SERIF_FONT_FAMILY); 133 prefs->RegisterLocalizedStringPref(prefs::kWebKitCursiveFontFamily, 134 IDS_CURSIVE_FONT_FAMILY); 135 prefs->RegisterLocalizedStringPref(prefs::kWebKitFantasyFontFamily, 136 IDS_FANTASY_FONT_FAMILY); 137 prefs->RegisterLocalizedIntegerPref(prefs::kWebKitDefaultFontSize, 138 IDS_DEFAULT_FONT_SIZE); 139 prefs->RegisterLocalizedIntegerPref(prefs::kWebKitDefaultFixedFontSize, 140 IDS_DEFAULT_FIXED_FONT_SIZE); 141 prefs->RegisterLocalizedIntegerPref(prefs::kWebKitMinimumFontSize, 142 IDS_MINIMUM_FONT_SIZE); 143 prefs->RegisterLocalizedIntegerPref(prefs::kWebKitMinimumLogicalFontSize, 144 IDS_MINIMUM_LOGICAL_FONT_SIZE); 145 prefs->RegisterLocalizedBooleanPref(prefs::kWebKitUsesUniversalDetector, 146 IDS_USES_UNIVERSAL_DETECTOR); 147 prefs->RegisterLocalizedStringPref(prefs::kStaticEncodings, 148 IDS_STATIC_ENCODING_LIST); 149 prefs->RegisterStringPref(prefs::kRecentlySelectedEncoding, ""); 150 } 151 152 string16 TabContentsWrapper::GetDefaultTitle() { 153 return l10n_util::GetStringUTF16(IDS_DEFAULT_TAB_TITLE); 154 } 155 156 string16 TabContentsWrapper::GetStatusText() const { 157 if (!tab_contents()->is_loading() || 158 tab_contents()->load_state() == net::LOAD_STATE_IDLE) { 159 return string16(); 160 } 161 162 switch (tab_contents()->load_state()) { 163 case net::LOAD_STATE_WAITING_FOR_CACHE: 164 return l10n_util::GetStringUTF16(IDS_LOAD_STATE_WAITING_FOR_CACHE); 165 case net::LOAD_STATE_ESTABLISHING_PROXY_TUNNEL: 166 return 167 l10n_util::GetStringUTF16(IDS_LOAD_STATE_ESTABLISHING_PROXY_TUNNEL); 168 case net::LOAD_STATE_RESOLVING_PROXY_FOR_URL: 169 return l10n_util::GetStringUTF16(IDS_LOAD_STATE_RESOLVING_PROXY_FOR_URL); 170 case net::LOAD_STATE_RESOLVING_HOST: 171 return l10n_util::GetStringUTF16(IDS_LOAD_STATE_RESOLVING_HOST); 172 case net::LOAD_STATE_CONNECTING: 173 return l10n_util::GetStringUTF16(IDS_LOAD_STATE_CONNECTING); 174 case net::LOAD_STATE_SSL_HANDSHAKE: 175 return l10n_util::GetStringUTF16(IDS_LOAD_STATE_SSL_HANDSHAKE); 176 case net::LOAD_STATE_SENDING_REQUEST: 177 if (tab_contents()->upload_size()) 178 return l10n_util::GetStringFUTF16Int( 179 IDS_LOAD_STATE_SENDING_REQUEST_WITH_PROGRESS, 180 static_cast<int>((100 * tab_contents()->upload_position()) / 181 tab_contents()->upload_size())); 182 else 183 return l10n_util::GetStringUTF16(IDS_LOAD_STATE_SENDING_REQUEST); 184 case net::LOAD_STATE_WAITING_FOR_RESPONSE: 185 return l10n_util::GetStringFUTF16(IDS_LOAD_STATE_WAITING_FOR_RESPONSE, 186 tab_contents()->load_state_host()); 187 // Ignore net::LOAD_STATE_READING_RESPONSE and net::LOAD_STATE_IDLE 188 case net::LOAD_STATE_IDLE: 189 case net::LOAD_STATE_READING_RESPONSE: 190 break; 191 } 192 193 return string16(); 194 } 195 196 TabContentsWrapper* TabContentsWrapper::Clone() { 197 TabContents* new_contents = tab_contents()->Clone(); 198 TabContentsWrapper* new_wrapper = new TabContentsWrapper(new_contents); 199 200 new_wrapper->extension_tab_helper()->CopyStateFrom( 201 *extension_tab_helper_.get()); 202 return new_wrapper; 203 } 204 205 TabContentsWrapper* TabContentsWrapper::GetCurrentWrapperForContents( 206 TabContents* contents) { 207 TabContentsWrapper** wrapper = 208 property_accessor()->GetProperty(contents->property_bag()); 209 210 return wrapper ? *wrapper : NULL; 211 } 212 213 //////////////////////////////////////////////////////////////////////////////// 214 // TabContentsWrapper, TabContentsObserver implementation: 215 216 void TabContentsWrapper::DidNavigateMainFramePostCommit( 217 const NavigationController::LoadCommittedDetails& /*details*/, 218 const ViewHostMsg_FrameNavigate_Params& /*params*/) { 219 UpdateStarredStateForCurrentURL(); 220 } 221 222 bool TabContentsWrapper::OnMessageReceived(const IPC::Message& message) { 223 bool handled = true; 224 IPC_BEGIN_MESSAGE_MAP(TabContentsWrapper, message) 225 IPC_MESSAGE_HANDLER(ViewHostMsg_PageContents, OnPageContents) 226 IPC_MESSAGE_HANDLER(ViewHostMsg_JSOutOfMemory, OnJSOutOfMemory) 227 IPC_MESSAGE_HANDLER(ViewHostMsg_RegisterProtocolHandler, 228 OnRegisterProtocolHandler) 229 IPC_MESSAGE_HANDLER(ViewHostMsg_Thumbnail, OnMsgThumbnail) 230 IPC_MESSAGE_UNHANDLED(handled = false) 231 IPC_END_MESSAGE_MAP() 232 return handled; 233 } 234 235 //////////////////////////////////////////////////////////////////////////////// 236 // TabContentsWrapper, NotificationObserver implementation: 237 238 void TabContentsWrapper::Observe(NotificationType type, 239 const NotificationSource& source, 240 const NotificationDetails& details) { 241 switch (type.value) { 242 case NotificationType::BOOKMARK_MODEL_LOADED: 243 // BookmarkModel finished loading, fall through to update starred state. 244 case NotificationType::URLS_STARRED: { 245 // Somewhere, a URL has been starred. 246 // Ignore notifications for profiles other than our current one. 247 Profile* source_profile = Source<Profile>(source).ptr(); 248 if (!source_profile || !source_profile->IsSameProfile(profile())) 249 return; 250 251 UpdateStarredStateForCurrentURL(); 252 break; 253 } 254 255 default: 256 NOTREACHED(); 257 } 258 } 259 260 //////////////////////////////////////////////////////////////////////////////// 261 // Internal helpers 262 263 void TabContentsWrapper::OnPageContents(const GURL& url, 264 int32 page_id, 265 const string16& contents) { 266 // Don't index any https pages. People generally don't want their bank 267 // accounts, etc. indexed on their computer, especially since some of these 268 // things are not marked cachable. 269 // TODO(brettw) we may want to consider more elaborate heuristics such as 270 // the cachability of the page. We may also want to consider subframes (this 271 // test will still index subframes if the subframe is SSL). 272 // TODO(zelidrag) bug chromium-os:2808 - figure out if we want to reenable 273 // content indexing for chromeos in some future releases. 274 #if !defined(OS_CHROMEOS) 275 if (!url.SchemeIsSecure()) { 276 Profile* p = profile(); 277 if (p && !p->IsOffTheRecord()) { 278 HistoryService* hs = p->GetHistoryService(Profile::IMPLICIT_ACCESS); 279 if (hs) 280 hs->SetPageContents(url, contents); 281 } 282 } 283 #endif 284 } 285 286 void TabContentsWrapper::OnJSOutOfMemory() { 287 tab_contents()->AddInfoBar(new SimpleAlertInfoBarDelegate(tab_contents(), 288 NULL, l10n_util::GetStringUTF16(IDS_JS_OUT_OF_MEMORY_PROMPT), true)); 289 } 290 291 void TabContentsWrapper::OnRegisterProtocolHandler(const std::string& protocol, 292 const GURL& url, 293 const string16& title) { 294 ProtocolHandlerRegistry* registry = profile()->GetProtocolHandlerRegistry(); 295 ProtocolHandler* handler = 296 ProtocolHandler::CreateProtocolHandler(protocol, url, title); 297 if ((handler != NULL) && 298 registry->CanSchemeBeOverridden(handler->protocol())) { 299 tab_contents()->AddInfoBar(registry->IsAlreadyRegistered(handler) ? 300 static_cast<InfoBarDelegate*>(new SimpleAlertInfoBarDelegate( 301 tab_contents(), NULL, l10n_util::GetStringFUTF16( 302 IDS_REGISTER_PROTOCOL_HANDLER_ALREADY_REGISTERED, 303 handler->title(), UTF8ToUTF16(handler->protocol())), true)) : 304 new RegisterProtocolHandlerInfoBarDelegate(tab_contents(), registry, 305 handler)); 306 } 307 } 308 309 void TabContentsWrapper::OnMsgThumbnail(const GURL& url, 310 const ThumbnailScore& score, 311 const SkBitmap& bitmap) { 312 if (profile()->IsOffTheRecord()) 313 return; 314 315 // Tell History about this thumbnail 316 history::TopSites* ts = profile()->GetTopSites(); 317 if (ts) 318 ts->SetPageThumbnail(url, bitmap, score); 319 } 320 321 void TabContentsWrapper::UpdateStarredStateForCurrentURL() { 322 BookmarkModel* model = tab_contents()->profile()->GetBookmarkModel(); 323 const bool old_state = is_starred_; 324 is_starred_ = (model && model->IsBookmarked(tab_contents()->GetURL())); 325 326 if (is_starred_ != old_state && delegate()) 327 delegate()->URLStarredChanged(this, is_starred_); 328 } 329