| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2012 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/command_line.h" | |
| 8 #include "base/lazy_instance.h" | |
| 9 #include "chrome/browser/autocomplete_history_manager.h" | |
| 10 #include "chrome/browser/autofill/autofill_external_delegate.h" | |
| 11 #include "chrome/browser/autofill/autofill_manager.h" | |
| 12 #include "chrome/browser/automation/automation_tab_helper.h" | |
| 13 #include "chrome/browser/content_settings/tab_specific_content_settings.h" | |
| 14 #include "chrome/browser/extensions/api/web_navigation/web_navigation_api.h" | |
| 15 #include "chrome/browser/extensions/extension_tab_helper.h" | |
| 16 #include "chrome/browser/external_protocol/external_protocol_observer.h" | |
| 17 #include "chrome/browser/favicon/favicon_tab_helper.h" | |
| 18 #include "chrome/browser/history/history_tab_helper.h" | |
| 19 #include "chrome/browser/infobars/infobar_tab_helper.h" | |
| 20 #include "chrome/browser/omnibox_search_hint.h" | |
| 21 #include "chrome/browser/password_manager/password_manager.h" | |
| 22 #include "chrome/browser/password_manager/password_manager_delegate_impl.h" | |
| 23 #include "chrome/browser/plugin_observer.h" | |
| 24 #include "chrome/browser/prerender/prerender_tab_helper.h" | |
| 25 #include "chrome/browser/printing/print_preview_message_handler.h" | |
| 26 #include "chrome/browser/printing/print_view_manager.h" | |
| 27 #include "chrome/browser/safe_browsing/safe_browsing_tab_observer.h" | |
| 28 #include "chrome/browser/sessions/restore_tab_helper.h" | |
| 29 #include "chrome/browser/tab_contents/tab_contents_ssl_helper.h" | |
| 30 #include "chrome/browser/tab_contents/thumbnail_generator.h" | |
| 31 #include "chrome/browser/translate/translate_tab_helper.h" | |
| 32 #include "chrome/browser/ui/alternate_error_tab_observer.h" | |
| 33 #include "chrome/browser/ui/blocked_content/blocked_content_tab_helper.h" | |
| 34 #include "chrome/browser/ui/bookmarks/bookmark_tab_helper.h" | |
| 35 #include "chrome/browser/ui/constrained_window_tab_helper.h" | |
| 36 #include "chrome/browser/ui/find_bar/find_tab_helper.h" | |
| 37 #include "chrome/browser/ui/hung_plugin_tab_helper.h" | |
| 38 #include "chrome/browser/ui/intents/web_intent_picker_controller.h" | |
| 39 #include "chrome/browser/ui/pdf/pdf_tab_observer.h" | |
| 40 #include "chrome/browser/ui/prefs/prefs_tab_helper.h" | |
| 41 #include "chrome/browser/ui/sad_tab_helper.h" | |
| 42 #include "chrome/browser/ui/search_engines/search_engine_tab_helper.h" | |
| 43 #include "chrome/browser/ui/snapshot_tab_helper.h" | |
| 44 #include "chrome/browser/ui/sync/one_click_signin_helper.h" | |
| 45 #include "chrome/browser/ui/sync/tab_contents_wrapper_synced_tab_delegate.h" | |
| 46 #include "chrome/browser/ui/tab_contents/core_tab_helper.h" | |
| 47 #include "chrome/browser/view_type_utils.h" | |
| 48 #include "chrome/common/chrome_notification_types.h" | |
| 49 #include "chrome/common/chrome_switches.h" | |
| 50 #include "chrome/common/thumbnail_support.h" | |
| 51 #include "content/public/browser/notification_service.h" | |
| 52 #include "content/public/browser/web_contents.h" | |
| 53 | |
| 54 #if defined(OS_WIN) | |
| 55 #include "base/win/metro.h" | |
| 56 #endif | |
| 57 | |
| 58 using content::WebContents; | |
| 59 | |
| 60 namespace { | |
| 61 | |
| 62 static base::LazyInstance<base::PropertyAccessor<TabContentsWrapper*> > | |
| 63 g_tab_contents_wrapper_property_accessor = LAZY_INSTANCE_INITIALIZER; | |
| 64 | |
| 65 } // namespace | |
| 66 | |
| 67 //////////////////////////////////////////////////////////////////////////////// | |
| 68 // TabContentsWrapper, public: | |
| 69 | |
| 70 TabContentsWrapper::TabContentsWrapper(WebContents* contents) | |
| 71 : content::WebContentsObserver(contents), | |
| 72 in_destructor_(false), | |
| 73 web_contents_(contents) { | |
| 74 DCHECK(contents); | |
| 75 DCHECK(!GetCurrentWrapperForContents(contents)); | |
| 76 | |
| 77 chrome::SetViewType(contents, chrome::VIEW_TYPE_TAB_CONTENTS); | |
| 78 | |
| 79 // Stash this in the property bag so it can be retrieved without having to | |
| 80 // go to a Browser. | |
| 81 property_accessor()->SetProperty(contents->GetPropertyBag(), this); | |
| 82 | |
| 83 // Create the tab helpers. | |
| 84 autocomplete_history_manager_.reset(new AutocompleteHistoryManager(contents)); | |
| 85 autofill_manager_ = new AutofillManager(this); | |
| 86 if (CommandLine::ForCurrentProcess()->HasSwitch( | |
| 87 switches::kExternalAutofillPopup)) { | |
| 88 autofill_external_delegate_.reset( | |
| 89 AutofillExternalDelegate::Create(this, autofill_manager_.get())); | |
| 90 autofill_manager_->SetExternalDelegate(autofill_external_delegate_.get()); | |
| 91 autocomplete_history_manager_->SetExternalDelegate( | |
| 92 autofill_external_delegate_.get()); | |
| 93 } | |
| 94 #if defined(ENABLE_AUTOMATION) | |
| 95 automation_tab_helper_.reset(new AutomationTabHelper(contents)); | |
| 96 #endif | |
| 97 blocked_content_tab_helper_.reset(new BlockedContentTabHelper(this)); | |
| 98 bookmark_tab_helper_.reset(new BookmarkTabHelper(this)); | |
| 99 constrained_window_tab_helper_.reset(new ConstrainedWindowTabHelper(this)); | |
| 100 core_tab_helper_.reset(new CoreTabHelper(contents)); | |
| 101 extension_tab_helper_.reset(new ExtensionTabHelper(this)); | |
| 102 favicon_tab_helper_.reset(new FaviconTabHelper(contents)); | |
| 103 find_tab_helper_.reset(new FindTabHelper(contents)); | |
| 104 history_tab_helper_.reset(new HistoryTabHelper(contents)); | |
| 105 hung_plugin_tab_helper_.reset(new HungPluginTabHelper(contents)); | |
| 106 infobar_tab_helper_.reset(new InfoBarTabHelper(contents)); | |
| 107 password_manager_delegate_.reset(new PasswordManagerDelegateImpl(this)); | |
| 108 password_manager_.reset( | |
| 109 new PasswordManager(contents, password_manager_delegate_.get())); | |
| 110 prefs_tab_helper_.reset(new PrefsTabHelper(contents)); | |
| 111 prerender_tab_helper_.reset(new prerender::PrerenderTabHelper(this)); | |
| 112 restore_tab_helper_.reset(new RestoreTabHelper(contents)); | |
| 113 search_engine_tab_helper_.reset(new SearchEngineTabHelper(contents)); | |
| 114 snapshot_tab_helper_.reset(new SnapshotTabHelper(contents)); | |
| 115 ssl_helper_.reset(new TabContentsSSLHelper(this)); | |
| 116 synced_tab_delegate_.reset(new TabContentsWrapperSyncedTabDelegate(this)); | |
| 117 content_settings_.reset(new TabSpecificContentSettings(contents)); | |
| 118 translate_tab_helper_.reset(new TranslateTabHelper(contents)); | |
| 119 web_intent_picker_controller_.reset(new WebIntentPickerController(this)); | |
| 120 | |
| 121 #if !defined(OS_ANDROID) | |
| 122 print_view_manager_.reset(new printing::PrintViewManager(this)); | |
| 123 sad_tab_helper_.reset(new SadTabHelper(contents)); | |
| 124 #endif | |
| 125 | |
| 126 // Create the per-tab observers. | |
| 127 alternate_error_page_tab_observer_.reset( | |
| 128 new AlternateErrorPageTabObserver(contents, profile())); | |
| 129 webnavigation_observer_.reset( | |
| 130 new extensions::WebNavigationTabObserver(contents)); | |
| 131 external_protocol_observer_.reset(new ExternalProtocolObserver(contents)); | |
| 132 pdf_tab_observer_.reset(new PDFTabObserver(this)); | |
| 133 safe_browsing_tab_observer_.reset( | |
| 134 new safe_browsing::SafeBrowsingTabObserver(this)); | |
| 135 | |
| 136 #if defined(OS_WIN) | |
| 137 // Metro mode Chrome on Windows does not support plugins. Avoid registering | |
| 138 // the PluginObserver so we don't popup plugin-related infobars. | |
| 139 if (!base::win::GetMetroModule()) | |
| 140 plugin_observer_.reset(new PluginObserver(this)); | |
| 141 #else | |
| 142 plugin_observer_.reset(new PluginObserver(this)); | |
| 143 #endif | |
| 144 | |
| 145 #if !defined(OS_ANDROID) | |
| 146 if (OmniboxSearchHint::IsEnabled(profile())) | |
| 147 omnibox_search_hint_.reset(new OmniboxSearchHint(this)); | |
| 148 print_preview_.reset(new printing::PrintPreviewMessageHandler(contents)); | |
| 149 #endif | |
| 150 | |
| 151 // Start the in-browser thumbnailing if the feature is enabled. | |
| 152 if (ShouldEnableInBrowserThumbnailing()) { | |
| 153 thumbnail_generator_.reset(new ThumbnailGenerator); | |
| 154 thumbnail_generator_->StartThumbnailing(web_contents_.get()); | |
| 155 } | |
| 156 | |
| 157 // If this is not an incognito window, setup to handle one-click login. | |
| 158 // We don't want to check that the profile is already connected at this time | |
| 159 // because the connected state may change while this tab is open. Having a | |
| 160 // one-click signin helper attached does not cause problems if the profile | |
| 161 // happens to be already connected. | |
| 162 #if defined(ENABLE_ONE_CLICK_SIGNIN) | |
| 163 if (OneClickSigninHelper::CanOffer(contents, false)) | |
| 164 one_click_signin_helper_.reset(new OneClickSigninHelper(contents)); | |
| 165 #endif | |
| 166 } | |
| 167 | |
| 168 TabContentsWrapper::~TabContentsWrapper() { | |
| 169 in_destructor_ = true; | |
| 170 | |
| 171 // Need to reset |thumbnail_generator_| here before |web_contents_| is | |
| 172 // deleted because destructing |web_contents_| can end up causing the | |
| 173 // thumbnailer to generate a thumbnail. Since TabContentsWrapper can be | |
| 174 // destructed during shutdown, trying to generate a thumbnail by sending an | |
| 175 // IPC message to the GPU process is not safe. Sending | |
| 176 // chrome::NOTIFICATION_TAB_CONTENTS_DESTROYED can also cause the thumbnailer | |
| 177 // to generate a thumbnail, so this must be placed before sending the | |
| 178 // notification. | |
| 179 thumbnail_generator_.reset(); | |
| 180 | |
| 181 content::NotificationService::current()->Notify( | |
| 182 chrome::NOTIFICATION_TAB_CONTENTS_DESTROYED, | |
| 183 content::Source<TabContentsWrapper>(this), | |
| 184 content::NotificationService::NoDetails()); | |
| 185 | |
| 186 // Need to tear down infobars before the WebContents goes away. | |
| 187 // TODO(avi): Can we get this handled by the tab helper itself? | |
| 188 infobar_tab_helper_.reset(); | |
| 189 } | |
| 190 | |
| 191 base::PropertyAccessor<TabContentsWrapper*>* | |
| 192 TabContentsWrapper::property_accessor() { | |
| 193 return g_tab_contents_wrapper_property_accessor.Pointer(); | |
| 194 } | |
| 195 | |
| 196 TabContentsWrapper* TabContentsWrapper::Clone() { | |
| 197 WebContents* new_contents = web_contents()->Clone(); | |
| 198 TabContentsWrapper* new_wrapper = new TabContentsWrapper(new_contents); | |
| 199 | |
| 200 // TODO(avi): Can we generalize this so that knowledge of the functionings of | |
| 201 // the tab helpers isn't required here? | |
| 202 new_wrapper->extension_tab_helper()->CopyStateFrom( | |
| 203 *extension_tab_helper_.get()); | |
| 204 return new_wrapper; | |
| 205 } | |
| 206 | |
| 207 // static | |
| 208 TabContentsWrapper* TabContentsWrapper::GetCurrentWrapperForContents( | |
| 209 WebContents* contents) { | |
| 210 TabContentsWrapper** wrapper = | |
| 211 property_accessor()->GetProperty(contents->GetPropertyBag()); | |
| 212 | |
| 213 return wrapper ? *wrapper : NULL; | |
| 214 } | |
| 215 | |
| 216 // static | |
| 217 const TabContentsWrapper* TabContentsWrapper::GetCurrentWrapperForContents( | |
| 218 const WebContents* contents) { | |
| 219 TabContentsWrapper* const* wrapper = | |
| 220 property_accessor()->GetProperty(contents->GetPropertyBag()); | |
| 221 | |
| 222 return wrapper ? *wrapper : NULL; | |
| 223 } | |
| 224 | |
| 225 WebContents* TabContentsWrapper::web_contents() const { | |
| 226 return web_contents_.get(); | |
| 227 } | |
| 228 | |
| 229 Profile* TabContentsWrapper::profile() const { | |
| 230 return Profile::FromBrowserContext(web_contents()->GetBrowserContext()); | |
| 231 } | |
| 232 | |
| 233 //////////////////////////////////////////////////////////////////////////////// | |
| 234 // WebContentsObserver overrides | |
| 235 | |
| 236 void TabContentsWrapper::WebContentsDestroyed(WebContents* tab) { | |
| 237 // Destruction of the WebContents should only be done by us from our | |
| 238 // destructor. Otherwise it's very likely we (or one of the helpers we own) | |
| 239 // will attempt to access the WebContents and we'll crash. | |
| 240 DCHECK(in_destructor_); | |
| 241 } | |
| OLD | NEW |