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_warning_set.h"
6
7#include "base/files/file_path.h"
8#include "base/strings/utf_string_conversions.h"
9#include "chrome/browser/chrome_notification_types.h"
10#include "chrome/common/extensions/extension_set.h"
11#include "content/public/browser/browser_thread.h"
12#include "extensions/common/extension.h"
13#include "grit/chromium_strings.h"
14#include "grit/generated_resources.h"
15#include "net/base/escape.h"
16#include "ui/base/l10n/l10n_util.h"
17
18using content::BrowserThread;
19
20namespace {
21// Prefix for message parameters indicating that the parameter needs to
22// be translated from an extension id to the extension name.
23const char kTranslate[] = "TO_TRANSLATE:";
24const size_t kMaxNumberOfParameters = 4;
25}
26
27namespace extensions {
28
29//
30// ExtensionWarning
31//
32
33ExtensionWarning::ExtensionWarning(
34    WarningType type,
35    const std::string& extension_id,
36    int message_id,
37    const std::vector<std::string>& message_parameters)
38    : type_(type),
39      extension_id_(extension_id),
40      message_id_(message_id),
41      message_parameters_(message_parameters) {
42  // These are invalid here because they do not have corresponding warning
43  // messages in the UI.
44  CHECK_NE(type, kInvalid);
45  CHECK_NE(type, kMaxWarningType);
46  CHECK_LE(message_parameters.size(), kMaxNumberOfParameters);
47}
48
49ExtensionWarning::ExtensionWarning(const ExtensionWarning& other)
50  : type_(other.type_),
51    extension_id_(other.extension_id_),
52    message_id_(other.message_id_),
53    message_parameters_(other.message_parameters_) {}
54
55ExtensionWarning::~ExtensionWarning() {
56}
57
58ExtensionWarning& ExtensionWarning::operator=(const ExtensionWarning& other) {
59  type_ = other.type_;
60  extension_id_ = other.extension_id_;
61  message_id_ = other.message_id_;
62  message_parameters_ = other.message_parameters_;
63  return *this;
64}
65
66// static
67ExtensionWarning ExtensionWarning::CreateNetworkDelayWarning(
68    const std::string& extension_id) {
69  std::vector<std::string> message_parameters;
70  message_parameters.push_back(l10n_util::GetStringUTF8(IDS_PRODUCT_NAME));
71  return ExtensionWarning(
72      kNetworkDelay,
73      extension_id,
74      IDS_EXTENSION_WARNINGS_NETWORK_DELAY,
75      message_parameters);
76}
77
78// static
79ExtensionWarning ExtensionWarning::CreateNetworkConflictWarning(
80    const std::string& extension_id) {
81  std::vector<std::string> message_parameters;
82  return ExtensionWarning(
83      kNetworkConflict,
84      extension_id,
85      IDS_EXTENSION_WARNINGS_NETWORK_CONFLICT,
86      message_parameters);
87}
88
89// static
90ExtensionWarning ExtensionWarning::CreateRedirectConflictWarning(
91    const std::string& extension_id,
92    const std::string& winning_extension_id,
93    const GURL& attempted_redirect_url,
94    const GURL& winning_redirect_url) {
95  std::vector<std::string> message_parameters;
96  message_parameters.push_back(attempted_redirect_url.spec());
97  message_parameters.push_back(kTranslate + winning_extension_id);
98  message_parameters.push_back(winning_redirect_url.spec());
99  return ExtensionWarning(
100      kRedirectConflict,
101      extension_id,
102      IDS_EXTENSION_WARNINGS_REDIRECT_CONFLICT,
103      message_parameters);
104}
105
106// static
107ExtensionWarning ExtensionWarning::CreateRequestHeaderConflictWarning(
108    const std::string& extension_id,
109    const std::string& winning_extension_id,
110    const std::string& conflicting_header) {
111  std::vector<std::string> message_parameters;
112  message_parameters.push_back(conflicting_header);
113  message_parameters.push_back(kTranslate + winning_extension_id);
114  return ExtensionWarning(
115      kNetworkConflict,
116      extension_id,
117      IDS_EXTENSION_WARNINGS_REQUEST_HEADER_CONFLICT,
118      message_parameters);
119}
120
121// static
122ExtensionWarning ExtensionWarning::CreateResponseHeaderConflictWarning(
123    const std::string& extension_id,
124    const std::string& winning_extension_id,
125    const std::string& conflicting_header) {
126  std::vector<std::string> message_parameters;
127  message_parameters.push_back(conflicting_header);
128  message_parameters.push_back(kTranslate + winning_extension_id);
129  return ExtensionWarning(
130      kNetworkConflict,
131      extension_id,
132      IDS_EXTENSION_WARNINGS_RESPONSE_HEADER_CONFLICT,
133      message_parameters);
134}
135
136// static
137ExtensionWarning ExtensionWarning::CreateCredentialsConflictWarning(
138    const std::string& extension_id,
139    const std::string& winning_extension_id) {
140  std::vector<std::string> message_parameters;
141  message_parameters.push_back(kTranslate + winning_extension_id);
142  return ExtensionWarning(
143      kNetworkConflict,
144      extension_id,
145      IDS_EXTENSION_WARNINGS_CREDENTIALS_CONFLICT,
146      message_parameters);
147}
148
149// static
150ExtensionWarning ExtensionWarning::CreateRepeatedCacheFlushesWarning(
151    const std::string& extension_id) {
152  std::vector<std::string> message_parameters;
153  message_parameters.push_back(l10n_util::GetStringUTF8(IDS_PRODUCT_NAME));
154  return ExtensionWarning(
155      kRepeatedCacheFlushes,
156      extension_id,
157      IDS_EXTENSION_WARNINGS_NETWORK_DELAY,
158      message_parameters);
159}
160
161// static
162ExtensionWarning ExtensionWarning::CreateDownloadFilenameConflictWarning(
163    const std::string& losing_extension_id,
164    const std::string& winning_extension_id,
165    const base::FilePath& losing_filename,
166    const base::FilePath& winning_filename) {
167  std::vector<std::string> message_parameters;
168  message_parameters.push_back(UTF16ToUTF8(losing_filename.LossyDisplayName()));
169  message_parameters.push_back(kTranslate + winning_extension_id);
170  message_parameters.push_back(UTF16ToUTF8(
171      winning_filename.LossyDisplayName()));
172  return ExtensionWarning(
173      kDownloadFilenameConflict,
174      losing_extension_id,
175      IDS_EXTENSION_WARNINGS_DOWNLOAD_FILENAME_CONFLICT,
176      message_parameters);
177}
178
179std::string ExtensionWarning::GetLocalizedMessage(
180    const ExtensionSet* extensions) const {
181  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
182
183  // These parameters may be unsafe (URLs and Extension names) and need
184  // to be HTML-escaped before being embedded in the UI. Also extension IDs
185  // are translated to full extension names.
186  std::vector<base::string16> final_parameters;
187  for (size_t i = 0; i < message_parameters_.size(); ++i) {
188    std::string message = message_parameters_[i];
189    if (StartsWithASCII(message, kTranslate, true)) {
190      std::string extension_id = message.substr(sizeof(kTranslate) - 1);
191      const extensions::Extension* extension =
192          extensions->GetByID(extension_id);
193      message = extension ? extension->name() : extension_id;
194    }
195    final_parameters.push_back(UTF8ToUTF16(net::EscapeForHTML(message)));
196  }
197
198  COMPILE_ASSERT(kMaxNumberOfParameters == 4u, YouNeedToAddMoreCaseStatements);
199  switch (final_parameters.size()) {
200    case 0:
201      return l10n_util::GetStringUTF8(message_id_);
202    case 1:
203      return l10n_util::GetStringFUTF8(message_id_, final_parameters[0]);
204    case 2:
205      return l10n_util::GetStringFUTF8(message_id_, final_parameters[0],
206          final_parameters[1]);
207    case 3:
208      return l10n_util::GetStringFUTF8(message_id_, final_parameters[0],
209          final_parameters[1], final_parameters[2]);
210    case 4:
211      return l10n_util::GetStringFUTF8(message_id_, final_parameters[0],
212          final_parameters[1], final_parameters[2], final_parameters[3]);
213    default:
214      NOTREACHED();
215      return std::string();
216  }
217}
218
219bool operator<(const ExtensionWarning& a, const ExtensionWarning& b) {
220  if (a.extension_id() != b.extension_id())
221    return a.extension_id() < b.extension_id();
222  return a.warning_type() < b.warning_type();
223}
224
225}  // namespace extensions
226