summaryrefslogtreecommitdiff
path: root/chromium/chrome/browser/extensions/api/debugger/extension_dev_tools_infobar.cc
blob: fdc19ab8c5535dc9c29fe36a73dcf15d5a22830f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/extensions/api/debugger/extension_dev_tools_infobar.h"

#include <memory>

#include "base/callback_helpers.h"
#include "base/lazy_instance.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/devtools/global_confirm_info_bar.h"
#include "chrome/grit/generated_resources.h"
#include "components/infobars/core/confirm_infobar_delegate.h"
#include "ui/base/l10n/l10n_util.h"

namespace extensions {

namespace {

// The InfoBarDelegate that ExtensionDevToolsInfoBar shows.
class ExtensionDevToolsInfoBarDelegate : public ConfirmInfoBarDelegate {
 public:
  ExtensionDevToolsInfoBarDelegate(const base::Closure& dismissed_callback,
                                   const std::string& client_name);
  ~ExtensionDevToolsInfoBarDelegate() override;

  // ConfirmInfoBarDelegate:
  infobars::InfoBarDelegate::InfoBarIdentifier GetIdentifier() const override;
  bool ShouldExpire(const NavigationDetails& details) const override;
  void InfoBarDismissed() override;
  base::string16 GetMessageText() const override;
  gfx::ElideBehavior GetMessageElideBehavior() const override;

  int GetButtons() const override;
  bool Cancel() override;

 private:
  const base::string16 client_name_;
  base::Closure dismissed_callback_;

  DISALLOW_COPY_AND_ASSIGN(ExtensionDevToolsInfoBarDelegate);
};

ExtensionDevToolsInfoBarDelegate::ExtensionDevToolsInfoBarDelegate(
    const base::Closure& dismissed_callback,
    const std::string& client_name)
    : ConfirmInfoBarDelegate(),
      client_name_(base::UTF8ToUTF16(client_name)),
      dismissed_callback_(dismissed_callback) {}

ExtensionDevToolsInfoBarDelegate::~ExtensionDevToolsInfoBarDelegate() {}

infobars::InfoBarDelegate::InfoBarIdentifier
ExtensionDevToolsInfoBarDelegate::GetIdentifier() const {
  return EXTENSION_DEV_TOOLS_INFOBAR_DELEGATE;
}

bool ExtensionDevToolsInfoBarDelegate::ShouldExpire(
    const NavigationDetails& details) const {
  return false;
}

void ExtensionDevToolsInfoBarDelegate::InfoBarDismissed() {
  DCHECK(!dismissed_callback_.is_null());
  // Use ResetAndReturn() since running the callback may delete |this|.
  base::ResetAndReturn(&dismissed_callback_).Run();
}

base::string16 ExtensionDevToolsInfoBarDelegate::GetMessageText() const {
  return l10n_util::GetStringFUTF16(IDS_DEV_TOOLS_INFOBAR_LABEL, client_name_);
}

gfx::ElideBehavior ExtensionDevToolsInfoBarDelegate::GetMessageElideBehavior()
    const {
  // The important part of the message text above is at the end:
  // "... is debugging the browser". If the extension name is very long,
  // we'd rather truncate it instead. See https://crbug.com/823194.
  return gfx::ELIDE_HEAD;
}

int ExtensionDevToolsInfoBarDelegate::GetButtons() const {
  return BUTTON_CANCEL;
}

bool ExtensionDevToolsInfoBarDelegate::Cancel() {
  InfoBarDismissed();
  // InfoBarDismissed() will have closed us already.
  return false;
}

using ExtensionInfoBars = std::map<std::string, ExtensionDevToolsInfoBar*>;
base::LazyInstance<ExtensionInfoBars>::Leaky g_extension_info_bars =
    LAZY_INSTANCE_INITIALIZER;

}  // namespace

// static
ExtensionDevToolsInfoBar* ExtensionDevToolsInfoBar::Create(
    const std::string& extension_id,
    const std::string& extension_name,
    ExtensionDevToolsClientHost* client_host,
    const base::Closure& dismissed_callback) {
  ExtensionInfoBars::iterator it =
      g_extension_info_bars.Get().find(extension_id);
  ExtensionDevToolsInfoBar* infobar = nullptr;
  if (it != g_extension_info_bars.Get().end())
    infobar = it->second;
  else
    infobar = new ExtensionDevToolsInfoBar(extension_id, extension_name);
  infobar->callbacks_[client_host] = dismissed_callback;
  return infobar;
}

ExtensionDevToolsInfoBar::ExtensionDevToolsInfoBar(
    const std::string& extension_id,
    const std::string& extension_name)
    : extension_id_(extension_id) {
  g_extension_info_bars.Get()[extension_id] = this;

  // This class closes the |infobar_|, so it's safe to pass Unretained(this).
  auto delegate = std::make_unique<ExtensionDevToolsInfoBarDelegate>(
      base::Bind(&ExtensionDevToolsInfoBar::InfoBarDismissed,
                 base::Unretained(this)),
      extension_name);
  infobar_ = GlobalConfirmInfoBar::Show(std::move(delegate));
}

ExtensionDevToolsInfoBar::~ExtensionDevToolsInfoBar() {
  g_extension_info_bars.Get().erase(extension_id_);
  if (infobar_)
    infobar_->Close();
}

void ExtensionDevToolsInfoBar::Remove(
    ExtensionDevToolsClientHost* client_host) {
  callbacks_.erase(client_host);
  if (callbacks_.empty())
    delete this;
}

void ExtensionDevToolsInfoBar::InfoBarDismissed() {
  std::map<ExtensionDevToolsClientHost*, base::Closure> copy = callbacks_;
  for (const auto& pair : copy)
    pair.second.Run();
}

}  // namespace extensions