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/extensions/extension_infobar_delegate.h" 6 7 #include "chrome/browser/chrome_notification_types.h" 8 #include "chrome/browser/extensions/extension_host.h" 9 #include "chrome/browser/extensions/extension_process_manager.h" 10 #include "chrome/browser/extensions/extension_system.h" 11 #include "chrome/browser/infobars/infobar.h" 12 #include "chrome/browser/infobars/infobar_service.h" 13 #include "chrome/browser/profiles/profile.h" 14 #include "chrome/browser/ui/browser.h" 15 #include "chrome/common/extensions/extension.h" 16 #include "content/public/browser/notification_details.h" 17 #include "content/public/browser/notification_source.h" 18 19 20 ExtensionInfoBarDelegate::~ExtensionInfoBarDelegate() { 21 if (observer_) 22 observer_->OnDelegateDeleted(); 23 } 24 25 // static 26 void ExtensionInfoBarDelegate::Create(InfoBarService* infobar_service, 27 Browser* browser, 28 const extensions::Extension* extension, 29 const GURL& url, 30 int height) { 31 infobar_service->AddInfoBar(scoped_ptr<InfoBarDelegate>( 32 new ExtensionInfoBarDelegate(browser, infobar_service, extension, url, 33 infobar_service->web_contents(), height))); 34 } 35 36 ExtensionInfoBarDelegate::ExtensionInfoBarDelegate( 37 Browser* browser, 38 InfoBarService* infobar_service, 39 const extensions::Extension* extension, 40 const GURL& url, 41 content::WebContents* web_contents, 42 int height) 43 : InfoBarDelegate(infobar_service), 44 #if defined(TOOLKIT_VIEWS) 45 browser_(browser), 46 #endif 47 observer_(NULL), 48 extension_(extension), 49 closing_(false) { 50 ExtensionProcessManager* manager = 51 extensions::ExtensionSystem::Get(browser->profile())->process_manager(); 52 extension_host_.reset(manager->CreateInfobarHost(url, browser)); 53 extension_host_->SetAssociatedWebContents(web_contents); 54 55 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_HOST_VIEW_SHOULD_CLOSE, 56 content::Source<Profile>(browser->profile())); 57 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED, 58 content::Source<Profile>(browser->profile())); 59 60 #if defined(TOOLKIT_VIEWS) || defined(TOOLKIT_GTK) || defined(OS_ANDROID) 61 // TODO(dtrainor): On Android, this is not used. Might need to pull this from 62 // Android UI level in the future. Tracked via issue 115303. 63 int default_height = InfoBar::kDefaultBarTargetHeight; 64 #elif defined(OS_MACOSX) 65 // TODO(pkasting): Once Infobars have been ported to Mac, we can remove the 66 // ifdefs and just use the Infobar constant below. 67 int default_height = 36; 68 #endif 69 height_ = std::max(0, height); 70 height_ = std::min(2 * default_height, height_); 71 if (height_ == 0) 72 height_ = default_height; 73 } 74 75 bool ExtensionInfoBarDelegate::EqualsDelegate(InfoBarDelegate* delegate) const { 76 ExtensionInfoBarDelegate* extension_delegate = 77 delegate->AsExtensionInfoBarDelegate(); 78 // When an extension crashes, an InfoBar is shown (for the crashed extension). 79 // That will result in a call to this function (to see if this InfoBarDelegate 80 // is already showing the 'extension crashed InfoBar', which it never is), but 81 // if it is our extension that crashes, the extension delegate is NULL so 82 // we cannot check. 83 if (!extension_delegate) 84 return false; 85 86 // Only allow one InfoBar at a time per extension. 87 return extension_delegate->extension_host()->extension() == 88 extension_host_->extension(); 89 } 90 91 void ExtensionInfoBarDelegate::InfoBarDismissed() { 92 closing_ = true; 93 } 94 95 InfoBarDelegate::Type ExtensionInfoBarDelegate::GetInfoBarType() const { 96 return PAGE_ACTION_TYPE; 97 } 98 99 ExtensionInfoBarDelegate* 100 ExtensionInfoBarDelegate::AsExtensionInfoBarDelegate() { 101 return this; 102 } 103 104 void ExtensionInfoBarDelegate::Observe( 105 int type, 106 const content::NotificationSource& source, 107 const content::NotificationDetails& details) { 108 if (type == chrome::NOTIFICATION_EXTENSION_HOST_VIEW_SHOULD_CLOSE) { 109 if (extension_host_.get() == 110 content::Details<extensions::ExtensionHost>(details).ptr()) 111 RemoveSelf(); 112 } else { 113 DCHECK(type == chrome::NOTIFICATION_EXTENSION_UNLOADED); 114 if (extension_ == content::Details<extensions::UnloadedExtensionInfo>( 115 details)->extension) 116 RemoveSelf(); 117 } 118 } 119