1 // Copyright 2013 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.
5 #include "base/basictypes.h"
6 #include "base/logging.h"
7 #include "base/metrics/field_trial.h"
8 #include "base/strings/string_number_conversions.h"
9 #include "base/strings/string_split.h"
10 #include "base/strings/stringprintf.h"
11 #include "chrome/browser/extensions/extension_install_prompt_experiment.h"
12 #include "chrome/grit/generated_resources.h"
13 #include "ui/base/l10n/l10n_util.h"
17 const char kExperimentName
[] = "ExtensionPermissionDialog";
18 const char kGroupPrefix
[] = "Group";
20 // Flags for groups. Not all combinations make sense.
21 // Refer to the UI screens at http://goo.gl/f2KzPj for those that do.
23 // No changes (Control group).
25 // Indicates that the experiment is text only. A text only experiment
26 // only adds an explanation text at the bottom of the permission dialog and
27 // modifies the text on accept/cancel buttons.
29 // Indicates that the experiment shows inline explanations for permissions.
30 INLINE_EXPLANATIONS
= 1 << 1,
31 // Indicates that the experiment highlights permission text color.
32 SHOULD_HIGHLIGHT_TEXT
= 1 << 2,
33 // Indicates that the experiment highlights permission text background.
34 SHOULD_HIGHLIGHT_BACKGROUND
= 1 << 3,
35 // Indicates that the experiment highlights all permissions.
36 SHOULD_HIGHLIGHT_ALL_PERMISSIONS
= 1 << 4,
37 // Indicates that the experiment puts a "show details" link in the UI.
38 SHOULD_SHOW_DETAILS_LINK
= 1 << 5,
39 // Indicates that the experiment hides the permissions by default and the list
41 EXPANDABLE_PERMISSION_LIST
= 1 << 6,
42 // Indicates that the experiment shows checkboxes for each permission.
43 SHOULD_SHOW_CHECKBOXES
= 1 << 7
46 // Flags for the actual experiment groups. These flags define what kind of
47 // UI changes each experiment group does. An experiment group may change
48 // multiple aspects of the extension install dialog (e.g. one of the groups
49 // show a details link and inline explanations for permissions). The control
50 // group doesn't change the UI. Text only groups add a text warning to the UI,
51 // with the text changing depending on the group number. Groups with inline
52 // explanations show detailed explanations for a subset of permissions. Some
53 // groups highlight the foreground or the background of permission texts.
54 // The flags reflect the UI screens at http://goo.gl/f2KzPj.
55 const unsigned int kGroupFlags
[] = {
56 // Control group doesn't change the UI.
58 // Adds "Do you trust this extension to use these privileges safely" text.
60 // Adds "Extension can be malicious" text.
62 // Adds "Are you sure you want to install" text.
64 // Adds "Make sure these privileges make sense for this extension" text.
66 // Adds "Do you trust this extension to perform these actions" text.
68 // Adds inline explanations displayed by default.
70 // Adds expandable inline explanations with a "Show Details" link.
71 SHOULD_SHOW_DETAILS_LINK
| INLINE_EXPLANATIONS
,
72 // Adds expandable permission list with a "Show Permissions" link.
73 SHOULD_SHOW_DETAILS_LINK
| EXPANDABLE_PERMISSION_LIST
,
74 // Highlights text for risky permissions.
75 SHOULD_HIGHLIGHT_TEXT
,
76 // Highlights background for risky permissions.
77 SHOULD_HIGHLIGHT_BACKGROUND
,
78 // Highlights background for all permissions
79 SHOULD_HIGHLIGHT_BACKGROUND
| SHOULD_HIGHLIGHT_ALL_PERMISSIONS
,
80 // Displays checkboxes for all permissions.
81 SHOULD_SHOW_CHECKBOXES
84 const size_t kGroupCount
= arraysize(kGroupFlags
);
86 // Parameters for text only experiments.
87 const struct TextParams
{
93 IDS_EXTENSION_PROMPT_EXPERIMENT_EXPLANATION1
,
94 IDS_EXTENSION_PROMPT_EXPERIMENT_INSTALL_BUTTON_TRUST
,
98 IDS_EXTENSION_PROMPT_EXPERIMENT_EXPLANATION2
,
99 IDS_EXTENSION_PROMPT_EXPERIMENT_INSTALL_BUTTON_YES
,
100 IDS_EXTENSION_PROMPT_EXPERIMENT_INSTALL_BUTTON_NOPE
103 IDS_EXTENSION_PROMPT_EXPERIMENT_EXPLANATION3
,
104 IDS_EXTENSION_PROMPT_EXPERIMENT_INSTALL_BUTTON_SURE
,
105 IDS_EXTENSION_PROMPT_EXPERIMENT_INSTALL_BUTTON_NOPE
108 IDS_EXTENSION_PROMPT_EXPERIMENT_EXPLANATION4
,
109 IDS_EXTENSION_PROMPT_INSTALL_BUTTON
,
113 IDS_EXTENSION_PROMPT_EXPERIMENT_EXPLANATION5
,
114 IDS_EXTENSION_PROMPT_EXPERIMENT_INSTALL_BUTTON_TRUST2
,
115 IDS_EXTENSION_PROMPT_EXPERIMENT_INSTALL_BUTTON_NOPE
119 // Permission warnings in this list have inline explanation texts.
120 const struct PermissionExplanations
{
122 int extra_explanation_id
;
123 } kPermissionExplanations
[] = {
125 IDS_EXTENSION_PROMPT_WARNING_FULL_ACCESS
,
126 IDS_EXTENSION_PROMPT_WARNING_FULL_ACCESS_EXPLANATION
129 IDS_EXTENSION_PROMPT_WARNING_ALL_HOSTS
,
130 IDS_EXTENSION_PROMPT_WARNING_ALL_HOSTS_EXPLANATION
134 // Permission warnings in this list are going to be highlighted.
135 // Note that the matching is done by string comparison, so this list must not
136 // contain any dynamic strings (e.g. permission for 3 hosts with the host list).
137 const int kHighlightedWarnings
[] = {
138 IDS_EXTENSION_PROMPT_WARNING_FULL_ACCESS
,
139 IDS_EXTENSION_PROMPT_WARNING_ALL_HOSTS
,
140 IDS_EXTENSION_PROMPT_WARNING_BOOKMARKS
,
141 IDS_EXTENSION_PROMPT_WARNING_CONTENT_SETTINGS
,
142 IDS_EXTENSION_PROMPT_WARNING_HISTORY_WRITE
,
143 IDS_EXTENSION_PROMPT_WARNING_INPUT
,
144 IDS_EXTENSION_PROMPT_WARNING_MANAGEMENT
,
145 IDS_EXTENSION_PROMPT_WARNING_HISTORY_READ
,
146 IDS_EXTENSION_PROMPT_WARNING_DEBUGGER
149 bool IsImportantWarning(const base::string16
& message
) {
150 for (size_t i
= 0; i
< arraysize(kHighlightedWarnings
); ++i
) {
151 if (message
== l10n_util::GetStringUTF16(kHighlightedWarnings
[i
]))
159 ExtensionInstallPromptExperiment::ExtensionInstallPromptExperiment(
160 unsigned int group_id
, unsigned int flags
)
161 : group_id_(group_id
),
165 ExtensionInstallPromptExperiment::~ExtensionInstallPromptExperiment() {
169 ExtensionInstallPromptExperiment
*
170 ExtensionInstallPromptExperiment::ControlGroup() {
171 return new ExtensionInstallPromptExperiment(0, kGroupFlags
[0]);
175 ExtensionInstallPromptExperiment
*
176 ExtensionInstallPromptExperiment::Find() {
177 base::FieldTrial
* trial
= base::FieldTrialList::Find(kExperimentName
);
178 // Default is control group.
179 unsigned int group_id
= 0;
181 std::vector
<std::string
> tokens
;
182 base::SplitString(trial
->group_name().c_str(), '_', &tokens
);
183 if (tokens
.size() == 2 && tokens
[0] == kGroupPrefix
) {
184 base::StringToUint(tokens
[1], &group_id
);
185 if (group_id
>= kGroupCount
)
189 return new ExtensionInstallPromptExperiment(group_id
, kGroupFlags
[group_id
]);
192 base::string16
ExtensionInstallPromptExperiment::GetExplanationText() const {
193 DCHECK(group_id_
> 0 && group_id_
- 1 < arraysize(kTextParams
));
194 return l10n_util::GetStringUTF16(kTextParams
[group_id_
- 1].text_id
);
197 base::string16
ExtensionInstallPromptExperiment::GetOkButtonText() const {
198 DCHECK(group_id_
> 0 && group_id_
- 1 < arraysize(kTextParams
));
199 return l10n_util::GetStringUTF16(kTextParams
[group_id_
- 1].ok_text_id
);
202 base::string16
ExtensionInstallPromptExperiment::GetCancelButtonText() const {
203 DCHECK(group_id_
> 0 && group_id_
- 1 < arraysize(kTextParams
));
204 return l10n_util::GetStringUTF16(kTextParams
[group_id_
- 1].cancel_text_id
);
207 bool ExtensionInstallPromptExperiment::text_only() const {
208 return (flags_
& TEXT_ONLY
) != 0;
211 bool ExtensionInstallPromptExperiment::ShouldHighlightText(
212 const base::string16
& message
) const {
213 return (flags_
& SHOULD_HIGHLIGHT_TEXT
) != 0 && IsImportantWarning(message
);
216 bool ExtensionInstallPromptExperiment::ShouldHighlightBackground(
217 const base::string16
& message
) const {
218 return (flags_
& SHOULD_HIGHLIGHT_BACKGROUND
) != 0 &&
219 ((flags_
& SHOULD_HIGHLIGHT_ALL_PERMISSIONS
) != 0 ||
220 IsImportantWarning(message
));
223 bool ExtensionInstallPromptExperiment::show_details_link() const {
224 return (flags_
& SHOULD_SHOW_DETAILS_LINK
) != 0;
227 bool ExtensionInstallPromptExperiment::show_checkboxes() const {
228 return (flags_
& SHOULD_SHOW_CHECKBOXES
) != 0;
231 bool ExtensionInstallPromptExperiment::should_show_expandable_permission_list()
233 return (flags_
& EXPANDABLE_PERMISSION_LIST
) != 0;
236 bool ExtensionInstallPromptExperiment::should_show_inline_explanations() const {
237 return (flags_
& INLINE_EXPLANATIONS
) != 0;
240 base::string16
ExtensionInstallPromptExperiment::GetInlineExplanation(
241 const base::string16
& message
) const {
242 for (size_t i
= 0; i
< arraysize(kPermissionExplanations
); ++i
) {
243 if (message
== l10n_util::GetStringUTF16(
244 kPermissionExplanations
[i
].warning_msg_id
)) {
245 return l10n_util::GetStringUTF16(
246 kPermissionExplanations
[i
].extra_explanation_id
);
249 return base::string16();