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_view_host.h"
9#include "chrome/browser/extensions/extension_view_host_factory.h"
10#include "chrome/browser/infobars/infobar_service.h"
11#include "chrome/browser/profiles/profile.h"
12#include "chrome/browser/ui/browser.h"
13#include "components/infobars/core/infobar.h"
14#include "content/public/browser/notification_details.h"
15#include "content/public/browser/notification_source.h"
16#include "extensions/browser/extension_registry.h"
17#include "extensions/common/extension.h"
18
19ExtensionInfoBarDelegate::~ExtensionInfoBarDelegate() {
20}
21
22// static
23void ExtensionInfoBarDelegate::Create(content::WebContents* web_contents,
24                                      Browser* browser,
25                                      const extensions::Extension* extension,
26                                      const GURL& url,
27                                      int height) {
28  InfoBarService::FromWebContents(web_contents)->AddInfoBar(
29      ExtensionInfoBarDelegate::CreateInfoBar(
30          scoped_ptr<ExtensionInfoBarDelegate>(new ExtensionInfoBarDelegate(
31              browser, extension, url, web_contents, height))));
32}
33
34ExtensionInfoBarDelegate::ExtensionInfoBarDelegate(
35    Browser* browser,
36    const extensions::Extension* extension,
37    const GURL& url,
38    content::WebContents* web_contents,
39    int height)
40    : infobars::InfoBarDelegate(),
41#if defined(TOOLKIT_VIEWS)
42      browser_(browser),
43#endif
44      extension_(extension),
45      extension_registry_observer_(this),
46      closing_(false) {
47  extension_view_host_.reset(
48      extensions::ExtensionViewHostFactory::CreateInfobarHost(url, browser));
49  extension_view_host_->SetAssociatedWebContents(web_contents);
50
51  extension_registry_observer_.Add(
52      extensions::ExtensionRegistry::Get(browser->profile()));
53  registrar_.Add(this,
54                 extensions::NOTIFICATION_EXTENSION_HOST_VIEW_SHOULD_CLOSE,
55                 content::Source<Profile>(browser->profile()));
56
57  height_ = std::max(0, height);
58  height_ = std::min(2 * infobars::InfoBar::kDefaultBarTargetHeight, height_);
59  if (height_ == 0)
60    height_ = infobars::InfoBar::kDefaultBarTargetHeight;
61}
62
63content::WebContents* ExtensionInfoBarDelegate::GetWebContents() {
64  return InfoBarService::WebContentsFromInfoBar(infobar());
65}
66
67// ExtensionInfoBarDelegate::CreateInfoBar() is implemented in platform-specific
68// files.
69
70bool ExtensionInfoBarDelegate::EqualsDelegate(
71    infobars::InfoBarDelegate* delegate) const {
72  ExtensionInfoBarDelegate* extension_delegate =
73      delegate->AsExtensionInfoBarDelegate();
74  // When an extension crashes, an InfoBar is shown (for the crashed extension).
75  // That will result in a call to this function (to see if this InfoBarDelegate
76  // is already showing the 'extension crashed InfoBar', which it never is), but
77  // if it is our extension that crashes, the extension delegate is NULL so
78  // we cannot check.
79  if (!extension_delegate)
80    return false;
81
82  // Only allow one InfoBar at a time per extension.
83  return extension_delegate->extension_view_host()->extension() ==
84         extension_view_host_->extension();
85}
86
87void ExtensionInfoBarDelegate::InfoBarDismissed() {
88  closing_ = true;
89}
90
91infobars::InfoBarDelegate::Type ExtensionInfoBarDelegate::GetInfoBarType()
92    const {
93  return PAGE_ACTION_TYPE;
94}
95
96ExtensionInfoBarDelegate*
97    ExtensionInfoBarDelegate::AsExtensionInfoBarDelegate() {
98  return this;
99}
100
101void ExtensionInfoBarDelegate::OnExtensionUnloaded(
102    content::BrowserContext* browser_context,
103    const extensions::Extension* extension,
104    extensions::UnloadedExtensionInfo::Reason reason) {
105  if (extension_ == extension)
106    infobar()->RemoveSelf();
107}
108
109void ExtensionInfoBarDelegate::Observe(
110    int type,
111    const content::NotificationSource& source,
112    const content::NotificationDetails& details) {
113  DCHECK_EQ(type, extensions::NOTIFICATION_EXTENSION_HOST_VIEW_SHOULD_CLOSE);
114  if (extension_view_host_.get() ==
115      content::Details<extensions::ExtensionHost>(details).ptr())
116    infobar()->RemoveSelf();
117}
118