| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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 "app/l10n_util.h" | 9 #include "app/l10n_util.h" |
| 10 #include "app/resource_bundle.h" | 10 #include "app/resource_bundle.h" |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 52 #if defined(TOOLKIT_VIEWS) | 52 #if defined(TOOLKIT_VIEWS) |
| 53 #include "views/widget/widget.h" | 53 #include "views/widget/widget.h" |
| 54 #endif | 54 #endif |
| 55 | 55 |
| 56 using WebKit::WebDragOperation; | 56 using WebKit::WebDragOperation; |
| 57 using WebKit::WebDragOperationsMask; | 57 using WebKit::WebDragOperationsMask; |
| 58 | 58 |
| 59 // static | 59 // static |
| 60 bool ExtensionHost::enable_dom_automation_ = false; | 60 bool ExtensionHost::enable_dom_automation_ = false; |
| 61 | 61 |
| 62 static const char* kToolstripTextColorSubstitution = "$TEXT_COLOR$"; | |
| 63 | |
| 64 // Helper class that rate-limits the creation of renderer processes for | 62 // Helper class that rate-limits the creation of renderer processes for |
| 65 // ExtensionHosts, to avoid blocking the UI. | 63 // ExtensionHosts, to avoid blocking the UI. |
| 66 class ExtensionHost::ProcessCreationQueue { | 64 class ExtensionHost::ProcessCreationQueue { |
| 67 public: | 65 public: |
| 68 static ProcessCreationQueue* get() { | 66 static ProcessCreationQueue* get() { |
| 69 return Singleton<ProcessCreationQueue>::get(); | 67 return Singleton<ProcessCreationQueue>::get(); |
| 70 } | 68 } |
| 71 | 69 |
| 72 // Add a host to the queue for RenderView creation. | 70 // Add a host to the queue for RenderView creation. |
| 73 void CreateSoon(ExtensionHost* host) { | 71 void CreateSoon(ExtensionHost* host) { |
| (...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 242 } | 240 } |
| 243 | 241 |
| 244 void ExtensionHost::Observe(NotificationType type, | 242 void ExtensionHost::Observe(NotificationType type, |
| 245 const NotificationSource& source, | 243 const NotificationSource& source, |
| 246 const NotificationDetails& details) { | 244 const NotificationDetails& details) { |
| 247 switch (type.value) { | 245 switch (type.value) { |
| 248 case NotificationType::EXTENSION_BACKGROUND_PAGE_READY: | 246 case NotificationType::EXTENSION_BACKGROUND_PAGE_READY: |
| 249 DCHECK(extension_->GetBackgroundPageReady()); | 247 DCHECK(extension_->GetBackgroundPageReady()); |
| 250 NavigateToURL(url_); | 248 NavigateToURL(url_); |
| 251 break; | 249 break; |
| 252 case NotificationType::BROWSER_THEME_CHANGED: | |
| 253 if (extension_host_type_ == ViewType::EXTENSION_TOOLSTRIP || | |
| 254 extension_host_type_ == ViewType::EXTENSION_MOLE) { | |
| 255 InsertThemedToolstripCSS(); | |
| 256 } | |
| 257 break; | |
| 258 case NotificationType::RENDERER_PROCESS_CREATED: | 250 case NotificationType::RENDERER_PROCESS_CREATED: |
| 259 LOG(INFO) << "Sending EXTENSION_PROCESS_CREATED"; | 251 LOG(INFO) << "Sending EXTENSION_PROCESS_CREATED"; |
| 260 NotificationService::current()->Notify( | 252 NotificationService::current()->Notify( |
| 261 NotificationType::EXTENSION_PROCESS_CREATED, | 253 NotificationType::EXTENSION_PROCESS_CREATED, |
| 262 Source<Profile>(profile_), | 254 Source<Profile>(profile_), |
| 263 Details<ExtensionHost>(this)); | 255 Details<ExtensionHost>(this)); |
| 264 break; | 256 break; |
| 265 case NotificationType::EXTENSION_UNLOADED: | 257 case NotificationType::EXTENSION_UNLOADED: |
| 266 // The extension object will be deleted after this notification has been | 258 // The extension object will be deleted after this notification has been |
| 267 // sent. NULL it out so that dirty pointer issues don't arise in cases | 259 // sent. NULL it out so that dirty pointer issues don't arise in cases |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 318 } | 310 } |
| 319 | 311 |
| 320 // This catches two bogus use cases: | 312 // This catches two bogus use cases: |
| 321 // (1) URLs that look like chrome-extension://somethingbogus or | 313 // (1) URLs that look like chrome-extension://somethingbogus or |
| 322 // chrome-extension://nosuchid/, in other words, no Extension would | 314 // chrome-extension://nosuchid/, in other words, no Extension would |
| 323 // be found. | 315 // be found. |
| 324 // (2) URLs that refer to a different extension than this one. | 316 // (2) URLs that refer to a different extension than this one. |
| 325 // In both cases, we preserve the old URL and reset the EFD to NULL. This | 317 // In both cases, we preserve the old URL and reset the EFD to NULL. This |
| 326 // will leave the host in kind of a bad state with poor UI and errors, but | 318 // will leave the host in kind of a bad state with poor UI and errors, but |
| 327 // it's better than the alternative. | 319 // it's better than the alternative. |
| 328 // TODO(erikkay) Perhaps we should display log errors or display a big 404 | 320 // TODO(erikkay) Perhaps we should display errors in developer mode. |
| 329 // in the toolstrip or something like that. | |
| 330 if (params.url.host() != extension_->id()) { | 321 if (params.url.host() != extension_->id()) { |
| 331 extension_function_dispatcher_.reset(NULL); | 322 extension_function_dispatcher_.reset(NULL); |
| 332 return; | 323 return; |
| 333 } | 324 } |
| 334 | 325 |
| 335 LOG(INFO) << "(DidNavigate) Resetting EFD to " << url_.spec() << " for " | 326 LOG(INFO) << "(DidNavigate) Resetting EFD to " << url_.spec() << " for " |
| 336 << extension_->name(); | 327 << extension_->name(); |
| 337 url_ = params.url; | 328 url_ = params.url; |
| 338 extension_function_dispatcher_.reset( | 329 extension_function_dispatcher_.reset( |
| 339 ExtensionFunctionDispatcher::Create(render_view_host_, this, url_)); | 330 ExtensionFunctionDispatcher::Create(render_view_host_, this, url_)); |
| 340 } | 331 } |
| 341 | 332 |
| 342 void ExtensionHost::InsertInfobarCSS() { | 333 void ExtensionHost::InsertInfobarCSS() { |
| 343 DCHECK(!is_background_page()); | 334 DCHECK(!is_background_page()); |
| 344 | 335 |
| 345 static const base::StringPiece css( | 336 static const base::StringPiece css( |
| 346 ResourceBundle::GetSharedInstance().GetRawDataResource( | 337 ResourceBundle::GetSharedInstance().GetRawDataResource( |
| 347 IDR_EXTENSIONS_INFOBAR_CSS)); | 338 IDR_EXTENSIONS_INFOBAR_CSS)); |
| 348 | 339 |
| 349 render_view_host()->InsertCSSInWebFrame( | 340 render_view_host()->InsertCSSInWebFrame( |
| 350 L"", css.as_string(), "InfobarThemeCSS"); | 341 L"", css.as_string(), "InfobarThemeCSS"); |
| 351 } | 342 } |
| 352 | 343 |
| 353 void ExtensionHost::InsertThemedToolstripCSS() { | |
| 354 DCHECK(!is_background_page()); | |
| 355 | |
| 356 static const base::StringPiece toolstrip_theme_css( | |
| 357 ResourceBundle::GetSharedInstance().GetRawDataResource( | |
| 358 IDR_EXTENSIONS_TOOLSTRIP_THEME_CSS)); | |
| 359 | |
| 360 std::string css = toolstrip_theme_css.as_string(); | |
| 361 ThemeProvider* theme_provider = | |
| 362 render_view_host()->process()->profile()->GetThemeProvider(); | |
| 363 | |
| 364 SkColor text_color = theme_provider ? | |
| 365 theme_provider->GetColor(BrowserThemeProvider::COLOR_BOOKMARK_TEXT) : | |
| 366 SK_ColorBLACK; | |
| 367 | |
| 368 std::string hex_color_string = StringPrintf( | |
| 369 "#%02x%02x%02x", SkColorGetR(text_color), | |
| 370 SkColorGetG(text_color), | |
| 371 SkColorGetB(text_color)); | |
| 372 size_t pos = css.find(kToolstripTextColorSubstitution); | |
| 373 while (pos != std::string::npos) { | |
| 374 css.replace(pos, 12, hex_color_string); | |
| 375 pos = css.find(kToolstripTextColorSubstitution); | |
| 376 } | |
| 377 | |
| 378 // As a toolstrip, inject our toolstrip CSS to make it easier for toolstrips | |
| 379 // to blend in with the chrome UI. | |
| 380 render_view_host()->InsertCSSInWebFrame(L"", css, "ToolstripThemeCSS"); | |
| 381 } | |
| 382 | |
| 383 void ExtensionHost::DisableScrollbarsForSmallWindows( | 344 void ExtensionHost::DisableScrollbarsForSmallWindows( |
| 384 const gfx::Size& size_limit) { | 345 const gfx::Size& size_limit) { |
| 385 render_view_host()->Send(new ViewMsg_DisableScrollbarsForSmallWindows( | 346 render_view_host()->Send(new ViewMsg_DisableScrollbarsForSmallWindows( |
| 386 render_view_host()->routing_id(), size_limit)); | 347 render_view_host()->routing_id(), size_limit)); |
| 387 } | 348 } |
| 388 | 349 |
| 389 void ExtensionHost::DidStopLoading() { | 350 void ExtensionHost::DidStopLoading() { |
| 390 bool notify = !did_stop_loading_; | 351 bool notify = !did_stop_loading_; |
| 391 did_stop_loading_ = true; | 352 did_stop_loading_ = true; |
| 392 if (extension_host_type_ == ViewType::EXTENSION_TOOLSTRIP || | 353 if (extension_host_type_ == ViewType::EXTENSION_POPUP || |
| 393 extension_host_type_ == ViewType::EXTENSION_MOLE || | |
| 394 extension_host_type_ == ViewType::EXTENSION_POPUP || | |
| 395 extension_host_type_ == ViewType::EXTENSION_INFOBAR) { | 354 extension_host_type_ == ViewType::EXTENSION_INFOBAR) { |
| 396 #if defined(TOOLKIT_VIEWS) | 355 #if defined(TOOLKIT_VIEWS) |
| 397 if (view_.get()) | 356 if (view_.get()) |
| 398 view_->DidStopLoading(); | 357 view_->DidStopLoading(); |
| 399 #endif | 358 #endif |
| 400 } | 359 } |
| 401 if (notify) { | 360 if (notify) { |
| 402 LOG(INFO) << "Sending EXTENSION_HOST_DID_STOP_LOADING"; | 361 LOG(INFO) << "Sending EXTENSION_HOST_DID_STOP_LOADING"; |
| 403 NotificationService::current()->Notify( | 362 NotificationService::current()->Notify( |
| 404 NotificationType::EXTENSION_HOST_DID_STOP_LOADING, | 363 NotificationType::EXTENSION_HOST_DID_STOP_LOADING, |
| 405 Source<Profile>(profile_), | 364 Source<Profile>(profile_), |
| 406 Details<ExtensionHost>(this)); | 365 Details<ExtensionHost>(this)); |
| 407 if (extension_host_type_ == ViewType::EXTENSION_BACKGROUND_PAGE) { | 366 if (extension_host_type_ == ViewType::EXTENSION_BACKGROUND_PAGE) { |
| 408 UMA_HISTOGRAM_TIMES("Extensions.BackgroundPageLoadTime", | 367 UMA_HISTOGRAM_TIMES("Extensions.BackgroundPageLoadTime", |
| 409 since_created_.Elapsed()); | 368 since_created_.Elapsed()); |
| 410 } else if (extension_host_type_ == ViewType::EXTENSION_POPUP) { | 369 } else if (extension_host_type_ == ViewType::EXTENSION_POPUP) { |
| 411 UMA_HISTOGRAM_TIMES("Extensions.PopupLoadTime", | 370 UMA_HISTOGRAM_TIMES("Extensions.PopupLoadTime", |
| 412 since_created_.Elapsed()); | 371 since_created_.Elapsed()); |
| 413 } else if (extension_host_type_ == ViewType::EXTENSION_TOOLSTRIP) { | |
| 414 UMA_HISTOGRAM_TIMES("Extensions.ToolstripLoadTime", | |
| 415 since_created_.Elapsed()); | |
| 416 } else if (extension_host_type_ == ViewType::EXTENSION_INFOBAR) { | 372 } else if (extension_host_type_ == ViewType::EXTENSION_INFOBAR) { |
| 417 UMA_HISTOGRAM_TIMES("Extensions.InfobarLoadTime", | 373 UMA_HISTOGRAM_TIMES("Extensions.InfobarLoadTime", |
| 418 since_created_.Elapsed()); | 374 since_created_.Elapsed()); |
| 419 } | 375 } |
| 420 } | 376 } |
| 421 } | 377 } |
| 422 | 378 |
| 423 void ExtensionHost::DocumentAvailableInMainFrame(RenderViewHost* rvh) { | 379 void ExtensionHost::DocumentAvailableInMainFrame(RenderViewHost* rvh) { |
| 424 // If the document has already been marked as available for this host, then | 380 // If the document has already been marked as available for this host, then |
| 425 // bail. No need for the redundant setup. http://crbug.com/31170 | 381 // bail. No need for the redundant setup. http://crbug.com/31170 |
| 426 if (document_element_available_) | 382 if (document_element_available_) |
| 427 return; | 383 return; |
| 428 | 384 |
| 429 document_element_available_ = true; | 385 document_element_available_ = true; |
| 430 if (is_background_page()) { | 386 if (is_background_page()) { |
| 431 extension_->SetBackgroundPageReady(); | 387 extension_->SetBackgroundPageReady(); |
| 432 } else { | 388 } else { |
| 433 switch (extension_host_type_) { | 389 switch (extension_host_type_) { |
| 434 case ViewType::EXTENSION_INFOBAR: | 390 case ViewType::EXTENSION_INFOBAR: |
| 435 InsertInfobarCSS(); | 391 InsertInfobarCSS(); |
| 436 break; | 392 break; |
| 437 case ViewType::EXTENSION_TOOLSTRIP: | |
| 438 case ViewType::EXTENSION_MOLE: | |
| 439 // See also BROWSER_THEME_CHANGED in the Observe function. | |
| 440 InsertThemedToolstripCSS(); | |
| 441 | |
| 442 // Listen for browser changes so we can resend the CSS. | |
| 443 registrar_.Add(this, NotificationType::BROWSER_THEME_CHANGED, | |
| 444 NotificationService::AllSources()); | |
| 445 break; | |
| 446 default: | 393 default: |
| 447 break; // No style sheet for other types, at the moment. | 394 break; // No style sheet for other types, at the moment. |
| 448 } | 395 } |
| 449 } | 396 } |
| 450 } | 397 } |
| 451 | 398 |
| 452 void ExtensionHost::DocumentOnLoadCompletedInMainFrame(RenderViewHost* rvh) { | 399 void ExtensionHost::DocumentOnLoadCompletedInMainFrame(RenderViewHost* rvh) { |
| 453 if (ViewType::EXTENSION_POPUP == GetRenderViewType()) { | 400 if (ViewType::EXTENSION_POPUP == GetRenderViewType()) { |
| 454 NotificationService::current()->Notify( | 401 NotificationService::current()->Notify( |
| 455 NotificationType::EXTENSION_POPUP_VIEW_READY, | 402 NotificationType::EXTENSION_POPUP_VIEW_READY, |
| (...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 695 void ExtensionHost::HandleMouseDown() { | 642 void ExtensionHost::HandleMouseDown() { |
| 696 } | 643 } |
| 697 | 644 |
| 698 void ExtensionHost::HandleMouseLeave() { | 645 void ExtensionHost::HandleMouseLeave() { |
| 699 #if defined(OS_WIN) | 646 #if defined(OS_WIN) |
| 700 if (view_.get()) | 647 if (view_.get()) |
| 701 view_->HandleMouseLeave(); | 648 view_->HandleMouseLeave(); |
| 702 #endif | 649 #endif |
| 703 } | 650 } |
| 704 | 651 |
| 705 void ExtensionHost::SetRenderViewType(ViewType::Type type) { | |
| 706 DCHECK(type == ViewType::EXTENSION_MOLE || | |
| 707 type == ViewType::EXTENSION_TOOLSTRIP || | |
| 708 type == ViewType::EXTENSION_POPUP); | |
| 709 extension_host_type_ = type; | |
| 710 render_view_host()->ViewTypeChanged(extension_host_type_); | |
| 711 } | |
| 712 | |
| 713 ViewType::Type ExtensionHost::GetRenderViewType() const { | 652 ViewType::Type ExtensionHost::GetRenderViewType() const { |
| 714 return extension_host_type_; | 653 return extension_host_type_; |
| 715 } | 654 } |
| 716 | 655 |
| 717 void ExtensionHost::RenderViewCreated(RenderViewHost* render_view_host) { | 656 void ExtensionHost::RenderViewCreated(RenderViewHost* render_view_host) { |
| 718 if (view_.get()) | 657 if (view_.get()) |
| 719 view_->RenderViewCreated(); | 658 view_->RenderViewCreated(); |
| 720 | 659 |
| 721 // TODO(mpcomplete): This is duplicated in DidNavigate, which means that | 660 // TODO(mpcomplete): This is duplicated in DidNavigate, which means that |
| 722 // we'll create 2 EFDs for the first navigation. We should try to find a | 661 // we'll create 2 EFDs for the first navigation. We should try to find a |
| 723 // better way to unify them. | 662 // better way to unify them. |
| 724 // See http://code.google.com/p/chromium/issues/detail?id=18240 | 663 // See http://code.google.com/p/chromium/issues/detail?id=18240 |
| 725 LOG(INFO) << "(RenderViewCreated) Resetting EFD to " << url_.spec() << " for " | 664 LOG(INFO) << "(RenderViewCreated) Resetting EFD to " << url_.spec() << " for " |
| 726 << extension_->name(); | 665 << extension_->name(); |
| 727 extension_function_dispatcher_.reset( | 666 extension_function_dispatcher_.reset( |
| 728 ExtensionFunctionDispatcher::Create(render_view_host, this, url_)); | 667 ExtensionFunctionDispatcher::Create(render_view_host, this, url_)); |
| 729 | 668 |
| 730 if (extension_host_type_ == ViewType::EXTENSION_TOOLSTRIP || | 669 if (extension_host_type_ == ViewType::EXTENSION_POPUP || |
| 731 extension_host_type_ == ViewType::EXTENSION_MOLE || | |
| 732 extension_host_type_ == ViewType::EXTENSION_POPUP || | |
| 733 extension_host_type_ == ViewType::EXTENSION_INFOBAR) { | 670 extension_host_type_ == ViewType::EXTENSION_INFOBAR) { |
| 734 render_view_host->EnablePreferredSizeChangedMode( | 671 render_view_host->EnablePreferredSizeChangedMode( |
| 735 kPreferredSizeWidth | kPreferredSizeHeightThisIsSlow); | 672 kPreferredSizeWidth | kPreferredSizeHeightThisIsSlow); |
| 736 } | 673 } |
| 737 } | 674 } |
| 738 | 675 |
| 739 int ExtensionHost::GetBrowserWindowID() const { | 676 int ExtensionHost::GetBrowserWindowID() const { |
| 740 // Hosts not attached to any browser window have an id of -1. This includes | 677 // Hosts not attached to any browser window have an id of -1. This includes |
| 741 // those mentioned below, and background pages. | 678 // those mentioned below, and background pages. |
| 742 int window_id = extension_misc::kUnknownWindowId; | 679 int window_id = extension_misc::kUnknownWindowId; |
| 743 if (extension_host_type_ == ViewType::EXTENSION_TOOLSTRIP || | 680 if (extension_host_type_ == ViewType::EXTENSION_POPUP || |
| 744 extension_host_type_ == ViewType::EXTENSION_MOLE || | |
| 745 extension_host_type_ == ViewType::EXTENSION_POPUP || | |
| 746 extension_host_type_ == ViewType::EXTENSION_INFOBAR) { | 681 extension_host_type_ == ViewType::EXTENSION_INFOBAR) { |
| 747 // If the host is bound to a browser, then extract its window id. | 682 // If the host is bound to a browser, then extract its window id. |
| 748 // Extensions hosted in ExternalTabContainer objects may not have | 683 // Extensions hosted in ExternalTabContainer objects may not have |
| 749 // an associated browser. | 684 // an associated browser. |
| 750 Browser* browser = GetBrowser(); | 685 Browser* browser = GetBrowser(); |
| 751 if (browser) | 686 if (browser) |
| 752 window_id = ExtensionTabUtil::GetWindowId(browser); | 687 window_id = ExtensionTabUtil::GetWindowId(browser); |
| 753 } else if (extension_host_type_ != ViewType::EXTENSION_BACKGROUND_PAGE) { | 688 } else if (extension_host_type_ != ViewType::EXTENSION_BACKGROUND_PAGE) { |
| 754 NOTREACHED(); | 689 NOTREACHED(); |
| 755 } | 690 } |
| 756 return window_id; | 691 return window_id; |
| 757 } | 692 } |
| OLD | NEW |