| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/extensions/extension_host.h" | 5 #include "chrome/browser/extensions/extension_host.h" |
| 6 | 6 |
| 7 #include <list> | 7 #include <list> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/memory/singleton.h" | 10 #include "base/memory/singleton.h" |
| 11 #include "base/memory/weak_ptr.h" | 11 #include "base/memory/weak_ptr.h" |
| 12 #include "base/message_loop.h" | 12 #include "base/message_loop.h" |
| 13 #include "base/metrics/histogram.h" | 13 #include "base/metrics/histogram.h" |
| 14 #include "base/string_util.h" | 14 #include "base/string_util.h" |
| 15 #include "base/utf_string_conversions.h" | 15 #include "base/utf_string_conversions.h" |
| 16 #include "chrome/browser/browser_shutdown.h" | 16 #include "chrome/browser/browser_shutdown.h" |
| 17 #include "chrome/browser/extensions/extension_service.h" | 17 #include "chrome/browser/extensions/extension_service.h" |
| 18 #include "chrome/browser/extensions/extension_tab_util.h" | 18 #include "chrome/browser/extensions/extension_tab_util.h" |
| 19 #include "chrome/browser/file_select_helper.h" | |
| 20 #include "chrome/browser/platform_util.h" | |
| 21 #include "chrome/browser/profiles/profile.h" | 19 #include "chrome/browser/profiles/profile.h" |
| 22 #include "chrome/browser/renderer_preferences_util.h" | |
| 23 #include "chrome/browser/tabs/tab_strip_model.h" | |
| 24 #include "chrome/browser/ui/app_modal_dialogs/message_box_handler.h" | 20 #include "chrome/browser/ui/app_modal_dialogs/message_box_handler.h" |
| 25 #include "chrome/browser/ui/browser.h" | 21 #include "chrome/browser/ui/browser.h" |
| 26 #include "chrome/browser/ui/browser_list.h" | 22 #include "chrome/browser/ui/browser_list.h" |
| 27 #include "chrome/browser/ui/browser_window.h" | 23 #include "chrome/browser/ui/browser_window.h" |
| 28 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" | 24 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" |
| 29 #include "chrome/browser/ui/webui/chrome_web_ui_factory.h" | |
| 30 #include "chrome/common/chrome_constants.h" | 25 #include "chrome/common/chrome_constants.h" |
| 31 #include "chrome/common/chrome_notification_types.h" | 26 #include "chrome/common/chrome_notification_types.h" |
| 32 #include "chrome/common/extensions/extension.h" | 27 #include "chrome/common/extensions/extension.h" |
| 33 #include "chrome/common/extensions/extension_constants.h" | 28 #include "chrome/common/extensions/extension_constants.h" |
| 34 #include "chrome/common/extensions/extension_messages.h" | 29 #include "chrome/common/extensions/extension_messages.h" |
| 35 #include "chrome/common/render_messages.h" | 30 #include "chrome/common/render_messages.h" |
| 36 #include "chrome/common/url_constants.h" | 31 #include "chrome/common/url_constants.h" |
| 37 #include "chrome/common/chrome_view_types.h" | 32 #include "chrome/common/chrome_view_types.h" |
| 38 #include "content/browser/browsing_instance.h" | 33 #include "content/browser/browsing_instance.h" |
| 39 #include "content/browser/renderer_host/browser_render_process_host.h" | 34 #include "content/browser/renderer_host/browser_render_process_host.h" |
| 40 #include "content/browser/renderer_host/render_process_host.h" | 35 #include "content/browser/renderer_host/render_process_host.h" |
| 41 #include "content/browser/renderer_host/render_view_host.h" | 36 #include "content/browser/renderer_host/render_view_host.h" |
| 42 #include "content/browser/renderer_host/render_widget_host.h" | |
| 43 #include "content/browser/renderer_host/render_widget_host_view.h" | |
| 44 #include "content/browser/site_instance.h" | |
| 45 #include "content/browser/tab_contents/popup_menu_helper_mac.h" | |
| 46 #include "content/browser/tab_contents/tab_contents.h" | 37 #include "content/browser/tab_contents/tab_contents.h" |
| 47 #include "content/browser/tab_contents/tab_contents_view.h" | 38 #include "content/browser/tab_contents/tab_contents_view.h" |
| 48 #include "content/public/browser/notification_service.h" | 39 #include "content/public/browser/notification_service.h" |
| 49 #include "content/common/view_messages.h" | 40 #include "content/common/view_messages.h" |
| 50 #include "content/public/browser/content_browser_client.h" | 41 #include "content/public/browser/content_browser_client.h" |
| 51 #include "content/public/browser/native_web_keyboard_event.h" | 42 #include "content/public/browser/native_web_keyboard_event.h" |
| 52 #include "content/public/common/bindings_policy.h" | |
| 53 #include "grit/browser_resources.h" | 43 #include "grit/browser_resources.h" |
| 54 #include "grit/chromium_strings.h" | 44 #include "grit/chromium_strings.h" |
| 55 #include "grit/generated_resources.h" | 45 #include "grit/generated_resources.h" |
| 56 #include "ui/base/keycodes/keyboard_codes.h" | 46 #include "ui/base/keycodes/keyboard_codes.h" |
| 57 #include "ui/base/l10n/l10n_util.h" | 47 #include "ui/base/l10n/l10n_util.h" |
| 58 #include "ui/base/resource/resource_bundle.h" | 48 #include "ui/base/resource/resource_bundle.h" |
| 59 #include "webkit/glue/context_menu.h" | |
| 60 | 49 |
| 61 #if defined(TOOLKIT_VIEWS) | 50 #if defined(TOOLKIT_VIEWS) |
| 62 #include "views/widget/widget.h" | 51 #include "views/widget/widget.h" |
| 63 #endif | 52 #endif |
| 64 | 53 |
| 65 using WebKit::WebDragOperation; | 54 using WebKit::WebDragOperation; |
| 66 using WebKit::WebDragOperationsMask; | 55 using WebKit::WebDragOperationsMask; |
| 67 | 56 |
| 68 // static | |
| 69 bool ExtensionHost::enable_dom_automation_ = false; | |
| 70 | |
| 71 // Helper class that rate-limits the creation of renderer processes for | 57 // Helper class that rate-limits the creation of renderer processes for |
| 72 // ExtensionHosts, to avoid blocking the UI. | 58 // ExtensionHosts, to avoid blocking the UI. |
| 73 class ExtensionHost::ProcessCreationQueue { | 59 class ExtensionHost::ProcessCreationQueue { |
| 74 public: | 60 public: |
| 75 static ProcessCreationQueue* GetInstance() { | 61 static ProcessCreationQueue* GetInstance() { |
| 76 return Singleton<ProcessCreationQueue>::get(); | 62 return Singleton<ProcessCreationQueue>::get(); |
| 77 } | 63 } |
| 78 | 64 |
| 79 // Add a host to the queue for RenderView creation. | 65 // Add a host to the queue for RenderView creation. |
| 80 void CreateSoon(ExtensionHost* host) { | 66 void CreateSoon(ExtensionHost* host) { |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 131 ExtensionHost::ExtensionHost(const Extension* extension, | 117 ExtensionHost::ExtensionHost(const Extension* extension, |
| 132 SiteInstance* site_instance, | 118 SiteInstance* site_instance, |
| 133 const GURL& url, | 119 const GURL& url, |
| 134 content::ViewType host_type) | 120 content::ViewType host_type) |
| 135 : extension_(extension), | 121 : extension_(extension), |
| 136 extension_id_(extension->id()), | 122 extension_id_(extension->id()), |
| 137 profile_(Profile::FromBrowserContext( | 123 profile_(Profile::FromBrowserContext( |
| 138 site_instance->browsing_instance()->browser_context())), | 124 site_instance->browsing_instance()->browser_context())), |
| 139 did_stop_loading_(false), | 125 did_stop_loading_(false), |
| 140 document_element_available_(false), | 126 document_element_available_(false), |
| 141 url_(url), | 127 initial_url_(url), |
| 142 ALLOW_THIS_IN_INITIALIZER_LIST( | 128 ALLOW_THIS_IN_INITIALIZER_LIST( |
| 143 extension_function_dispatcher_(profile_, this)), | 129 extension_function_dispatcher_(profile_, this)), |
| 144 extension_host_type_(host_type), | 130 extension_host_type_(host_type), |
| 145 associated_tab_contents_(NULL) { | 131 associated_tab_contents_(NULL) { |
| 146 render_view_host_ = new RenderViewHost(site_instance, this, MSG_ROUTING_NONE, | 132 host_contents_.reset(new TabContents( |
| 147 NULL); | 133 profile_, site_instance, MSG_ROUTING_NONE, NULL, NULL)); |
| 148 if (enable_dom_automation_) | 134 TabContentsObserver::Observe(host_contents_.get()); |
| 149 render_view_host_->AllowBindings(content::BINDINGS_POLICY_DOM_AUTOMATION); | 135 host_contents_->set_delegate(this); |
| 136 host_contents_->set_view_type(host_type); |
| 150 | 137 |
| 151 // Listen for when the render process' handle is available so we can add it | 138 // Listen for when the render process' handle is available so we can add it |
| 152 // to the task manager then. | 139 // to the task manager then. |
| 153 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CREATED, | 140 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CREATED, |
| 154 content::Source<RenderProcessHost>(render_process_host())); | 141 content::NotificationService::AllBrowserContextsAndSources()); |
| 155 // Listen for when an extension is unloaded from the same profile, as it may | 142 // Listen for when an extension is unloaded from the same profile, as it may |
| 156 // be the same extension that this points to. | 143 // be the same extension that this points to. |
| 157 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED, | 144 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED, |
| 158 content::Source<Profile>(profile_)); | 145 content::Source<Profile>(profile_)); |
| 159 } | 146 } |
| 160 | 147 |
| 161 // This "mock" constructor should only be used by unit tests. | 148 // This "mock" constructor should only be used by unit tests. |
| 162 ExtensionHost::ExtensionHost(const Extension* extension, | 149 ExtensionHost::ExtensionHost(const Extension* extension, |
| 163 content::ViewType host_type) | 150 content::ViewType host_type) |
| 164 : extension_(extension), | 151 : extension_(extension), |
| 165 extension_id_(extension->id()), | 152 extension_id_(extension->id()), |
| 166 profile_(NULL), | 153 profile_(NULL), |
| 167 render_view_host_(NULL), | |
| 168 did_stop_loading_(false), | 154 did_stop_loading_(false), |
| 169 document_element_available_(false), | 155 document_element_available_(false), |
| 170 url_(GURL()), | 156 initial_url_(GURL()), |
| 171 ALLOW_THIS_IN_INITIALIZER_LIST( | 157 ALLOW_THIS_IN_INITIALIZER_LIST( |
| 172 extension_function_dispatcher_(profile_, this)), | 158 extension_function_dispatcher_(profile_, this)), |
| 173 extension_host_type_(host_type), | 159 extension_host_type_(host_type), |
| 174 associated_tab_contents_(NULL) { | 160 associated_tab_contents_(NULL) { |
| 175 } | 161 } |
| 176 | 162 |
| 177 ExtensionHost::~ExtensionHost() { | 163 ExtensionHost::~ExtensionHost() { |
| 178 content::NotificationService::current()->Notify( | 164 content::NotificationService::current()->Notify( |
| 179 chrome::NOTIFICATION_EXTENSION_HOST_DESTROYED, | 165 chrome::NOTIFICATION_EXTENSION_HOST_DESTROYED, |
| 180 content::Source<Profile>(profile_), | 166 content::Source<Profile>(profile_), |
| 181 content::Details<ExtensionHost>(this)); | 167 content::Details<ExtensionHost>(this)); |
| 182 ProcessCreationQueue::GetInstance()->Remove(this); | 168 ProcessCreationQueue::GetInstance()->Remove(this); |
| 183 GetJavaScriptDialogCreatorInstance()->ResetJavaScriptState(this); | |
| 184 // render_view_host_ may be NULL in unit tests. | |
| 185 if (render_view_host_) | |
| 186 render_view_host_->Shutdown(); // deletes render_view_host | |
| 187 } | 169 } |
| 188 | 170 |
| 189 void ExtensionHost::CreateView(Browser* browser) { | 171 void ExtensionHost::CreateView(Browser* browser) { |
| 190 #if defined(TOOLKIT_VIEWS) | 172 #if defined(TOOLKIT_VIEWS) |
| 191 view_.reset(new ExtensionView(this, browser)); | 173 view_.reset(new ExtensionView(this, browser)); |
| 192 // We own |view_|, so don't auto delete when it's removed from the view | 174 // We own |view_|, so don't auto delete when it's removed from the view |
| 193 // hierarchy. | 175 // hierarchy. |
| 194 view_->set_parent_owned(false); | 176 view_->set_parent_owned(false); |
| 195 #elif defined(OS_MACOSX) | 177 #elif defined(OS_MACOSX) |
| 196 view_.reset(new ExtensionViewMac(this, browser)); | 178 view_.reset(new ExtensionViewMac(this, browser)); |
| 197 view_->Init(); | 179 view_->Init(); |
| 198 #elif defined(TOOLKIT_USES_GTK) | 180 #elif defined(TOOLKIT_USES_GTK) |
| 199 view_.reset(new ExtensionViewGtk(this, browser)); | 181 view_.reset(new ExtensionViewGtk(this, browser)); |
| 200 view_->Init(); | 182 view_->Init(); |
| 201 #else | 183 #else |
| 202 // TODO(port) | 184 // TODO(port) |
| 203 NOTREACHED(); | 185 NOTREACHED(); |
| 204 #endif | 186 #endif |
| 205 } | 187 } |
| 206 | 188 |
| 207 TabContents* ExtensionHost::GetAssociatedTabContents() const { | 189 TabContents* ExtensionHost::GetAssociatedTabContents() const { |
| 208 return associated_tab_contents_; | 190 return associated_tab_contents_; |
| 209 } | 191 } |
| 210 | 192 |
| 211 RenderProcessHost* ExtensionHost::render_process_host() const { | 193 RenderProcessHost* ExtensionHost::render_process_host() const { |
| 212 return render_view_host_->process(); | 194 return host_contents()->GetRenderProcessHost(); |
| 213 } | 195 } |
| 214 | 196 |
| 215 SiteInstance* ExtensionHost::site_instance() const { | 197 RenderViewHost* ExtensionHost::render_view_host() const { |
| 216 return render_view_host_->site_instance(); | 198 // TODO(mpcomplete): This can be NULL. How do we handle that? |
| 199 return host_contents()->render_view_host(); |
| 217 } | 200 } |
| 218 | 201 |
| 219 bool ExtensionHost::IsRenderViewLive() const { | 202 bool ExtensionHost::IsRenderViewLive() const { |
| 220 return render_view_host_->IsRenderViewLive(); | 203 return render_view_host()->IsRenderViewLive(); |
| 221 } | 204 } |
| 222 | 205 |
| 223 void ExtensionHost::CreateRenderViewSoon(RenderWidgetHostView* host_view) { | 206 void ExtensionHost::CreateRenderViewSoon() { |
| 224 render_view_host_->SetView(host_view); | 207 if (render_process_host()->HasConnection()) { |
| 225 if (render_view_host_->process()->HasConnection()) { | |
| 226 // If the process is already started, go ahead and initialize the RenderView | 208 // If the process is already started, go ahead and initialize the RenderView |
| 227 // synchronously. The process creation is the real meaty part that we want | 209 // synchronously. The process creation is the real meaty part that we want |
| 228 // to defer. | 210 // to defer. |
| 229 CreateRenderViewNow(); | 211 CreateRenderViewNow(); |
| 230 } else { | 212 } else { |
| 231 ProcessCreationQueue::GetInstance()->CreateSoon(this); | 213 ProcessCreationQueue::GetInstance()->CreateSoon(this); |
| 232 } | 214 } |
| 233 } | 215 } |
| 234 | 216 |
| 235 void ExtensionHost::CreateRenderViewNow() { | 217 void ExtensionHost::CreateRenderViewNow() { |
| 236 render_view_host_->CreateRenderView(string16()); | 218 LoadInitialURL(); |
| 237 if (extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_POPUP || | |
| 238 extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_DIALOG || | |
| 239 extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_INFOBAR) { | |
| 240 // If the host is bound to a browser, then extract its window id. | |
| 241 // Extensions hosted in ExternalTabContainer objects may not have | |
| 242 // an associated browser. | |
| 243 const Browser* browser = GetBrowser(); | |
| 244 if (browser && render_view_host_) { | |
| 245 render_view_host_->Send(new ExtensionMsg_UpdateBrowserWindowId( | |
| 246 render_view_host_->routing_id(), | |
| 247 ExtensionTabUtil::GetWindowId(browser))); | |
| 248 } | |
| 249 } | |
| 250 NavigateToURL(url_); | |
| 251 DCHECK(IsRenderViewLive()); | 219 DCHECK(IsRenderViewLive()); |
| 252 if (is_background_page()) | 220 if (is_background_page()) |
| 253 profile_->GetExtensionService()->DidCreateRenderViewForBackgroundPage( | 221 profile_->GetExtensionService()->DidCreateRenderViewForBackgroundPage(this); |
| 254 this); | |
| 255 } | 222 } |
| 256 | 223 |
| 257 const Browser* ExtensionHost::GetBrowser() const { | 224 const Browser* ExtensionHost::GetBrowser() const { |
| 258 return view() ? view()->browser() : NULL; | 225 return view() ? view()->browser() : NULL; |
| 259 } | 226 } |
| 260 | 227 |
| 261 Browser* ExtensionHost::GetBrowser() { | 228 Browser* ExtensionHost::GetBrowser() { |
| 262 return view() ? view()->browser() : NULL; | 229 return view() ? view()->browser() : NULL; |
| 263 } | 230 } |
| 264 | 231 |
| 265 gfx::NativeView ExtensionHost::GetNativeViewOfHost() { | 232 gfx::NativeView ExtensionHost::GetNativeViewOfHost() { |
| 266 return view() ? view()->native_view() : NULL; | 233 return view() ? view()->native_view() : NULL; |
| 267 } | 234 } |
| 268 | 235 |
| 269 void ExtensionHost::NavigateToURL(const GURL& url) { | 236 const GURL& ExtensionHost::GetURL() const { |
| 270 // Prevent explicit navigation to another extension id's pages. | 237 return host_contents()->GetURL(); |
| 271 // This method is only called by some APIs, so we still need to protect | 238 } |
| 272 // DidNavigate below (location = ""). | |
| 273 if (url.SchemeIs(chrome::kExtensionScheme) && url.host() != extension_id()) { | |
| 274 // TODO(erikkay) communicate this back to the caller? | |
| 275 return; | |
| 276 } | |
| 277 | 239 |
| 278 url_ = url; | 240 void ExtensionHost::LoadInitialURL() { |
| 279 | |
| 280 if (!is_background_page() && | 241 if (!is_background_page() && |
| 281 !profile_->GetExtensionService()->IsBackgroundPageReady(extension_)) { | 242 !profile_->GetExtensionService()->IsBackgroundPageReady(extension_)) { |
| 282 // Make sure the background page loads before any others. | 243 // Make sure the background page loads before any others. |
| 283 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_BACKGROUND_PAGE_READY, | 244 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_BACKGROUND_PAGE_READY, |
| 284 content::Source<Extension>(extension_)); | 245 content::Source<Extension>(extension_)); |
| 285 return; | 246 return; |
| 286 } | 247 } |
| 287 | 248 |
| 288 render_view_host_->NavigateToURL(url_); | 249 host_contents_->controller().LoadURL( |
| 250 initial_url_, GURL(), content::PAGE_TRANSITION_LINK, std::string()); |
| 289 } | 251 } |
| 290 | 252 |
| 291 void ExtensionHost::Observe(int type, | 253 void ExtensionHost::Observe(int type, |
| 292 const content::NotificationSource& source, | 254 const content::NotificationSource& source, |
| 293 const content::NotificationDetails& details) { | 255 const content::NotificationDetails& details) { |
| 294 switch (type) { | 256 switch (type) { |
| 295 case chrome::NOTIFICATION_EXTENSION_BACKGROUND_PAGE_READY: | 257 case chrome::NOTIFICATION_EXTENSION_BACKGROUND_PAGE_READY: |
| 296 DCHECK(profile_->GetExtensionService()-> | 258 DCHECK(profile_->GetExtensionService()-> |
| 297 IsBackgroundPageReady(extension_)); | 259 IsBackgroundPageReady(extension_)); |
| 298 NavigateToURL(url_); | 260 LoadInitialURL(); |
| 299 break; | 261 break; |
| 300 case content::NOTIFICATION_RENDERER_PROCESS_CREATED: | 262 case content::NOTIFICATION_RENDERER_PROCESS_CREATED: |
| 301 content::NotificationService::current()->Notify( | 263 if (content::Source<RenderProcessHost>(source).ptr() == |
| 302 chrome::NOTIFICATION_EXTENSION_PROCESS_CREATED, | 264 render_process_host()) { |
| 303 content::Source<Profile>(profile_), | 265 content::NotificationService::current()->Notify( |
| 304 content::Details<ExtensionHost>(this)); | 266 chrome::NOTIFICATION_EXTENSION_PROCESS_CREATED, |
| 267 content::Source<Profile>(profile_), |
| 268 content::Details<ExtensionHost>(this)); |
| 269 } |
| 305 break; | 270 break; |
| 306 case chrome::NOTIFICATION_EXTENSION_UNLOADED: | 271 case chrome::NOTIFICATION_EXTENSION_UNLOADED: |
| 307 // The extension object will be deleted after this notification has been | 272 // The extension object will be deleted after this notification has been |
| 308 // sent. NULL it out so that dirty pointer issues don't arise in cases | 273 // sent. NULL it out so that dirty pointer issues don't arise in cases |
| 309 // when multiple ExtensionHost objects pointing to the same Extension are | 274 // when multiple ExtensionHost objects pointing to the same Extension are |
| 310 // present. | 275 // present. |
| 311 if (extension_ == | 276 if (extension_ == |
| 312 content::Details<UnloadedExtensionInfo>(details)->extension) { | 277 content::Details<UnloadedExtensionInfo>(details)->extension) { |
| 313 extension_ = NULL; | 278 extension_ = NULL; |
| 314 } | 279 } |
| 315 break; | 280 break; |
| 316 default: | 281 default: |
| 317 NOTREACHED() << "Unexpected notification sent."; | 282 NOTREACHED() << "Unexpected notification sent."; |
| 318 break; | 283 break; |
| 319 } | 284 } |
| 320 } | 285 } |
| 321 | 286 |
| 322 void ExtensionHost::UpdatePreferredSize(const gfx::Size& new_size) { | 287 void ExtensionHost::UpdatePreferredSize(TabContents* source, |
| 288 const gfx::Size& pref_size) { |
| 323 if (view_.get()) | 289 if (view_.get()) |
| 324 view_->UpdatePreferredSize(new_size); | 290 view_->UpdatePreferredSize(pref_size); |
| 325 } | 291 } |
| 326 | 292 |
| 327 void ExtensionHost::RenderViewGone(RenderViewHost* render_view_host, | 293 void ExtensionHost::RenderViewGone() { |
| 328 base::TerminationStatus status, | |
| 329 int error_code) { | |
| 330 // During browser shutdown, we may use sudden termination on an extension | 294 // During browser shutdown, we may use sudden termination on an extension |
| 331 // process, so it is expected to lose our connection to the render view. | 295 // process, so it is expected to lose our connection to the render view. |
| 332 // Do nothing. | 296 // Do nothing. |
| 333 if (browser_shutdown::GetShutdownType() != browser_shutdown::NOT_VALID) | 297 if (browser_shutdown::GetShutdownType() != browser_shutdown::NOT_VALID) |
| 334 return; | 298 return; |
| 335 | 299 |
| 336 // In certain cases, multiple ExtensionHost objects may have pointed to | 300 // In certain cases, multiple ExtensionHost objects may have pointed to |
| 337 // the same Extension at some point (one with a background page and a | 301 // the same Extension at some point (one with a background page and a |
| 338 // popup, for example). When the first ExtensionHost goes away, the extension | 302 // popup, for example). When the first ExtensionHost goes away, the extension |
| 339 // is unloaded, and any other host that pointed to that extension will have | 303 // is unloaded, and any other host that pointed to that extension will have |
| 340 // its pointer to it NULLed out so that any attempt to unload a dirty pointer | 304 // its pointer to it NULLed out so that any attempt to unload a dirty pointer |
| 341 // will be averted. | 305 // will be averted. |
| 342 if (!extension_) | 306 if (!extension_) |
| 343 return; | 307 return; |
| 344 | 308 |
| 345 // TODO(aa): This is suspicious. There can be multiple views in an extension, | 309 // TODO(aa): This is suspicious. There can be multiple views in an extension, |
| 346 // and they aren't all going to use ExtensionHost. This should be in someplace | 310 // and they aren't all going to use ExtensionHost. This should be in someplace |
| 347 // more central, like EPM maybe. | 311 // more central, like EPM maybe. |
| 348 DCHECK_EQ(render_view_host_, render_view_host); | |
| 349 content::NotificationService::current()->Notify( | 312 content::NotificationService::current()->Notify( |
| 350 chrome::NOTIFICATION_EXTENSION_PROCESS_TERMINATED, | 313 chrome::NOTIFICATION_EXTENSION_PROCESS_TERMINATED, |
| 351 content::Source<Profile>(profile_), | 314 content::Source<Profile>(profile_), |
| 352 content::Details<ExtensionHost>(this)); | 315 content::Details<ExtensionHost>(this)); |
| 353 } | 316 } |
| 354 | 317 |
| 355 void ExtensionHost::DidNavigate(RenderViewHost* render_view_host, | |
| 356 const ViewHostMsg_FrameNavigate_Params& params) { | |
| 357 // We only care when the outer frame changes. | |
| 358 if (!content::PageTransitionIsMainFrame(params.transition)) | |
| 359 return; | |
| 360 | |
| 361 url_ = params.url; | |
| 362 } | |
| 363 | |
| 364 void ExtensionHost::InsertInfobarCSS() { | 318 void ExtensionHost::InsertInfobarCSS() { |
| 365 DCHECK(!is_background_page()); | 319 DCHECK(!is_background_page()); |
| 366 | 320 |
| 367 static const base::StringPiece css( | 321 static const base::StringPiece css( |
| 368 ResourceBundle::GetSharedInstance().GetRawDataResource( | 322 ResourceBundle::GetSharedInstance().GetRawDataResource( |
| 369 IDR_EXTENSIONS_INFOBAR_CSS)); | 323 IDR_EXTENSIONS_INFOBAR_CSS)); |
| 370 | 324 |
| 371 render_view_host()->InsertCSS(string16(), css.as_string()); | 325 render_view_host()->InsertCSS(string16(), css.as_string()); |
| 372 } | 326 } |
| 373 | 327 |
| (...skipping 27 matching lines...) Expand all Loading... |
| 401 } else if (extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_POPUP) { | 355 } else if (extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_POPUP) { |
| 402 UMA_HISTOGRAM_TIMES("Extensions.PopupLoadTime", | 356 UMA_HISTOGRAM_TIMES("Extensions.PopupLoadTime", |
| 403 since_created_.Elapsed()); | 357 since_created_.Elapsed()); |
| 404 } else if (extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_INFOBAR) { | 358 } else if (extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_INFOBAR) { |
| 405 UMA_HISTOGRAM_TIMES("Extensions.InfobarLoadTime", | 359 UMA_HISTOGRAM_TIMES("Extensions.InfobarLoadTime", |
| 406 since_created_.Elapsed()); | 360 since_created_.Elapsed()); |
| 407 } | 361 } |
| 408 } | 362 } |
| 409 } | 363 } |
| 410 | 364 |
| 411 void ExtensionHost::DocumentAvailableInMainFrame(RenderViewHost* rvh) { | 365 void ExtensionHost::DocumentAvailableInMainFrame() { |
| 412 // If the document has already been marked as available for this host, then | 366 // If the document has already been marked as available for this host, then |
| 413 // bail. No need for the redundant setup. http://crbug.com/31170 | 367 // bail. No need for the redundant setup. http://crbug.com/31170 |
| 414 if (document_element_available_) | 368 if (document_element_available_) |
| 415 return; | 369 return; |
| 416 | 370 |
| 417 document_element_available_ = true; | 371 document_element_available_ = true; |
| 418 if (is_background_page()) { | 372 if (is_background_page()) { |
| 419 profile_->GetExtensionService()->SetBackgroundPageReady(extension_); | 373 profile_->GetExtensionService()->SetBackgroundPageReady(extension_); |
| 420 } else { | 374 } else { |
| 421 switch (extension_host_type_) { | 375 switch (extension_host_type_) { |
| 422 case chrome::VIEW_TYPE_EXTENSION_INFOBAR: | 376 case chrome::VIEW_TYPE_EXTENSION_INFOBAR: |
| 423 InsertInfobarCSS(); | 377 InsertInfobarCSS(); |
| 424 break; | 378 break; |
| 425 default: | 379 default: |
| 426 break; // No style sheet for other types, at the moment. | 380 break; // No style sheet for other types, at the moment. |
| 427 } | 381 } |
| 428 } | 382 } |
| 429 } | 383 } |
| 430 | 384 |
| 431 void ExtensionHost::DocumentOnLoadCompletedInMainFrame(RenderViewHost* rvh, | 385 void ExtensionHost::CloseContents(TabContents* contents) { |
| 432 int32 page_id) { | |
| 433 if (chrome::VIEW_TYPE_EXTENSION_POPUP == GetRenderViewType()) { | |
| 434 content::NotificationService::current()->Notify( | |
| 435 chrome::NOTIFICATION_EXTENSION_POPUP_VIEW_READY, | |
| 436 content::Source<Profile>(profile_), | |
| 437 content::Details<ExtensionHost>(this)); | |
| 438 } | |
| 439 } | |
| 440 | |
| 441 void ExtensionHost::RunJavaScriptMessage(const RenderViewHost* rvh, | |
| 442 const string16& message, | |
| 443 const string16& default_prompt, | |
| 444 const GURL& frame_url, | |
| 445 const int flags, | |
| 446 IPC::Message* reply_msg, | |
| 447 bool* did_suppress_message) { | |
| 448 bool suppress_this_message = false; | |
| 449 | |
| 450 string16 title; | |
| 451 if (extension_->location() == Extension::COMPONENT) | |
| 452 title = l10n_util::GetStringUTF16(IDS_PRODUCT_NAME); | |
| 453 else | |
| 454 title = UTF8ToUTF16(extension_->name()); | |
| 455 | |
| 456 GetJavaScriptDialogCreatorInstance()->RunJavaScriptDialog( | |
| 457 this, | |
| 458 content::JavaScriptDialogCreator::DIALOG_TITLE_PLAIN_STRING, | |
| 459 title, | |
| 460 flags, | |
| 461 message, | |
| 462 default_prompt, | |
| 463 reply_msg, | |
| 464 &suppress_this_message); | |
| 465 | |
| 466 if (suppress_this_message) { | |
| 467 // If we are suppressing messages, just reply as if the user immediately | |
| 468 // pressed "Cancel". | |
| 469 OnDialogClosed(reply_msg, false, string16()); | |
| 470 } | |
| 471 | |
| 472 *did_suppress_message = suppress_this_message; | |
| 473 } | |
| 474 | |
| 475 gfx::NativeWindow ExtensionHost::GetDialogRootWindow() { | |
| 476 // If we have a view, use that. | |
| 477 gfx::NativeView native_view = GetNativeViewOfHost(); | |
| 478 if (native_view) | |
| 479 return platform_util::GetTopLevel(native_view); | |
| 480 | |
| 481 // Otherwise, try the active tab's view. | |
| 482 Browser* browser = extension_function_dispatcher_.GetCurrentBrowser( | |
| 483 render_view_host_, true); | |
| 484 if (browser) { | |
| 485 TabContents* active_tab = browser->GetSelectedTabContents(); | |
| 486 if (active_tab) | |
| 487 return active_tab->view()->GetTopLevelNativeWindow(); | |
| 488 } | |
| 489 | |
| 490 return NULL; | |
| 491 } | |
| 492 | |
| 493 void ExtensionHost::OnDialogClosed(IPC::Message* reply_msg, | |
| 494 bool success, | |
| 495 const string16& user_input) { | |
| 496 render_view_host()->JavaScriptDialogClosed(reply_msg, | |
| 497 success, | |
| 498 user_input); | |
| 499 } | |
| 500 | |
| 501 void ExtensionHost::Close(RenderViewHost* render_view_host) { | |
| 502 if (extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_POPUP || | 386 if (extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_POPUP || |
| 503 extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_DIALOG || | 387 extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_DIALOG || |
| 504 extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_BACKGROUND_PAGE || | 388 extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_BACKGROUND_PAGE || |
| 505 extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_INFOBAR) { | 389 extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_INFOBAR) { |
| 506 content::NotificationService::current()->Notify( | 390 content::NotificationService::current()->Notify( |
| 507 chrome::NOTIFICATION_EXTENSION_HOST_VIEW_SHOULD_CLOSE, | 391 chrome::NOTIFICATION_EXTENSION_HOST_VIEW_SHOULD_CLOSE, |
| 508 content::Source<Profile>(profile_), | 392 content::Source<Profile>(profile_), |
| 509 content::Details<ExtensionHost>(this)); | 393 content::Details<ExtensionHost>(this)); |
| 510 } | 394 } |
| 511 } | 395 } |
| 512 | 396 |
| 513 content::RendererPreferences ExtensionHost::GetRendererPrefs( | |
| 514 content::BrowserContext* browser_context) const { | |
| 515 Profile* profile = Profile::FromBrowserContext(browser_context); | |
| 516 content::RendererPreferences preferences; | |
| 517 | |
| 518 TabContents* associated_contents = GetAssociatedTabContents(); | |
| 519 if (associated_contents) | |
| 520 preferences = | |
| 521 static_cast<RenderViewHostDelegate*>(associated_contents)-> | |
| 522 GetRendererPrefs(profile); | |
| 523 | |
| 524 renderer_preferences_util::UpdateFromSystemSettings(&preferences, profile); | |
| 525 return preferences; | |
| 526 } | |
| 527 | |
| 528 WebPreferences ExtensionHost::GetWebkitPrefs() { | |
| 529 WebPreferences webkit_prefs = | |
| 530 RenderViewHostDelegateHelper::GetWebkitPrefs(render_view_host()); | |
| 531 | |
| 532 // Disable anything that requires the GPU process for background pages. | |
| 533 // See http://crbug.com/64512 and http://crbug.com/64841. | |
| 534 if (extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_BACKGROUND_PAGE) { | |
| 535 webkit_prefs.experimental_webgl_enabled = false; | |
| 536 webkit_prefs.accelerated_compositing_enabled = false; | |
| 537 webkit_prefs.accelerated_2d_canvas_enabled = false; | |
| 538 } | |
| 539 | |
| 540 return webkit_prefs; | |
| 541 } | |
| 542 | |
| 543 RenderViewHostDelegate::View* ExtensionHost::GetViewDelegate() { | |
| 544 return this; | |
| 545 } | |
| 546 | |
| 547 bool ExtensionHost::PreHandleKeyboardEvent(const NativeWebKeyboardEvent& event, | 397 bool ExtensionHost::PreHandleKeyboardEvent(const NativeWebKeyboardEvent& event, |
| 548 bool* is_keyboard_shortcut) { | 398 bool* is_keyboard_shortcut) { |
| 549 if (extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_POPUP && | 399 if (extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_POPUP && |
| 550 event.type == NativeWebKeyboardEvent::RawKeyDown && | 400 event.type == NativeWebKeyboardEvent::RawKeyDown && |
| 551 event.windowsKeyCode == ui::VKEY_ESCAPE) { | 401 event.windowsKeyCode == ui::VKEY_ESCAPE) { |
| 552 DCHECK(is_keyboard_shortcut != NULL); | 402 DCHECK(is_keyboard_shortcut != NULL); |
| 553 *is_keyboard_shortcut = true; | 403 *is_keyboard_shortcut = true; |
| 554 } | 404 } |
| 555 return false; | 405 return false; |
| 556 } | 406 } |
| 557 | 407 |
| 558 void ExtensionHost::HandleKeyboardEvent(const NativeWebKeyboardEvent& event) { | 408 void ExtensionHost::HandleKeyboardEvent(const NativeWebKeyboardEvent& event) { |
| 559 if (extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_POPUP) { | 409 if (extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_POPUP) { |
| 560 if (event.type == NativeWebKeyboardEvent::RawKeyDown && | 410 if (event.type == NativeWebKeyboardEvent::RawKeyDown && |
| 561 event.windowsKeyCode == ui::VKEY_ESCAPE) { | 411 event.windowsKeyCode == ui::VKEY_ESCAPE) { |
| 562 content::NotificationService::current()->Notify( | 412 content::NotificationService::current()->Notify( |
| 563 chrome::NOTIFICATION_EXTENSION_HOST_VIEW_SHOULD_CLOSE, | 413 chrome::NOTIFICATION_EXTENSION_HOST_VIEW_SHOULD_CLOSE, |
| 564 content::Source<Profile>(profile_), | 414 content::Source<Profile>(profile_), |
| 565 content::Details<ExtensionHost>(this)); | 415 content::Details<ExtensionHost>(this)); |
| 566 return; | 416 return; |
| 567 } | 417 } |
| 568 } | 418 } |
| 569 UnhandledKeyboardEvent(event); | 419 UnhandledKeyboardEvent(event); |
| 570 } | 420 } |
| 571 | 421 |
| 572 void ExtensionHost::HandleMouseMove() { | 422 // TODO(mpcomplete): is this necessary? |
| 573 #if defined(OS_WIN) | 423 void ExtensionHost::TabContentsFocused(TabContents* contents) { |
| 574 if (view_.get()) | 424 #if defined(TOOLKIT_VIEWS) && !defined(TOUCH_UI) |
| 575 view_->HandleMouseMove(); | 425 // Request focus so that the FocusManager has a focused view and can perform |
| 426 // normally its key event processing (so that it lets tab key events go to the |
| 427 // renderer). |
| 428 view()->RequestFocus(); |
| 429 #else |
| 430 // TODO(port) |
| 576 #endif | 431 #endif |
| 577 } | 432 } |
| 578 | 433 |
| 579 void ExtensionHost::HandleMouseDown() { | 434 bool ExtensionHost::OnMessageReceived(const IPC::Message& message) { |
| 435 bool handled = true; |
| 436 IPC_BEGIN_MESSAGE_MAP(ExtensionHost, message) |
| 437 IPC_MESSAGE_HANDLER(ExtensionHostMsg_Request, OnRequest) |
| 438 IPC_MESSAGE_UNHANDLED(handled = false) |
| 439 IPC_END_MESSAGE_MAP() |
| 440 return handled; |
| 580 } | 441 } |
| 581 | 442 |
| 582 void ExtensionHost::HandleMouseLeave() { | 443 void ExtensionHost::OnRequest(const ExtensionHostMsg_Request_Params& params) { |
| 583 #if defined(OS_WIN) | 444 extension_function_dispatcher_.Dispatch(params, render_view_host()); |
| 584 if (view_.get()) | |
| 585 view_->HandleMouseLeave(); | |
| 586 #endif | |
| 587 } | 445 } |
| 588 | 446 |
| 589 void ExtensionHost::HandleMouseUp() { | 447 void ExtensionHost::RenderViewCreated(RenderViewHost* render_view_host) { |
| 448 if (view_.get()) |
| 449 view_->RenderViewCreated(); |
| 450 |
| 451 if (extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_POPUP || |
| 452 extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_INFOBAR) { |
| 453 render_view_host->EnablePreferredSizeMode( |
| 454 kPreferredSizeWidth | kPreferredSizeHeightThisIsSlow); |
| 455 } |
| 456 |
| 457 // If the host is bound to a browser, then extract its window id. |
| 458 // Extensions hosted in ExternalTabContainer objects may not have |
| 459 // an associated browser. |
| 460 const Browser* browser = GetBrowser(); |
| 461 if (browser) { |
| 462 render_view_host->Send(new ExtensionMsg_UpdateBrowserWindowId( |
| 463 render_view_host->routing_id(), |
| 464 ExtensionTabUtil::GetWindowId(browser))); |
| 465 } |
| 590 } | 466 } |
| 591 | 467 |
| 592 void ExtensionHost::HandleMouseActivate() { | 468 content::JavaScriptDialogCreator* ExtensionHost::GetJavaScriptDialogCreator() { |
| 469 return GetJavaScriptDialogCreatorInstance(); |
| 593 } | 470 } |
| 594 | 471 |
| 595 void ExtensionHost::RunFileChooser( | 472 void ExtensionHost::AddNewContents(TabContents* source, |
| 596 RenderViewHost* render_view_host, | 473 TabContents* new_contents, |
| 597 const ViewHostMsg_RunFileChooser_Params& params) { | 474 WindowOpenDisposition disposition, |
| 598 // FileSelectHelper adds a reference to itself and only releases it after | 475 const gfx::Rect& initial_pos, |
| 599 // sending the result message. It won't be destroyed when this reference | 476 bool user_gesture) { |
| 600 // goes out of scope. | 477 // TODO(mpcomplete): is all this necessary? Maybe we can just call the |
| 601 scoped_refptr<FileSelectHelper> file_select_helper( | 478 // brower's delegate, and fall back to browser::Navigate if browser is NULL. |
| 602 new FileSelectHelper(profile())); | 479 TabContents* contents = new_contents; |
| 603 file_select_helper->RunFileChooser(render_view_host, | |
| 604 GetAssociatedTabContents(), | |
| 605 params); | |
| 606 } | |
| 607 | |
| 608 void ExtensionHost::CreateNewWindow( | |
| 609 int route_id, | |
| 610 const ViewHostMsg_CreateWindow_Params& params) { | |
| 611 // TODO(aa): Use the browser's profile if the extension is split mode | |
| 612 // incognito. | |
| 613 Profile* profile = Profile::FromBrowserContext( | |
| 614 render_view_host()->process()->browser_context()); | |
| 615 TabContents* new_contents = delegate_view_helper_.CreateNewWindow( | |
| 616 route_id, | |
| 617 profile, | |
| 618 site_instance(), | |
| 619 ChromeWebUIFactory::GetInstance()->GetWebUIType( | |
| 620 render_view_host()->process()->browser_context(), url_), | |
| 621 this, | |
| 622 params.window_container_type, | |
| 623 params.frame_name); | |
| 624 | |
| 625 TabContents* associated_contents = GetAssociatedTabContents(); | |
| 626 if (associated_contents && associated_contents->delegate()) | |
| 627 associated_contents->delegate()->TabContentsCreated(new_contents); | |
| 628 } | |
| 629 | |
| 630 void ExtensionHost::CreateNewWidget(int route_id, | |
| 631 WebKit::WebPopupType popup_type) { | |
| 632 CreateNewWidgetInternal(route_id, popup_type); | |
| 633 } | |
| 634 | |
| 635 void ExtensionHost::CreateNewFullscreenWidget(int route_id) { | |
| 636 NOTREACHED() | |
| 637 << "ExtensionHost does not support showing full screen popups yet."; | |
| 638 } | |
| 639 | |
| 640 RenderWidgetHostView* ExtensionHost::CreateNewWidgetInternal( | |
| 641 int route_id, WebKit::WebPopupType popup_type) { | |
| 642 return delegate_view_helper_.CreateNewWidget(route_id, popup_type, | |
| 643 site_instance()->GetProcess()); | |
| 644 } | |
| 645 | |
| 646 void ExtensionHost::ShowCreatedWindow(int route_id, | |
| 647 WindowOpenDisposition disposition, | |
| 648 const gfx::Rect& initial_pos, | |
| 649 bool user_gesture) { | |
| 650 TabContents* contents = delegate_view_helper_.GetCreatedWindow(route_id); | |
| 651 if (!contents) | 480 if (!contents) |
| 652 return; | 481 return; |
| 653 Profile* profile = Profile::FromBrowserContext(contents->browser_context()); | 482 Profile* profile = Profile::FromBrowserContext(contents->browser_context()); |
| 654 | 483 |
| 655 if (disposition == NEW_POPUP) { | 484 if (disposition == NEW_POPUP) { |
| 656 // Find a browser with a matching profile for creating a popup. | 485 // Find a browser with a matching profile for creating a popup. |
| 657 // (If none is found, NULL argument to NavigateParams is valid.) | 486 // (If none is found, NULL argument to NavigateParams is valid.) |
| 658 Browser* browser = BrowserList::FindTabbedBrowser( | 487 Browser* browser = BrowserList::FindTabbedBrowser( |
| 659 profile, false); // Match incognito exactly. | 488 profile, false); // Match incognito exactly. |
| 660 TabContentsWrapper* wrapper = new TabContentsWrapper(contents); | 489 TabContentsWrapper* wrapper = new TabContentsWrapper(contents); |
| 661 browser::NavigateParams params(browser, wrapper); | 490 browser::NavigateParams params(browser, wrapper); |
| 662 if (!browser) | 491 if (!browser) |
| 663 params.profile = profile; | 492 params.profile = profile; |
| 664 // The extension_app_id parameter ends up as app_name in the Browser | 493 // The extension_app_id parameter ends up as app_name in the Browser |
| 665 // which causes the Browser to return true for is_app(). This affects | 494 // which causes the Browser to return true for is_app(). This affects |
| 666 // among other things, whether the location bar gets displayed. | 495 // among other things, whether the location bar gets displayed. |
| 667 params.extension_app_id = extension_id_; | 496 params.extension_app_id = extension_id_; |
| 668 params.disposition = NEW_POPUP; | 497 params.disposition = NEW_POPUP; |
| 669 params.window_bounds = initial_pos; | 498 params.window_bounds = initial_pos; |
| 670 params.window_action = browser::NavigateParams::SHOW_WINDOW; | 499 params.window_action = browser::NavigateParams::SHOW_WINDOW; |
| 671 params.user_gesture = user_gesture; | 500 params.user_gesture = user_gesture; |
| 672 browser::Navigate(¶ms); | 501 browser::Navigate(¶ms); |
| 673 return; | 502 return; |
| 674 } | 503 } |
| 675 | 504 |
| 676 // If the tab contents isn't a popup, it's a normal tab. We need to find a | |
| 677 // home for it. This is typically a Browser, but it can also be some other | |
| 678 // TabContentsDelegate in the case of ChromeFrame. | |
| 679 | |
| 680 // First, if the creating extension view was associated with a tab contents, | 505 // First, if the creating extension view was associated with a tab contents, |
| 681 // use that tab content's delegate. We must be careful here that the | 506 // use that tab content's delegate. We must be careful here that the |
| 682 // associated tab contents has the same profile as the new tab contents. In | 507 // associated tab contents has the same profile as the new tab contents. In |
| 683 // the case of extensions in 'spanning' incognito mode, they can mismatch. | 508 // the case of extensions in 'spanning' incognito mode, they can mismatch. |
| 684 // We don't want to end up putting a normal tab into an incognito window, or | 509 // We don't want to end up putting a normal tab into an incognito window, or |
| 685 // vice versa. | 510 // vice versa. |
| 686 TabContents* associated_contents = GetAssociatedTabContents(); | 511 TabContents* associated_contents = GetAssociatedTabContents(); |
| 687 if (associated_contents && | 512 if (associated_contents && |
| 688 associated_contents->browser_context() == contents->browser_context()) { | 513 associated_contents->browser_context() == contents->browser_context()) { |
| 689 associated_contents->AddNewContents( | 514 associated_contents->AddNewContents( |
| 690 contents, disposition, initial_pos, user_gesture); | 515 contents, disposition, initial_pos, user_gesture); |
| 691 return; | 516 return; |
| 692 } | 517 } |
| 693 | 518 |
| 694 // If there's no associated tab contents, or it doesn't have a matching | 519 // If there's no associated tab contents, or it doesn't have a matching |
| 695 // profile, try finding an open window. Again, we must make sure to find a | 520 // profile, try finding an open window. Again, we must make sure to find a |
| 696 // window with the correct profile. | 521 // window with the correct profile. |
| 697 Browser* browser = BrowserList::FindTabbedBrowser( | 522 Browser* browser = BrowserList::FindTabbedBrowser( |
| 698 profile, false); // Match incognito exactly. | 523 profile, false); // Match incognito exactly. |
| 699 | 524 |
| 700 // If there's no Browser open with the right profile, create a new one. | 525 // If there's no Browser open with the right profile, create a new one. |
| 701 if (!browser) { | 526 if (!browser) { |
| 702 browser = Browser::Create(profile); | 527 browser = Browser::Create(profile); |
| 703 browser->window()->Show(); | 528 browser->window()->Show(); |
| 704 } | 529 } |
| 705 browser->AddTabContents(contents, disposition, initial_pos, user_gesture); | 530 browser->AddTabContents(contents, disposition, initial_pos, user_gesture); |
| 706 } | 531 } |
| 707 | |
| 708 void ExtensionHost::ShowCreatedWidget(int route_id, | |
| 709 const gfx::Rect& initial_pos) { | |
| 710 ShowCreatedWidgetInternal(delegate_view_helper_.GetCreatedWidget(route_id), | |
| 711 initial_pos); | |
| 712 } | |
| 713 | |
| 714 void ExtensionHost::ShowCreatedFullscreenWidget(int route_id) { | |
| 715 NOTREACHED() | |
| 716 << "ExtensionHost does not support showing full screen popups yet."; | |
| 717 } | |
| 718 | |
| 719 void ExtensionHost::ShowCreatedWidgetInternal( | |
| 720 RenderWidgetHostView* widget_host_view, | |
| 721 const gfx::Rect& initial_pos) { | |
| 722 Browser *browser = GetBrowser(); | |
| 723 DCHECK(browser); | |
| 724 if (!browser) | |
| 725 return; | |
| 726 browser->BrowserRenderWidgetShowing(); | |
| 727 // TODO(erikkay): These two lines could be refactored with TabContentsView. | |
| 728 widget_host_view->InitAsPopup(render_view_host()->view(), initial_pos); | |
| 729 widget_host_view->GetRenderWidgetHost()->Init(); | |
| 730 } | |
| 731 | |
| 732 void ExtensionHost::ShowContextMenu(const ContextMenuParams& params) { | |
| 733 // TODO(erikkay) Show a default context menu. | |
| 734 } | |
| 735 | |
| 736 void ExtensionHost::ShowPopupMenu(const gfx::Rect& bounds, | |
| 737 int item_height, | |
| 738 double item_font_size, | |
| 739 int selected_item, | |
| 740 const std::vector<WebMenuItem>& items, | |
| 741 bool right_aligned) { | |
| 742 #if defined(OS_MACOSX) | |
| 743 PopupMenuHelper popup_menu_helper(render_view_host()); | |
| 744 popup_menu_helper.ShowPopupMenu(bounds, item_height, item_font_size, | |
| 745 selected_item, items, right_aligned); | |
| 746 #else | |
| 747 // Only on Mac are select popup menus external. | |
| 748 NOTREACHED(); | |
| 749 #endif | |
| 750 } | |
| 751 | |
| 752 void ExtensionHost::StartDragging(const WebDropData& drop_data, | |
| 753 WebDragOperationsMask operation_mask, | |
| 754 const SkBitmap& image, | |
| 755 const gfx::Point& image_offset) { | |
| 756 // We're not going to do any drag & drop, but we have to tell the renderer the | |
| 757 // drag & drop ended, othewise the renderer thinks the drag operation is | |
| 758 // underway and mouse events won't work. See bug 34061. | |
| 759 // TODO(twiz) Implement drag & drop support for ExtensionHost instances. | |
| 760 // See feature issue 36288. | |
| 761 render_view_host()->DragSourceSystemDragEnded(); | |
| 762 } | |
| 763 | |
| 764 void ExtensionHost::UpdateDragCursor(WebDragOperation operation) { | |
| 765 } | |
| 766 | |
| 767 void ExtensionHost::GotFocus() { | |
| 768 #if defined(TOOLKIT_VIEWS) && !defined(TOUCH_UI) | |
| 769 // Request focus so that the FocusManager has a focused view and can perform | |
| 770 // normally its key event processing (so that it lets tab key events go to the | |
| 771 // renderer). | |
| 772 view()->RequestFocus(); | |
| 773 #else | |
| 774 // TODO(port) | |
| 775 #endif | |
| 776 } | |
| 777 | |
| 778 void ExtensionHost::TakeFocus(bool reverse) { | |
| 779 } | |
| 780 | |
| 781 content::ViewType ExtensionHost::GetRenderViewType() const { | |
| 782 return extension_host_type_; | |
| 783 } | |
| 784 | |
| 785 bool ExtensionHost::OnMessageReceived(const IPC::Message& message) { | |
| 786 bool handled = true; | |
| 787 IPC_BEGIN_MESSAGE_MAP(ExtensionHost, message) | |
| 788 IPC_MESSAGE_HANDLER(ExtensionHostMsg_Request, OnRequest) | |
| 789 IPC_MESSAGE_UNHANDLED(handled = false) | |
| 790 IPC_END_MESSAGE_MAP() | |
| 791 return handled; | |
| 792 } | |
| 793 | |
| 794 void ExtensionHost::OnRequest(const ExtensionHostMsg_Request_Params& params) { | |
| 795 extension_function_dispatcher_.Dispatch(params, render_view_host_); | |
| 796 } | |
| 797 | |
| 798 const GURL& ExtensionHost::GetURL() const { | |
| 799 return url_; | |
| 800 } | |
| 801 | |
| 802 void ExtensionHost::RenderViewCreated(RenderViewHost* render_view_host) { | |
| 803 if (view_.get()) | |
| 804 view_->RenderViewCreated(); | |
| 805 | |
| 806 if (extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_POPUP || | |
| 807 extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_INFOBAR) { | |
| 808 render_view_host->EnablePreferredSizeMode( | |
| 809 kPreferredSizeWidth | kPreferredSizeHeightThisIsSlow); | |
| 810 } | |
| 811 } | |
| OLD | NEW |