Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / browser / ui / views / conflicting_module_view_win.cc
blob1e3614edd21be724e4a6b8be322a7a440e5abe6b
1 // Copyright (c) 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 "chrome/browser/ui/views/conflicting_module_view_win.h"
7 #include "base/metrics/histogram.h"
8 #include "chrome/browser/chrome_notification_types.h"
9 #include "chrome/browser/enumerate_modules_model_win.h"
10 #include "chrome/browser/profiles/profile.h"
11 #include "chrome/browser/ui/browser.h"
12 #include "chrome/common/pref_names.h"
13 #include "content/public/browser/notification_service.h"
14 #include "content/public/browser/user_metrics.h"
15 #include "grit/chromium_strings.h"
16 #include "grit/generated_resources.h"
17 #include "grit/locale_settings.h"
18 #include "grit/theme_resources.h"
19 #include "ui/base/accessibility/accessible_view_state.h"
20 #include "ui/base/l10n/l10n_util.h"
21 #include "ui/base/resource/resource_bundle.h"
22 #include "ui/views/controls/button/label_button.h"
23 #include "ui/views/controls/image_view.h"
24 #include "ui/views/controls/label.h"
25 #include "ui/views/layout/grid_layout.h"
26 #include "ui/views/layout/layout_constants.h"
27 #include "ui/views/widget/widget.h"
29 using base::UserMetricsAction;
31 namespace {
33 // Layout constants.
34 const int kInsetBottomRight = 13;
35 const int kInsetLeft = 14;
36 const int kInsetTop = 9;
37 const int kHeadlineMessagePadding = 4;
38 const int kMessageBubblePadding = 11;
40 // How often to show this bubble.
41 const int kShowConflictingModuleBubbleMax = 3;
43 } // namespace
45 ////////////////////////////////////////////////////////////////////////////////
46 // ConflictingModuleView
48 ConflictingModuleView::ConflictingModuleView(
49 views::View* anchor_view,
50 Browser* browser,
51 const GURL& help_center_url)
52 : BubbleDelegateView(anchor_view, views::BubbleBorder::TOP_RIGHT),
53 browser_(browser),
54 explanation_(NULL),
55 learn_more_button_(NULL),
56 not_now_button_(NULL),
57 help_center_url_(help_center_url) {
58 set_close_on_deactivate(false);
59 set_move_with_anchor(true);
60 set_close_on_esc(true);
62 // Compensate for built-in vertical padding in the anchor view's image.
63 set_anchor_view_insets(gfx::Insets(5, 0, 5, 0));
65 registrar_.Add(this, chrome::NOTIFICATION_MODULE_INCOMPATIBILITY_BADGE_CHANGE,
66 content::NotificationService::AllSources());
69 // static
70 void ConflictingModuleView::MaybeShow(Browser* browser,
71 views::View* anchor_view) {
72 static bool done_checking = false;
73 if (done_checking)
74 return; // Only show the bubble once per launch.
76 EnumerateModulesModel* model = EnumerateModulesModel::GetInstance();
77 GURL url = model->GetFirstNotableConflict();
78 if (!url.is_valid()) {
79 done_checking = true;
80 return;
83 // A pref that counts how often the Sideload Wipeout bubble has been shown.
84 IntegerPrefMember bubble_shown;
85 bubble_shown.Init(prefs::kModuleConflictBubbleShown,
86 browser->profile()->GetPrefs());
87 if (bubble_shown.GetValue() >= kShowConflictingModuleBubbleMax) {
88 done_checking = true;
89 return;
92 // |anchor_view| must be in a widget (the browser's widget). If not, |browser|
93 // may be destroyed before us, and we'll crash trying to access |browser|
94 // later on. We can't DCHECK |browser|'s widget here as we may be called from
95 // creation of BrowserWindow, which means browser->window() may return NULL.
96 DCHECK(anchor_view);
97 DCHECK(anchor_view->GetWidget());
99 ConflictingModuleView* bubble_delegate =
100 new ConflictingModuleView(anchor_view, browser, url);
101 views::BubbleDelegateView::CreateBubble(bubble_delegate);
102 bubble_delegate->ShowBubble();
104 done_checking = true;
107 ////////////////////////////////////////////////////////////////////////////////
108 // ConflictingModuleView - private.
110 ConflictingModuleView::~ConflictingModuleView() {
113 void ConflictingModuleView::ShowBubble() {
114 StartFade(true);
116 IntegerPrefMember bubble_shown;
117 bubble_shown.Init(
118 prefs::kModuleConflictBubbleShown,
119 browser_->profile()->GetPrefs());
120 bubble_shown.SetValue(bubble_shown.GetValue() + 1);
123 void ConflictingModuleView::DismissBubble() {
124 GetWidget()->Close();
126 content::RecordAction(
127 UserMetricsAction("ConflictingModuleNotificationDismissed"));
130 void ConflictingModuleView::Init() {
131 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
133 views::GridLayout* layout = views::GridLayout::CreatePanel(this);
134 layout->SetInsets(kInsetTop, kInsetLeft,
135 kInsetBottomRight, kInsetBottomRight);
136 SetLayoutManager(layout);
138 views::ImageView* icon = new views::ImageView();
139 icon->SetImage(rb.GetNativeImageNamed(IDR_INPUT_ALERT_MENU).ToImageSkia());
140 gfx::Size icon_size = icon->GetPreferredSize();
142 const int text_column_set_id = 0;
143 views::ColumnSet* upper_columns = layout->AddColumnSet(text_column_set_id);
144 upper_columns->AddColumn(
145 views::GridLayout::LEADING, views::GridLayout::LEADING,
146 0, views::GridLayout::FIXED, icon_size.width(), icon_size.height());
147 upper_columns->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
148 upper_columns->AddColumn(
149 views::GridLayout::LEADING, views::GridLayout::LEADING,
150 0, views::GridLayout::USE_PREF, 0, 0);
152 layout->StartRowWithPadding(
153 0, text_column_set_id, 0, kHeadlineMessagePadding);
154 layout->AddView(icon);
155 explanation_ = new views::Label();
156 explanation_->SetMultiLine(true);
157 explanation_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
158 explanation_->SetText(l10n_util::GetStringUTF16(
159 IDS_OPTIONS_CONFLICTING_MODULE));
160 explanation_->SizeToFit(views::Widget::GetLocalizedContentsWidth(
161 IDS_CONFLICTING_MODULE_BUBBLE_WIDTH_CHARS));
162 layout->AddView(explanation_);
164 const int action_row_column_set_id = 1;
165 views::ColumnSet* bottom_columns =
166 layout->AddColumnSet(action_row_column_set_id);
167 bottom_columns->AddPaddingColumn(1, 0);
168 bottom_columns->AddColumn(views::GridLayout::TRAILING,
169 views::GridLayout::CENTER, 0, views::GridLayout::USE_PREF, 0, 0);
170 bottom_columns->AddPaddingColumn(0, views::kRelatedButtonHSpacing);
171 bottom_columns->AddColumn(views::GridLayout::TRAILING,
172 views::GridLayout::CENTER, 0, views::GridLayout::USE_PREF, 0, 0);
173 layout->AddPaddingRow(0, 7);
175 layout->StartRowWithPadding(0, action_row_column_set_id,
176 0, kMessageBubblePadding);
177 learn_more_button_ = new views::LabelButton(this,
178 l10n_util::GetStringUTF16(IDS_CONFLICTS_LEARN_MORE));
179 learn_more_button_->SetStyle(views::Button::STYLE_BUTTON);
180 layout->AddView(learn_more_button_);
181 not_now_button_ = new views::LabelButton(this,
182 l10n_util::GetStringUTF16(IDS_CONFLICTS_NOT_NOW));
183 not_now_button_->SetStyle(views::Button::STYLE_BUTTON);
184 layout->AddView(not_now_button_);
186 content::RecordAction(
187 UserMetricsAction("ConflictingModuleNotificationShown"));
189 UMA_HISTOGRAM_ENUMERATION("ConflictingModule.UserSelection",
190 EnumerateModulesModel::ACTION_BUBBLE_SHOWN,
191 EnumerateModulesModel::ACTION_BOUNDARY);
194 void ConflictingModuleView::ButtonPressed(views::Button* sender,
195 const ui::Event& event) {
196 if (sender == learn_more_button_) {
197 EnumerateModulesModel::RecordLearnMoreStat(false);
198 browser_->OpenURL(
199 content::OpenURLParams(help_center_url_,
200 content::Referrer(),
201 NEW_FOREGROUND_TAB,
202 content::PAGE_TRANSITION_LINK,
203 false));
205 EnumerateModulesModel* model = EnumerateModulesModel::GetInstance();
206 model->AcknowledgeConflictNotification();
207 DismissBubble();
208 } else if (sender == not_now_button_) {
209 DismissBubble();
213 void ConflictingModuleView::GetAccessibleState(
214 ui::AccessibleViewState* state) {
215 state->role = ui::AccessibilityTypes::ROLE_ALERT;
218 void ConflictingModuleView::ViewHierarchyChanged(
219 const ViewHierarchyChangedDetails& details) {
220 if (details.is_add && details.child == this)
221 NotifyAccessibilityEvent(ui::AccessibilityTypes::EVENT_ALERT, true);
224 void ConflictingModuleView::Observe(
225 int type,
226 const content::NotificationSource& source,
227 const content::NotificationDetails& details) {
228 DCHECK(type == chrome::NOTIFICATION_MODULE_INCOMPATIBILITY_BADGE_CHANGE);
229 EnumerateModulesModel* model = EnumerateModulesModel::GetInstance();
230 if (!model->ShouldShowConflictWarning())
231 GetWidget()->Close();