Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(372)

Side by Side Diff: chrome/browser/chromeos/notifications/balloon_view.cc

Issue 9664072: Removing WmIpc and related files from ChromeOS (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Copyright Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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/chromeos/notifications/balloon_view.h"
6
7 #include <algorithm>
8 #include <vector>
9
10 #include "base/bind.h"
11 #include "base/message_loop.h"
12 #include "base/utf_string_conversions.h"
13 #include "chrome/browser/chromeos/notifications/balloon_view_host.h"
14 #include "chrome/browser/chromeos/notifications/notification_panel.h"
15 #include "chrome/browser/notifications/balloon.h"
16 #include "chrome/browser/notifications/desktop_notification_service.h"
17 #include "chrome/browser/notifications/desktop_notification_service_factory.h"
18 #include "chrome/browser/notifications/notification.h"
19 #include "chrome/browser/profiles/profile.h"
20 #include "chrome/browser/ui/views/notifications/balloon_view_host.h"
21 #include "chrome/common/chrome_notification_types.h"
22 #include "content/public/browser/notification_details.h"
23 #include "content/public/browser/notification_source.h"
24 #include "content/public/browser/render_view_host.h"
25 #include "content/public/browser/render_widget_host_view.h"
26 #include "content/public/browser/web_contents.h"
27 #include "grit/generated_resources.h"
28 #include "grit/theme_resources.h"
29 #include "grit/theme_resources_standard.h"
30 #include "ui/base/l10n/l10n_util.h"
31 #include "ui/base/models/simple_menu_model.h"
32 #include "ui/base/resource/resource_bundle.h"
33 #include "ui/views/background.h"
34 #include "ui/views/controls/button/button.h"
35 #include "ui/views/controls/button/image_button.h"
36 #include "ui/views/controls/button/menu_button.h"
37 #include "ui/views/controls/button/menu_button_listener.h"
38 #include "ui/views/controls/label.h"
39 #include "ui/views/controls/menu/menu_item_view.h"
40 #include "ui/views/controls/menu/menu_model_adapter.h"
41 #include "ui/views/controls/menu/menu_runner.h"
42 #include "ui/views/widget/widget.h"
43
44 using content::RenderWidgetHostView;
45
46 namespace {
47 // Menu commands
48 const int kNoopCommand = 0;
49 const int kRevokePermissionCommand = 1;
50
51 // Vertical margin between close button and menu button.
52 const int kControlButtonsMargin = 6;
53
54 // Top, Right margin for notification control view.
55 const int kControlViewTopMargin = 4;
56 const int kControlViewRightMargin = 6;
57 } // namespace
58
59 namespace chromeos {
60
61 // NotificationControlView has close and menu buttons and
62 // overlays on top of renderer view.
63 class NotificationControlView : public views::View,
64 public views::MenuButtonListener,
65 public ui::SimpleMenuModel::Delegate,
66 public views::ButtonListener {
67 public:
68 explicit NotificationControlView(BalloonViewImpl* view)
69 : balloon_view_(view),
70 close_button_(NULL),
71 options_menu_contents_(NULL),
72 options_menu_button_(NULL) {
73 // TODO(oshima): make background transparent.
74 set_background(views::Background::CreateSolidBackground(SK_ColorWHITE));
75
76 ResourceBundle& rb = ResourceBundle::GetSharedInstance();
77
78 SkBitmap* close_button_n = rb.GetBitmapNamed(IDR_TAB_CLOSE);
79 SkBitmap* close_button_m = rb.GetBitmapNamed(IDR_TAB_CLOSE_MASK);
80 SkBitmap* close_button_h = rb.GetBitmapNamed(IDR_TAB_CLOSE_H);
81 SkBitmap* close_button_p = rb.GetBitmapNamed(IDR_TAB_CLOSE_P);
82
83 close_button_ = new views::ImageButton(this);
84 close_button_->SetImage(views::CustomButton::BS_NORMAL, close_button_n);
85 close_button_->SetImage(views::CustomButton::BS_HOT, close_button_h);
86 close_button_->SetImage(views::CustomButton::BS_PUSHED, close_button_p);
87 close_button_->SetBackground(
88 SK_ColorBLACK, close_button_n, close_button_m);
89
90 AddChildView(close_button_);
91
92 options_menu_button_ = new views::MenuButton(
93 NULL, string16(), this, false);
94 options_menu_button_->SetFont(rb.GetFont(ResourceBundle::SmallFont));
95 options_menu_button_->SetIcon(*rb.GetBitmapNamed(IDR_NOTIFICATION_MENU));
96 options_menu_button_->set_border(NULL);
97
98 options_menu_button_->set_icon_placement(views::TextButton::ICON_ON_RIGHT);
99 AddChildView(options_menu_button_);
100
101 // The control view will never be resized, so just layout once.
102 gfx::Size options_size = options_menu_button_->GetPreferredSize();
103 gfx::Size button_size = close_button_->GetPreferredSize();
104
105 int height = std::max(options_size.height(), button_size.height());
106 options_menu_button_->SetBounds(
107 0, (height - options_size.height()) / 2,
108 options_size.width(), options_size.height());
109
110 close_button_->SetBounds(
111 options_size.width() + kControlButtonsMargin,
112 (height - button_size.height()) / 2,
113 button_size.width(), button_size.height());
114
115 SizeToPreferredSize();
116 }
117
118 virtual gfx::Size GetPreferredSize() {
119 gfx::Rect total_bounds =
120 close_button_->bounds().Union(options_menu_button_->bounds());
121 return total_bounds.size();
122 }
123
124 // Overridden from views::MenuButtonListener:
125 virtual void OnMenuButtonClicked(views::View* source,
126 const gfx::Point& point) OVERRIDE {
127 CreateOptionsMenu();
128
129 views::MenuModelAdapter menu_model_adapter(options_menu_contents_.get());
130 menu_runner_.reset(new views::MenuRunner(menu_model_adapter.CreateMenu()));
131
132 gfx::Point screen_location;
133 views::View::ConvertPointToScreen(options_menu_button_, &screen_location);
134 if (menu_runner_->RunMenuAt(
135 source->GetWidget()->GetTopLevelWidget(), options_menu_button_,
136 gfx::Rect(screen_location, options_menu_button_->size()),
137 views::MenuItemView::TOPRIGHT, views::MenuRunner::HAS_MNEMONICS) ==
138 views::MenuRunner::MENU_DELETED)
139 return;
140 }
141
142 // views::ButtonListener implements.
143 virtual void ButtonPressed(views::Button* sender, const views::Event&) {
144 balloon_view_->Close(true);
145 }
146
147 // ui::SimpleMenuModel::Delegate impglements.
148 virtual bool IsCommandIdChecked(int /* command_id */) const {
149 // Nothing in the menu is checked.
150 return false;
151 }
152
153 virtual bool IsCommandIdEnabled(int /* command_id */) const {
154 // All the menu options are always enabled.
155 return true;
156 }
157
158 virtual bool GetAcceleratorForCommandId(
159 int /* command_id */, ui::Accelerator* /* accelerator */) {
160 // Currently no accelerators.
161 return false;
162 }
163
164 virtual void ExecuteCommand(int command_id) {
165 switch (command_id) {
166 case kRevokePermissionCommand:
167 balloon_view_->DenyPermission();
168 default:
169 NOTIMPLEMENTED();
170 }
171 }
172
173 private:
174 void CreateOptionsMenu() {
175 if (options_menu_contents_.get())
176 return;
177 const string16 source_label_text = l10n_util::GetStringFUTF16(
178 IDS_NOTIFICATION_BALLOON_SOURCE_LABEL,
179 balloon_view_->balloon_->notification().display_source());
180 const string16 label_text = l10n_util::GetStringFUTF16(
181 IDS_NOTIFICATION_BALLOON_REVOKE_MESSAGE,
182 balloon_view_->balloon_->notification().display_source());
183
184 options_menu_contents_.reset(new ui::SimpleMenuModel(this));
185 // TODO(oshima): Showing the source info in the menu for now.
186 // Figure out where to show the source info.
187 options_menu_contents_->AddItem(kNoopCommand, source_label_text);
188 options_menu_contents_->AddItem(kRevokePermissionCommand, label_text);
189 }
190
191 BalloonViewImpl* balloon_view_;
192
193 views::ImageButton* close_button_;
194
195 // The options menu.
196 scoped_ptr<ui::SimpleMenuModel> options_menu_contents_;
197 scoped_ptr<views::MenuRunner> menu_runner_;
198 views::MenuButton* options_menu_button_;
199
200 DISALLOW_COPY_AND_ASSIGN(NotificationControlView);
201 };
202
203 BalloonViewImpl::BalloonViewImpl(bool sticky, bool controls, bool web_ui)
204 : balloon_(NULL),
205 html_contents_(NULL),
206 stale_(false),
207 sticky_(sticky),
208 controls_(controls),
209 closed_(false),
210 web_ui_(web_ui) {
211 // This object is not to be deleted by the views hierarchy,
212 // as it is owned by the balloon.
213 set_parent_owned(false);
214 }
215
216 BalloonViewImpl::~BalloonViewImpl() {
217 if (control_view_host_.get()) {
218 control_view_host_->CloseNow();
219 }
220 if (html_contents_.get()) {
221 html_contents_->Shutdown();
222 }
223 }
224
225 ////////////////////////////////////////////////////////////////////////////////
226 // BallonViewImpl, BalloonView implementation.
227
228 void BalloonViewImpl::Show(Balloon* balloon) {
229 balloon_ = balloon;
230 html_contents_.reset(new BalloonViewHost(balloon));
231 if (web_ui_)
232 html_contents_->EnableWebUI();
233 AddChildView(html_contents_->view());
234 notification_registrar_.Add(this,
235 chrome::NOTIFICATION_NOTIFY_BALLOON_DISCONNECTED,
236 content::Source<Balloon>(balloon));
237 }
238
239 void BalloonViewImpl::Update() {
240 stale_ = false;
241 if (!html_contents_->web_contents())
242 return;
243 html_contents_->web_contents()->GetController().LoadURL(
244 balloon_->notification().content_url(), content::Referrer(),
245 content::PAGE_TRANSITION_LINK, std::string());
246 }
247
248 void BalloonViewImpl::Close(bool by_user) {
249 closed_ = true;
250 MessageLoop::current()->PostTask(
251 FROM_HERE,
252 base::Bind(&BalloonViewImpl::DelayedClose, AsWeakPtr(), by_user));
253 }
254
255 gfx::Size BalloonViewImpl::GetSize() const {
256 // Not used. The layout is managed by the Panel.
257 return gfx::Size(0, 0);
258 }
259
260 BalloonHost* BalloonViewImpl::GetHost() const {
261 return html_contents_.get();
262 }
263
264 void BalloonViewImpl::RepositionToBalloon() {
265 // Not used. The layout is managed by the Panel.
266 }
267
268 ////////////////////////////////////////////////////////////////////////////////
269 // views::View interface overrides.
270
271 void BalloonViewImpl::Layout() {
272 gfx::Size size = balloon_->content_size();
273
274 SetBounds(x(), y(), size.width(), size.height());
275
276 html_contents_->view()->SetBounds(0, 0, size.width(), size.height());
277 if (html_contents_->web_contents()) {
278 RenderWidgetHostView* view =
279 html_contents_->web_contents()->GetRenderViewHost()->GetView();
280 if (view)
281 view->SetSize(size);
282 }
283 }
284
285 void BalloonViewImpl::ViewHierarchyChanged(
286 bool is_add, View* parent, View* child) {
287 if (is_add && GetWidget() && !control_view_host_.get() && controls_) {
288 control_view_host_.reset(new views::Widget);
289 views::Widget::InitParams params(
290 views::Widget::InitParams::TYPE_CONTROL);
291 params.double_buffer = true;
292 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
293 params.parent = GetParentNativeView();
294 control_view_host_->Init(params);
295 NotificationControlView* control = new NotificationControlView(this);
296 control_view_host_->SetContentsView(control);
297 }
298 if (!is_add && this == child && control_view_host_.get() && controls_)
299 control_view_host_.release()->CloseNow();
300 }
301
302 gfx::Size BalloonViewImpl::GetPreferredSize() {
303 return gfx::Size(1000, 1000);
304 }
305
306 ////////////////////////////////////////////////////////////////////////////////
307 // content::NotificationObserver overrides.
308
309 void BalloonViewImpl::Observe(int type,
310 const content::NotificationSource& source,
311 const content::NotificationDetails& details) {
312 if (type != chrome::NOTIFICATION_NOTIFY_BALLOON_DISCONNECTED) {
313 NOTREACHED();
314 return;
315 }
316
317 // If the renderer process attached to this balloon is disconnected
318 // (e.g., because of a crash), we want to close the balloon.
319 notification_registrar_.Remove(this,
320 chrome::NOTIFICATION_NOTIFY_BALLOON_DISCONNECTED,
321 content::Source<Balloon>(balloon_));
322 Close(false);
323 }
324
325 ////////////////////////////////////////////////////////////////////////////////
326 // BalloonViewImpl public.
327
328 bool BalloonViewImpl::IsFor(const Notification& notification) const {
329 return balloon_->notification().notification_id() ==
330 notification.notification_id();
331 }
332
333 void BalloonViewImpl::Activated() {
334 if (!control_view_host_.get())
335 return;
336
337 // Get the size of Control View.
338 gfx::Size size =
339 control_view_host_->GetRootView()->child_at(0)->GetPreferredSize();
340 control_view_host_->Show();
341 control_view_host_->SetBounds(
342 gfx::Rect(width() - size.width() - kControlViewRightMargin,
343 kControlViewTopMargin,
344 size.width(), size.height()));
345 }
346
347 void BalloonViewImpl::Deactivated() {
348 if (control_view_host_.get()) {
349 control_view_host_->Hide();
350 }
351 }
352
353 ////////////////////////////////////////////////////////////////////////////////
354 // BalloonViewImpl private.
355
356 void BalloonViewImpl::DelayedClose(bool by_user) {
357 html_contents_->Shutdown();
358 html_contents_.reset();
359 balloon_->OnClose(by_user);
360 }
361
362 void BalloonViewImpl::DenyPermission() {
363 DesktopNotificationService* service =
364 DesktopNotificationServiceFactory::GetForProfile(balloon_->profile());
365 service->DenyPermission(balloon_->notification().origin_url());
366 }
367
368 gfx::NativeView BalloonViewImpl::GetParentNativeView() {
369 RenderWidgetHostView* view =
370 html_contents_->web_contents()->GetRenderViewHost()->GetView();
371 DCHECK(view);
372 return view->GetNativeView();
373 }
374
375 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698