15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_infobar_delegate.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
77dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/chrome_notification_types.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_host.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_process_manager.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_system.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/infobars/infobar.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/infobars/infobar_service.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/extensions/extension.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_details.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_source.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ExtensionInfoBarDelegate::~ExtensionInfoBarDelegate() {
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (observer_)
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    observer_->OnDelegateDeleted();
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ExtensionInfoBarDelegate::Create(InfoBarService* infobar_service,
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                      Browser* browser,
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                      const extensions::Extension* extension,
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                      const GURL& url,
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                      int height) {
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  infobar_service->AddInfoBar(scoped_ptr<InfoBarDelegate>(
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new ExtensionInfoBarDelegate(browser, infobar_service, extension, url,
33ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                                   infobar_service->web_contents(), height)));
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ExtensionInfoBarDelegate::ExtensionInfoBarDelegate(
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Browser* browser,
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    InfoBarService* infobar_service,
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const extensions::Extension* extension,
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& url,
41ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    content::WebContents* web_contents,
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int height)
437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    : InfoBarDelegate(infobar_service),
447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#if defined(TOOLKIT_VIEWS)
457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      browser_(browser),
467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#endif
477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      observer_(NULL),
487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      extension_(extension),
497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      closing_(false) {
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExtensionProcessManager* manager =
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      extensions::ExtensionSystem::Get(browser->profile())->process_manager();
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  extension_host_.reset(manager->CreateInfobarHost(url, browser));
53ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  extension_host_->SetAssociatedWebContents(web_contents);
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_HOST_VIEW_SHOULD_CLOSE,
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 content::Source<Profile>(browser->profile()));
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED,
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 content::Source<Profile>(browser->profile()));
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
60ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#if defined(TOOLKIT_VIEWS) || defined(TOOLKIT_GTK) || defined(OS_ANDROID)
61ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // TODO(dtrainor): On Android, this is not used.  Might need to pull this from
62ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Android UI level in the future.  Tracked via issue 115303.
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int default_height = InfoBar::kDefaultBarTargetHeight;
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_MACOSX)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(pkasting): Once Infobars have been ported to Mac, we can remove the
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ifdefs and just use the Infobar constant below.
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int default_height = 36;
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  height_ = std::max(0, height);
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  height_ = std::min(2 * default_height, height_);
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (height_ == 0)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    height_ = default_height;
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ExtensionInfoBarDelegate::EqualsDelegate(InfoBarDelegate* delegate) const {
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExtensionInfoBarDelegate* extension_delegate =
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delegate->AsExtensionInfoBarDelegate();
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // When an extension crashes, an InfoBar is shown (for the crashed extension).
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // That will result in a call to this function (to see if this InfoBarDelegate
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // is already showing the 'extension crashed InfoBar', which it never is), but
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // if it is our extension that crashes, the extension delegate is NULL so
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // we cannot check.
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!extension_delegate)
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Only allow one InfoBar at a time per extension.
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return extension_delegate->extension_host()->extension() ==
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         extension_host_->extension();
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionInfoBarDelegate::InfoBarDismissed() {
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  closing_ = true;
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)InfoBarDelegate::Type ExtensionInfoBarDelegate::GetInfoBarType() const {
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return PAGE_ACTION_TYPE;
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ExtensionInfoBarDelegate*
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ExtensionInfoBarDelegate::AsExtensionInfoBarDelegate() {
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return this;
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionInfoBarDelegate::Observe(
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int type,
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const content::NotificationSource& source,
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const content::NotificationDetails& details) {
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (type == chrome::NOTIFICATION_EXTENSION_HOST_VIEW_SHOULD_CLOSE) {
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (extension_host_.get() ==
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        content::Details<extensions::ExtensionHost>(details).ptr())
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      RemoveSelf();
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(type == chrome::NOTIFICATION_EXTENSION_UNLOADED);
1147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    if (extension_ == content::Details<extensions::UnloadedExtensionInfo>(
1157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        details)->extension)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      RemoveSelf();
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
119