| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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/event_router.h" | 17 #include "chrome/browser/extensions/event_router.h" |
| 18 #include "chrome/browser/extensions/extension_process_manager.h" | 18 #include "chrome/browser/extensions/extension_process_manager.h" |
| 19 #include "chrome/browser/extensions/extension_service.h" | 19 #include "chrome/browser/extensions/extension_service.h" |
| 20 #include "chrome/browser/extensions/extension_system.h" | 20 #include "chrome/browser/extensions/extension_system.h" |
| 21 #include "chrome/browser/extensions/extension_tab_util.h" | 21 #include "chrome/browser/extensions/extension_tab_util.h" |
| 22 #include "chrome/browser/extensions/extension_view.h" |
| 22 #include "chrome/browser/extensions/window_controller.h" | 23 #include "chrome/browser/extensions/window_controller.h" |
| 23 #include "chrome/browser/file_select_helper.h" | 24 #include "chrome/browser/file_select_helper.h" |
| 24 #include "chrome/browser/profiles/profile.h" | 25 #include "chrome/browser/profiles/profile.h" |
| 25 #include "chrome/browser/ui/app_modal_dialogs/javascript_dialog_creator.h" | 26 #include "chrome/browser/ui/app_modal_dialogs/javascript_dialog_creator.h" |
| 26 #include "chrome/browser/ui/browser.h" | 27 #include "chrome/browser/ui/browser.h" |
| 27 #include "chrome/browser/ui/browser_finder.h" | 28 #include "chrome/browser/ui/browser_finder.h" |
| 28 #include "chrome/browser/ui/browser_list.h" | 29 #include "chrome/browser/ui/browser_list.h" |
| 29 #include "chrome/browser/ui/browser_window.h" | 30 #include "chrome/browser/ui/browser_window.h" |
| 30 #include "chrome/browser/ui/prefs/prefs_tab_helper.h" | 31 #include "chrome/browser/ui/prefs/prefs_tab_helper.h" |
| 31 #include "chrome/browser/ui/tab_contents/tab_contents.h" | 32 #include "chrome/browser/ui/tab_contents/tab_contents.h" |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 162 UMA_HISTOGRAM_LONG_TIMES("Extensions.EventPageActiveTime", | 163 UMA_HISTOGRAM_LONG_TIMES("Extensions.EventPageActiveTime", |
| 163 since_created_.Elapsed()); | 164 since_created_.Elapsed()); |
| 164 } | 165 } |
| 165 content::NotificationService::current()->Notify( | 166 content::NotificationService::current()->Notify( |
| 166 chrome::NOTIFICATION_EXTENSION_HOST_DESTROYED, | 167 chrome::NOTIFICATION_EXTENSION_HOST_DESTROYED, |
| 167 content::Source<Profile>(profile_), | 168 content::Source<Profile>(profile_), |
| 168 content::Details<ExtensionHost>(this)); | 169 content::Details<ExtensionHost>(this)); |
| 169 ProcessCreationQueue::GetInstance()->Remove(this); | 170 ProcessCreationQueue::GetInstance()->Remove(this); |
| 170 } | 171 } |
| 171 | 172 |
| 173 void ExtensionHost::SetExtensionView(ExtensionView* view) { |
| 174 extension_view_.reset(view); |
| 175 } |
| 176 |
| 177 const ExtensionView* ExtensionHost::GetExtensionView() const { |
| 178 return extension_view_.get(); |
| 179 } |
| 180 |
| 181 ExtensionView* ExtensionHost::GetExtensionView() { |
| 182 return extension_view_.get(); |
| 183 } |
| 184 |
| 172 void ExtensionHost::CreateView(Browser* browser) { | 185 void ExtensionHost::CreateView(Browser* browser) { |
| 173 #if defined(TOOLKIT_VIEWS) | 186 extension_view_.reset(ExtensionView::Create(this, browser)); |
| 174 view_.reset(new ExtensionViewViews(this, browser)); | |
| 175 // We own |view_|, so don't auto delete when it's removed from the view | |
| 176 // hierarchy. | |
| 177 view_->set_owned_by_client(); | |
| 178 #elif defined(OS_MACOSX) | |
| 179 view_.reset(new ExtensionViewMac(this, browser)); | |
| 180 view_->Init(); | |
| 181 #elif defined(TOOLKIT_GTK) | |
| 182 view_.reset(new ExtensionViewGtk(this, browser)); | |
| 183 view_->Init(); | |
| 184 #else | |
| 185 // TODO(port) | |
| 186 NOTREACHED(); | |
| 187 #endif | |
| 188 } | 187 } |
| 189 | 188 |
| 190 WebContents* ExtensionHost::GetAssociatedWebContents() const { | 189 WebContents* ExtensionHost::GetAssociatedWebContents() const { |
| 191 return associated_web_contents_; | 190 return associated_web_contents_; |
| 192 } | 191 } |
| 193 | 192 |
| 194 void ExtensionHost::SetAssociatedWebContents( | 193 void ExtensionHost::SetAssociatedWebContents( |
| 195 content::WebContents* web_contents) { | 194 content::WebContents* web_contents) { |
| 196 associated_web_contents_ = web_contents; | 195 associated_web_contents_ = web_contents; |
| 197 if (web_contents) { | 196 if (web_contents) { |
| (...skipping 29 matching lines...) Expand all Loading... |
| 227 void ExtensionHost::CreateRenderViewNow() { | 226 void ExtensionHost::CreateRenderViewNow() { |
| 228 LoadInitialURL(); | 227 LoadInitialURL(); |
| 229 if (is_background_page()) { | 228 if (is_background_page()) { |
| 230 DCHECK(IsRenderViewLive()); | 229 DCHECK(IsRenderViewLive()); |
| 231 profile_->GetExtensionService()->DidCreateRenderViewForBackgroundPage(this); | 230 profile_->GetExtensionService()->DidCreateRenderViewForBackgroundPage(this); |
| 232 } | 231 } |
| 233 } | 232 } |
| 234 | 233 |
| 235 extensions::WindowController* | 234 extensions::WindowController* |
| 236 ExtensionHost::GetExtensionWindowController() const { | 235 ExtensionHost::GetExtensionWindowController() const { |
| 237 return view() && view()->browser() ? | 236 return GetExtensionView() && GetExtensionView()->GetBrowser() ? |
| 238 view()->browser()->extension_window_controller() : NULL; | 237 GetExtensionView()->GetBrowser()->extension_window_controller() : NULL; |
| 239 } | 238 } |
| 240 | 239 |
| 241 const GURL& ExtensionHost::GetURL() const { | 240 const GURL& ExtensionHost::GetURL() const { |
| 242 return host_contents()->GetURL(); | 241 return host_contents()->GetURL(); |
| 243 } | 242 } |
| 244 | 243 |
| 245 void ExtensionHost::LoadInitialURL() { | 244 void ExtensionHost::LoadInitialURL() { |
| 246 if (!is_background_page() && | 245 if (!is_background_page() && |
| 247 !profile_->GetExtensionService()->IsBackgroundPageReady(extension_)) { | 246 !profile_->GetExtensionService()->IsBackgroundPageReady(extension_)) { |
| 248 // Make sure the background page loads before any others. | 247 // Make sure the background page loads before any others. |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 289 } | 288 } |
| 290 break; | 289 break; |
| 291 default: | 290 default: |
| 292 NOTREACHED() << "Unexpected notification sent."; | 291 NOTREACHED() << "Unexpected notification sent."; |
| 293 break; | 292 break; |
| 294 } | 293 } |
| 295 } | 294 } |
| 296 | 295 |
| 297 void ExtensionHost::ResizeDueToAutoResize(WebContents* source, | 296 void ExtensionHost::ResizeDueToAutoResize(WebContents* source, |
| 298 const gfx::Size& new_size) { | 297 const gfx::Size& new_size) { |
| 299 if (view()) | 298 if (GetExtensionView()) |
| 300 view()->ResizeDueToAutoResize(new_size); | 299 GetExtensionView()->ResizeDueToAutoResize(new_size); |
| 301 } | 300 } |
| 302 | 301 |
| 303 void ExtensionHost::RenderViewGone(base::TerminationStatus status) { | 302 void ExtensionHost::RenderViewGone(base::TerminationStatus status) { |
| 304 // During browser shutdown, we may use sudden termination on an extension | 303 // During browser shutdown, we may use sudden termination on an extension |
| 305 // process, so it is expected to lose our connection to the render view. | 304 // process, so it is expected to lose our connection to the render view. |
| 306 // Do nothing. | 305 // Do nothing. |
| 307 if (browser_shutdown::GetShutdownType() != browser_shutdown::NOT_VALID) | 306 if (browser_shutdown::GetShutdownType() != browser_shutdown::NOT_VALID) |
| 308 return; | 307 return; |
| 309 | 308 |
| 310 // In certain cases, multiple ExtensionHost objects may have pointed to | 309 // In certain cases, multiple ExtensionHost objects may have pointed to |
| (...skipping 25 matching lines...) Expand all Loading... |
| 336 } | 335 } |
| 337 | 336 |
| 338 void ExtensionHost::DidStopLoading(content::RenderViewHost* render_view_host) { | 337 void ExtensionHost::DidStopLoading(content::RenderViewHost* render_view_host) { |
| 339 bool notify = !did_stop_loading_; | 338 bool notify = !did_stop_loading_; |
| 340 did_stop_loading_ = true; | 339 did_stop_loading_ = true; |
| 341 if (extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_POPUP || | 340 if (extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_POPUP || |
| 342 extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_DIALOG || | 341 extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_DIALOG || |
| 343 extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_INFOBAR || | 342 extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_INFOBAR || |
| 344 extension_host_type_ == chrome::VIEW_TYPE_PANEL) { | 343 extension_host_type_ == chrome::VIEW_TYPE_PANEL) { |
| 345 #if defined(TOOLKIT_VIEWS) || defined(OS_MACOSX) | 344 #if defined(TOOLKIT_VIEWS) || defined(OS_MACOSX) |
| 346 if (view()) | 345 if (GetExtensionView()) |
| 347 view()->DidStopLoading(); | 346 GetExtensionView()->DidStopLoading(); |
| 348 #endif | 347 #endif |
| 349 } | 348 } |
| 350 if (notify) { | 349 if (notify) { |
| 351 if (extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_BACKGROUND_PAGE) { | 350 if (extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_BACKGROUND_PAGE) { |
| 352 if (extension_ && extension_->has_lazy_background_page()) { | 351 if (extension_ && extension_->has_lazy_background_page()) { |
| 353 UMA_HISTOGRAM_TIMES("Extensions.EventPageLoadTime", | 352 UMA_HISTOGRAM_TIMES("Extensions.EventPageLoadTime", |
| 354 since_created_.Elapsed()); | 353 since_created_.Elapsed()); |
| 355 } else { | 354 } else { |
| 356 UMA_HISTOGRAM_TIMES("Extensions.BackgroundPageLoadTime", | 355 UMA_HISTOGRAM_TIMES("Extensions.BackgroundPageLoadTime", |
| 357 since_created_.Elapsed()); | 356 since_created_.Elapsed()); |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 406 extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_INFOBAR || | 405 extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_INFOBAR || |
| 407 extension_host_type_ == chrome::VIEW_TYPE_PANEL) { | 406 extension_host_type_ == chrome::VIEW_TYPE_PANEL) { |
| 408 Close(); | 407 Close(); |
| 409 } | 408 } |
| 410 } | 409 } |
| 411 | 410 |
| 412 void ExtensionHost::OnStartDownload( | 411 void ExtensionHost::OnStartDownload( |
| 413 content::WebContents* source, content::DownloadItem* download) { | 412 content::WebContents* source, content::DownloadItem* download) { |
| 414 // If |source| is in the context of a Browser, show the DownloadShelf on that | 413 // If |source| is in the context of a Browser, show the DownloadShelf on that |
| 415 // Browser. | 414 // Browser. |
| 416 if (!view() || !view()->browser()) | 415 if (!GetExtensionView() || !GetExtensionView()->GetBrowser()) |
| 417 return; | 416 return; |
| 418 static_cast<content::WebContentsDelegate*>(view()->browser())-> | 417 static_cast<content::WebContentsDelegate*>(GetExtensionView()->GetBrowser())-> |
| 419 OnStartDownload(source, download); | 418 OnStartDownload(source, download); |
| 420 } | 419 } |
| 421 | 420 |
| 422 void ExtensionHost::WebIntentDispatch( | 421 void ExtensionHost::WebIntentDispatch( |
| 423 content::WebContents* web_contents, | 422 content::WebContents* web_contents, |
| 424 content::WebIntentsDispatcher* intents_dispatcher) { | 423 content::WebIntentsDispatcher* intents_dispatcher) { |
| 425 #if !defined(OS_ANDROID) | 424 #if !defined(OS_ANDROID) |
| 426 scoped_ptr<content::WebIntentsDispatcher> dispatcher(intents_dispatcher); | 425 scoped_ptr<content::WebIntentsDispatcher> dispatcher(intents_dispatcher); |
| 427 | 426 |
| 428 Browser* browser = view() ? view()->browser() | 427 Browser* browser = GetExtensionView() ? GetExtensionView()->GetBrowser() |
| 429 : browser::FindBrowserWithWebContents(web_contents); | 428 : browser::FindBrowserWithWebContents(web_contents); |
| 430 | 429 |
| 431 // For background scripts/pages, there will be no view(). In this case, we | 430 // For background scripts/pages, there will be no GetExtensionView(). In this |
| 432 // want to treat the intent as a browser-initiated one and deliver it into the | 431 // case, we want to treat the intent as a browser-initiated one and deliver it |
| 433 // current browser. It probably came from a context menu click or similar. | 432 // into the current browser. It probably came from a context menu click or |
| 433 // similar. |
| 434 if (!browser) | 434 if (!browser) |
| 435 browser = web_intents::GetBrowserForBackgroundWebIntentDelivery(profile()); | 435 browser = web_intents::GetBrowserForBackgroundWebIntentDelivery(profile()); |
| 436 | 436 |
| 437 if (browser) { | 437 if (browser) { |
| 438 static_cast<WebContentsDelegate*>(browser)-> | 438 static_cast<WebContentsDelegate*>(browser)-> |
| 439 WebIntentDispatch(NULL, dispatcher.release()); | 439 WebIntentDispatch(NULL, dispatcher.release()); |
| 440 } | 440 } |
| 441 #endif | 441 #endif |
| 442 } | 442 } |
| 443 | 443 |
| (...skipping 17 matching lines...) Expand all Loading... |
| 461 switch (params.disposition) { | 461 switch (params.disposition) { |
| 462 case SINGLETON_TAB: | 462 case SINGLETON_TAB: |
| 463 case NEW_FOREGROUND_TAB: | 463 case NEW_FOREGROUND_TAB: |
| 464 case NEW_BACKGROUND_TAB: | 464 case NEW_BACKGROUND_TAB: |
| 465 case NEW_POPUP: | 465 case NEW_POPUP: |
| 466 case NEW_WINDOW: | 466 case NEW_WINDOW: |
| 467 case SAVE_TO_DISK: | 467 case SAVE_TO_DISK: |
| 468 case OFF_THE_RECORD: { | 468 case OFF_THE_RECORD: { |
| 469 // Only allow these from hosts that are bound to a browser (e.g. popups). | 469 // Only allow these from hosts that are bound to a browser (e.g. popups). |
| 470 // Otherwise they are not driven by a user gesture. | 470 // Otherwise they are not driven by a user gesture. |
| 471 Browser* browser = view() ? view()->browser() : NULL; | 471 Browser* browser = GetExtensionView() ? |
| 472 GetExtensionView()->GetBrowser() : NULL; |
| 472 return browser ? browser->OpenURL(params) : NULL; | 473 return browser ? browser->OpenURL(params) : NULL; |
| 473 } | 474 } |
| 474 default: | 475 default: |
| 475 return NULL; | 476 return NULL; |
| 476 } | 477 } |
| 477 } | 478 } |
| 478 | 479 |
| 479 bool ExtensionHost::PreHandleKeyboardEvent(WebContents* source, | 480 bool ExtensionHost::PreHandleKeyboardEvent(WebContents* source, |
| 480 const NativeWebKeyboardEvent& event, | 481 const NativeWebKeyboardEvent& event, |
| 481 bool* is_keyboard_shortcut) { | 482 bool* is_keyboard_shortcut) { |
| 482 if (extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_POPUP && | 483 if (extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_POPUP && |
| 483 event.type == NativeWebKeyboardEvent::RawKeyDown && | 484 event.type == NativeWebKeyboardEvent::RawKeyDown && |
| 484 event.windowsKeyCode == ui::VKEY_ESCAPE) { | 485 event.windowsKeyCode == ui::VKEY_ESCAPE) { |
| 485 DCHECK(is_keyboard_shortcut != NULL); | 486 DCHECK(is_keyboard_shortcut != NULL); |
| 486 *is_keyboard_shortcut = true; | 487 *is_keyboard_shortcut = true; |
| 487 return false; | 488 return false; |
| 488 } | 489 } |
| 489 | 490 |
| 490 // Handle higher priority browser shortcuts such as Ctrl-w. | 491 // Handle higher priority browser shortcuts such as Ctrl-w. |
| 491 Browser* browser = view() ? view()->browser() : NULL; | 492 Browser* browser = GetExtensionView() ? |
| 493 GetExtensionView()->GetBrowser() : NULL; |
| 492 if (browser) | 494 if (browser) |
| 493 return browser->PreHandleKeyboardEvent(source, event, is_keyboard_shortcut); | 495 return browser->PreHandleKeyboardEvent(source, event, is_keyboard_shortcut); |
| 494 | 496 |
| 495 *is_keyboard_shortcut = false; | 497 *is_keyboard_shortcut = false; |
| 496 return false; | 498 return false; |
| 497 } | 499 } |
| 498 | 500 |
| 499 void ExtensionHost::HandleKeyboardEvent(WebContents* source, | 501 void ExtensionHost::HandleKeyboardEvent(WebContents* source, |
| 500 const NativeWebKeyboardEvent& event) { | 502 const NativeWebKeyboardEvent& event) { |
| 501 if (extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_POPUP) { | 503 if (extension_host_type_ == chrome::VIEW_TYPE_EXTENSION_POPUP) { |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 543 void ExtensionHost::OnDecrementLazyKeepaliveCount() { | 545 void ExtensionHost::OnDecrementLazyKeepaliveCount() { |
| 544 ExtensionProcessManager* pm = | 546 ExtensionProcessManager* pm = |
| 545 ExtensionSystem::Get(profile_)->process_manager(); | 547 ExtensionSystem::Get(profile_)->process_manager(); |
| 546 if (pm) | 548 if (pm) |
| 547 pm->DecrementLazyKeepaliveCount(extension()); | 549 pm->DecrementLazyKeepaliveCount(extension()); |
| 548 } | 550 } |
| 549 | 551 |
| 550 void ExtensionHost::UnhandledKeyboardEvent( | 552 void ExtensionHost::UnhandledKeyboardEvent( |
| 551 WebContents* source, | 553 WebContents* source, |
| 552 const content::NativeWebKeyboardEvent& event) { | 554 const content::NativeWebKeyboardEvent& event) { |
| 553 Browser* browser = view() ? view()->browser() : NULL; | 555 Browser* browser = GetExtensionView() ? |
| 556 GetExtensionView()->GetBrowser() : NULL; |
| 554 if (browser) { | 557 if (browser) { |
| 555 // Handle lower priority browser shortcuts such as Ctrl-f. | 558 // Handle lower priority browser shortcuts such as Ctrl-f. |
| 556 return browser->HandleKeyboardEvent(source, event); | 559 return browser->HandleKeyboardEvent(source, event); |
| 557 } else { | 560 } else { |
| 558 #if defined(TOOLKIT_VIEWS) | 561 #if defined(TOOLKIT_VIEWS) |
| 559 // In case there's no Browser (e.g. for dialogs), pass it to | 562 // In case there's no Browser (e.g. for dialogs), pass it to |
| 560 // ExtensionViewViews to handle acceleratos. The view's FocusManager does | 563 // ExtensionViewViews to handle acceleratos. The view's FocusManager does |
| 561 // not know anything about Browser accelerators, but might know others such | 564 // not know anything about Browser accelerators, but might know others such |
| 562 // as Ash's. | 565 // as Ash's. |
| 563 if (view()) | 566 if (GetExtensionView()) |
| 564 view()->HandleKeyboardEvent(event); | 567 GetExtensionView()->HandleKeyboardEvent(event); |
| 565 #endif | 568 #endif |
| 566 } | 569 } |
| 567 } | 570 } |
| 568 | 571 |
| 569 void ExtensionHost::RenderViewCreated(RenderViewHost* render_view_host) { | 572 void ExtensionHost::RenderViewCreated(RenderViewHost* render_view_host) { |
| 570 render_view_host_ = render_view_host; | 573 render_view_host_ = render_view_host; |
| 571 | 574 |
| 572 if (view()) | 575 if (GetExtensionView()) |
| 573 view()->RenderViewCreated(); | 576 GetExtensionView()->RenderViewCreated(); |
| 574 | 577 |
| 575 // If the host is bound to a window, then extract its id. Extensions hosted | 578 // If the host is bound to a window, then extract its id. Extensions hosted |
| 576 // in ExternalTabContainer objects may not have an associated window. | 579 // in ExternalTabContainer objects may not have an associated window. |
| 577 extensions::WindowController* window = GetExtensionWindowController(); | 580 extensions::WindowController* window = GetExtensionWindowController(); |
| 578 if (window) { | 581 if (window) { |
| 579 render_view_host->Send(new ExtensionMsg_UpdateBrowserWindowId( | 582 render_view_host->Send(new ExtensionMsg_UpdateBrowserWindowId( |
| 580 render_view_host->GetRoutingID(), window->GetWindowId())); | 583 render_view_host->GetRoutingID(), window->GetWindowId())); |
| 581 } | 584 } |
| 582 } | 585 } |
| 583 | 586 |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 634 } | 637 } |
| 635 | 638 |
| 636 void ExtensionHost::RenderViewReady() { | 639 void ExtensionHost::RenderViewReady() { |
| 637 content::NotificationService::current()->Notify( | 640 content::NotificationService::current()->Notify( |
| 638 chrome::NOTIFICATION_EXTENSION_HOST_CREATED, | 641 chrome::NOTIFICATION_EXTENSION_HOST_CREATED, |
| 639 content::Source<Profile>(profile_), | 642 content::Source<Profile>(profile_), |
| 640 content::Details<ExtensionHost>(this)); | 643 content::Details<ExtensionHost>(this)); |
| 641 } | 644 } |
| 642 | 645 |
| 643 } // namespace extensions | 646 } // namespace extensions |
| OLD | NEW |