1// Copyright (c) 2011 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/extensions/extension_host.h"
8#include "chrome/browser/extensions/extension_process_manager.h"
9#include "chrome/browser/profiles/profile.h"
10#include "chrome/browser/ui/browser.h"
11#include "chrome/common/extensions/extension.h"
12#include "content/browser/tab_contents/tab_contents.h"
13#include "content/common/notification_details.h"
14#include "content/common/notification_source.h"
15#include "content/common/notification_type.h"
16
17ExtensionInfoBarDelegate::ExtensionInfoBarDelegate(Browser* browser,
18                                                   TabContents* tab_contents,
19                                                   const Extension* extension,
20                                                   const GURL& url)
21    : InfoBarDelegate(tab_contents),
22      observer_(NULL),
23      extension_(extension),
24      tab_contents_(tab_contents),
25      closing_(false) {
26  ExtensionProcessManager* manager =
27      browser->profile()->GetExtensionProcessManager();
28  extension_host_.reset(manager->CreateInfobar(url, browser));
29  extension_host_->set_associated_tab_contents(tab_contents);
30
31  registrar_.Add(this, NotificationType::EXTENSION_HOST_VIEW_SHOULD_CLOSE,
32                 Source<Profile>(browser->profile()));
33  registrar_.Add(this, NotificationType::EXTENSION_UNLOADED,
34                 Source<Profile>(browser->profile()));
35}
36
37ExtensionInfoBarDelegate::~ExtensionInfoBarDelegate() {
38  if (observer_)
39    observer_->OnDelegateDeleted();
40}
41
42bool ExtensionInfoBarDelegate::EqualsDelegate(InfoBarDelegate* delegate) const {
43  ExtensionInfoBarDelegate* extension_delegate =
44      delegate->AsExtensionInfoBarDelegate();
45  // When an extension crashes, an InfoBar is shown (for the crashed extension).
46  // That will result in a call to this function (to see if this InfoBarDelegate
47  // is already showing the 'extension crashed InfoBar', which it never is), but
48  // if it is our extension that crashes, the extension delegate is NULL so
49  // we cannot check.
50  if (!extension_delegate)
51    return false;
52
53  // Only allow one InfoBar at a time per extension.
54  return extension_delegate->extension_host()->extension() ==
55         extension_host_->extension();
56}
57
58void ExtensionInfoBarDelegate::InfoBarDismissed() {
59  closing_ = true;
60}
61
62void ExtensionInfoBarDelegate::InfoBarClosed() {
63  delete this;
64}
65
66InfoBarDelegate::Type ExtensionInfoBarDelegate::GetInfoBarType() const {
67  return PAGE_ACTION_TYPE;
68}
69
70ExtensionInfoBarDelegate*
71    ExtensionInfoBarDelegate::AsExtensionInfoBarDelegate() {
72  return this;
73}
74
75void ExtensionInfoBarDelegate::Observe(NotificationType type,
76                                       const NotificationSource& source,
77                                       const NotificationDetails& details) {
78  switch (type.value) {
79    case NotificationType::EXTENSION_HOST_VIEW_SHOULD_CLOSE: {
80      const ExtensionHost* result = Details<ExtensionHost>(details).ptr();
81      if (extension_host_.get() == result)
82        tab_contents_->RemoveInfoBar(this);
83      break;
84    }
85    case NotificationType::EXTENSION_UNLOADED: {
86      const Extension* extension =
87          Details<UnloadedExtensionInfo>(details)->extension;
88      if (extension_ == extension)
89        tab_contents_->RemoveInfoBar(this);
90      break;
91    }
92    default: {
93      NOTREACHED() << "Unknown message";
94      break;
95    }
96  }
97}
98