Home | History | Annotate | Download | only in tab_contents
      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