OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/ui/views/extensions/extension_installed_bubble.h" | 5 #include "chrome/browser/ui/views/extensions/extension_installed_bubble.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <string> | 8 #include <string> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 11 matching lines...) Expand all Loading... |
22 #include "chrome/browser/ui/views/toolbar_view.h" | 22 #include "chrome/browser/ui/views/toolbar_view.h" |
23 #include "chrome/common/chrome_notification_types.h" | 23 #include "chrome/common/chrome_notification_types.h" |
24 #include "chrome/common/extensions/extension.h" | 24 #include "chrome/common/extensions/extension.h" |
25 #include "chrome/common/extensions/extension_action.h" | 25 #include "chrome/common/extensions/extension_action.h" |
26 #include "content/public/browser/notification_details.h" | 26 #include "content/public/browser/notification_details.h" |
27 #include "content/public/browser/notification_source.h" | 27 #include "content/public/browser/notification_source.h" |
28 #include "grit/generated_resources.h" | 28 #include "grit/generated_resources.h" |
29 #include "grit/theme_resources_standard.h" | 29 #include "grit/theme_resources_standard.h" |
30 #include "ui/base/l10n/l10n_util.h" | 30 #include "ui/base/l10n/l10n_util.h" |
31 #include "ui/base/resource/resource_bundle.h" | 31 #include "ui/base/resource/resource_bundle.h" |
| 32 #include "ui/views/layout/fill_layout.h" |
32 #include "ui/views/layout/layout_constants.h" | 33 #include "ui/views/layout/layout_constants.h" |
33 #include "views/controls/button/image_button.h" | 34 #include "views/controls/button/image_button.h" |
34 #include "views/controls/image_view.h" | 35 #include "views/controls/image_view.h" |
35 #include "views/controls/label.h" | 36 #include "views/controls/label.h" |
36 #include "views/controls/link.h" | 37 #include "views/controls/link.h" |
37 #include "views/controls/link_listener.h" | 38 #include "views/controls/link_listener.h" |
38 #include "views/view.h" | 39 #include "views/view.h" |
39 | 40 |
40 namespace { | 41 namespace { |
41 | 42 |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
83 // InstalledBubbleContent is the content view which is placed in the | 84 // InstalledBubbleContent is the content view which is placed in the |
84 // ExtensionInstalledBubble. It displays the install icon and explanatory | 85 // ExtensionInstalledBubble. It displays the install icon and explanatory |
85 // text about the installed extension. | 86 // text about the installed extension. |
86 class InstalledBubbleContent : public views::View, | 87 class InstalledBubbleContent : public views::View, |
87 public views::ButtonListener, | 88 public views::ButtonListener, |
88 public views::LinkListener { | 89 public views::LinkListener { |
89 public: | 90 public: |
90 InstalledBubbleContent(Browser* browser, | 91 InstalledBubbleContent(Browser* browser, |
91 const Extension* extension, | 92 const Extension* extension, |
92 ExtensionInstalledBubble::BubbleType type, | 93 ExtensionInstalledBubble::BubbleType type, |
93 SkBitmap* icon) | 94 SkBitmap* icon, |
| 95 ExtensionInstalledBubble* bubble) |
94 : browser_(browser), | 96 : browser_(browser), |
95 extension_id_(extension->id()), | 97 extension_id_(extension->id()), |
96 bubble_(NULL), | 98 bubble_(bubble), |
97 type_(type), | 99 type_(type), |
98 info_(NULL) { | 100 info_(NULL) { |
99 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); | 101 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); |
100 const gfx::Font& font = rb.GetFont(ResourceBundle::BaseFont); | 102 const gfx::Font& font = rb.GetFont(ResourceBundle::BaseFont); |
101 | 103 |
102 // Scale down to 43x43, but allow smaller icons (don't scale up). | 104 // Scale down to 43x43, but allow smaller icons (don't scale up). |
103 gfx::Size size(icon->width(), icon->height()); | 105 gfx::Size size(icon->width(), icon->height()); |
104 if (size.width() > kIconSize || size.height() > kIconSize) | 106 if (size.width() > kIconSize || size.height() > kIconSize) |
105 size = gfx::Size(kIconSize, kIconSize); | 107 size = gfx::Size(kIconSize, kIconSize); |
106 icon_ = new views::ImageView(); | 108 icon_ = new views::ImageView(); |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
165 close_button_ = new views::ImageButton(this); | 167 close_button_ = new views::ImageButton(this); |
166 close_button_->SetImage(views::CustomButton::BS_NORMAL, | 168 close_button_->SetImage(views::CustomButton::BS_NORMAL, |
167 rb.GetBitmapNamed(IDR_CLOSE_BAR)); | 169 rb.GetBitmapNamed(IDR_CLOSE_BAR)); |
168 close_button_->SetImage(views::CustomButton::BS_HOT, | 170 close_button_->SetImage(views::CustomButton::BS_HOT, |
169 rb.GetBitmapNamed(IDR_CLOSE_BAR_H)); | 171 rb.GetBitmapNamed(IDR_CLOSE_BAR_H)); |
170 close_button_->SetImage(views::CustomButton::BS_PUSHED, | 172 close_button_->SetImage(views::CustomButton::BS_PUSHED, |
171 rb.GetBitmapNamed(IDR_CLOSE_BAR_P)); | 173 rb.GetBitmapNamed(IDR_CLOSE_BAR_P)); |
172 AddChildView(close_button_); | 174 AddChildView(close_button_); |
173 } | 175 } |
174 | 176 |
175 void set_bubble(Bubble* bubble) { bubble_ = bubble; } | 177 virtual void ButtonPressed(views::Button* sender, const views::Event& event) { |
176 | 178 if (sender == close_button_) |
177 virtual void ButtonPressed( | 179 bubble_->StartFade(false); |
178 views::Button* sender, | 180 else |
179 const views::Event& event) { | |
180 if (sender == close_button_) { | |
181 bubble_->set_fade_away_on_close(true); | |
182 GetWidget()->Close(); | |
183 } else { | |
184 NOTREACHED() << "Unknown view"; | 181 NOTREACHED() << "Unknown view"; |
185 } | |
186 } | 182 } |
187 | 183 |
188 // Implements the views::LinkListener interface. | 184 // Implements the views::LinkListener interface. |
189 virtual void LinkClicked(views::Link* source, int event_flags) OVERRIDE { | 185 virtual void LinkClicked(views::Link* source, int event_flags) OVERRIDE { |
190 GetWidget()->Close(); | 186 GetWidget()->Close(); |
191 ExtensionInstallUI::OpenAppInstalledNTP(browser_, extension_id_); | 187 ExtensionInstallUI::OpenAppInstalledNTP(browser_, extension_id_); |
192 } | 188 } |
193 | 189 |
194 private: | 190 private: |
195 virtual gfx::Size GetPreferredSize() { | 191 virtual gfx::Size GetPreferredSize() { |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
251 // title text and bubble arrow. | 247 // title text and bubble arrow. |
252 close_button_->SetBounds(x - 1, y - 1, sz.width(), sz.height()); | 248 close_button_->SetBounds(x - 1, y - 1, sz.width(), sz.height()); |
253 } | 249 } |
254 | 250 |
255 // The browser we're associated with. | 251 // The browser we're associated with. |
256 Browser* browser_; | 252 Browser* browser_; |
257 | 253 |
258 // The id of the extension just installed. | 254 // The id of the extension just installed. |
259 const std::string extension_id_; | 255 const std::string extension_id_; |
260 | 256 |
261 // The Bubble showing us. | 257 // The ExtensionInstalledBubble showing us. |
262 Bubble* bubble_; | 258 ExtensionInstalledBubble* bubble_; |
263 | 259 |
264 ExtensionInstalledBubble::BubbleType type_; | 260 ExtensionInstalledBubble::BubbleType type_; |
265 views::ImageView* icon_; | 261 views::ImageView* icon_; |
266 views::Label* heading_; | 262 views::Label* heading_; |
267 views::Label* info_; | 263 views::Label* info_; |
268 views::Label* manage_; | 264 views::Label* manage_; |
269 views::ImageButton* close_button_; | 265 views::ImageButton* close_button_; |
270 | 266 |
271 DISALLOW_COPY_AND_ASSIGN(InstalledBubbleContent); | 267 DISALLOW_COPY_AND_ASSIGN(InstalledBubbleContent); |
272 }; | 268 }; |
273 | 269 |
274 void ExtensionInstalledBubble::Show(const Extension* extension, | 270 void ExtensionInstalledBubble::Show(const Extension* extension, |
275 Browser *browser, | 271 Browser *browser, |
276 const SkBitmap& icon) { | 272 const SkBitmap& icon) { |
277 new ExtensionInstalledBubble(extension, browser, icon); | 273 new ExtensionInstalledBubble(extension, browser, icon); |
278 } | 274 } |
279 | 275 |
280 ExtensionInstalledBubble::ExtensionInstalledBubble(const Extension* extension, | 276 ExtensionInstalledBubble::ExtensionInstalledBubble(const Extension* extension, |
281 Browser *browser, | 277 Browser *browser, |
282 const SkBitmap& icon) | 278 const SkBitmap& icon) |
283 : extension_(extension), | 279 : extension_(extension), |
284 browser_(browser), | 280 browser_(browser), |
285 icon_(icon), | 281 icon_(icon), |
286 animation_wait_retries_(0) { | 282 animation_wait_retries_(0) { |
287 AddRef(); // Balanced in BubbleClosing. | |
288 | |
289 if (extension->is_app()) { | 283 if (extension->is_app()) { |
290 type_ = APP; | 284 type_ = APP; |
291 } else if (!extension_->omnibox_keyword().empty()) { | 285 } else if (!extension_->omnibox_keyword().empty()) { |
292 type_ = OMNIBOX_KEYWORD; | 286 type_ = OMNIBOX_KEYWORD; |
293 } else if (extension_->browser_action()) { | 287 } else if (extension_->browser_action()) { |
294 type_ = BROWSER_ACTION; | 288 type_ = BROWSER_ACTION; |
295 } else if (extension->page_action() && | 289 } else if (extension->page_action() && |
296 !extension->page_action()->default_icon_path().empty()) { | 290 !extension->page_action()->default_icon_path().empty()) { |
297 type_ = PAGE_ACTION; | 291 type_ = PAGE_ACTION; |
298 } else { | 292 } else { |
(...skipping 18 matching lines...) Expand all Loading... |
317 const content::NotificationSource& source, | 311 const content::NotificationSource& source, |
318 const content::NotificationDetails& details) { | 312 const content::NotificationDetails& details) { |
319 if (type == chrome::NOTIFICATION_EXTENSION_LOADED) { | 313 if (type == chrome::NOTIFICATION_EXTENSION_LOADED) { |
320 const Extension* extension = | 314 const Extension* extension = |
321 content::Details<const Extension>(details).ptr(); | 315 content::Details<const Extension>(details).ptr(); |
322 if (extension == extension_) { | 316 if (extension == extension_) { |
323 animation_wait_retries_ = 0; | 317 animation_wait_retries_ = 0; |
324 // PostTask to ourself to allow all EXTENSION_LOADED Observers to run. | 318 // PostTask to ourself to allow all EXTENSION_LOADED Observers to run. |
325 MessageLoopForUI::current()->PostTask( | 319 MessageLoopForUI::current()->PostTask( |
326 FROM_HERE, | 320 FROM_HERE, |
327 base::Bind(&ExtensionInstalledBubble::ShowInternal, this)); | 321 base::Bind(&ExtensionInstalledBubble::ShowInternal, |
| 322 base::Unretained(this))); |
328 } | 323 } |
329 } else if (type == chrome::NOTIFICATION_EXTENSION_UNLOADED) { | 324 } else if (type == chrome::NOTIFICATION_EXTENSION_UNLOADED) { |
330 const Extension* extension = | 325 const Extension* extension = |
331 content::Details<UnloadedExtensionInfo>(details)->extension; | 326 content::Details<UnloadedExtensionInfo>(details)->extension; |
332 if (extension == extension_) | 327 if (extension == extension_) |
333 extension_ = NULL; | 328 extension_ = NULL; |
334 } else { | 329 } else { |
335 NOTREACHED() << L"Received unexpected notification"; | 330 NOTREACHED() << L"Received unexpected notification"; |
336 } | 331 } |
337 } | 332 } |
338 | 333 |
339 void ExtensionInstalledBubble::ShowInternal() { | 334 void ExtensionInstalledBubble::ShowInternal() { |
340 BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser_); | 335 BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser_); |
341 | 336 |
342 const views::View* reference_view = NULL; | 337 views::View* reference_view = NULL; |
343 if (type_ == APP) { | 338 if (type_ == APP) { |
344 if (browser_view->IsTabStripVisible()) { | 339 if (browser_view->IsTabStripVisible()) { |
345 AbstractTabStripView* tabstrip = browser_view->tabstrip(); | 340 AbstractTabStripView* tabstrip = browser_view->tabstrip(); |
346 views::View* ntp_button = tabstrip->GetNewTabButton(); | 341 views::View* ntp_button = tabstrip->GetNewTabButton(); |
347 if (ntp_button && ntp_button->IsVisibleInRootView()) { | 342 if (ntp_button && ntp_button->IsVisibleInRootView()) { |
348 reference_view = ntp_button; | 343 reference_view = ntp_button; |
349 } else { | 344 } else { |
350 // Just have the bubble point at the tab strip. | 345 // Just have the bubble point at the tab strip. |
351 reference_view = tabstrip; | 346 reference_view = tabstrip; |
352 } | 347 } |
353 } | 348 } |
354 } else if (type_ == BROWSER_ACTION) { | 349 } else if (type_ == BROWSER_ACTION) { |
355 BrowserActionsContainer* container = | 350 BrowserActionsContainer* container = |
356 browser_view->GetToolbarView()->browser_actions(); | 351 browser_view->GetToolbarView()->browser_actions(); |
357 if (container->animating() && | 352 if (container->animating() && |
358 animation_wait_retries_++ < kAnimationWaitMaxRetry) { | 353 animation_wait_retries_++ < kAnimationWaitMaxRetry) { |
359 // We don't know where the view will be until the container has stopped | 354 // We don't know where the view will be until the container has stopped |
360 // animating, so check back in a little while. | 355 // animating, so check back in a little while. |
361 MessageLoopForUI::current()->PostDelayedTask( | 356 MessageLoopForUI::current()->PostDelayedTask( |
362 FROM_HERE, | 357 FROM_HERE, |
363 base::Bind(&ExtensionInstalledBubble::ShowInternal, this), | 358 base::Bind(&ExtensionInstalledBubble::ShowInternal, |
| 359 base::Unretained(this)), |
364 kAnimationWaitTime); | 360 kAnimationWaitTime); |
365 return; | 361 return; |
366 } | 362 } |
367 reference_view = container->GetBrowserActionView( | 363 reference_view = container->GetBrowserActionView( |
368 extension_->browser_action()); | 364 extension_->browser_action()); |
369 // If the view is not visible then it is in the chevron, so point the | 365 // If the view is not visible then it is in the chevron, so point the |
370 // install bubble to the chevron instead. If this is an incognito window, | 366 // install bubble to the chevron instead. If this is an incognito window, |
371 // both could be invisible. | 367 // both could be invisible. |
372 if (!reference_view || !reference_view->IsVisible()) { | 368 if (!reference_view || !reference_view->IsVisible()) { |
373 reference_view = container->chevron(); | 369 reference_view = container->chevron(); |
374 if (!reference_view || !reference_view->IsVisible()) | 370 if (!reference_view || !reference_view->IsVisible()) |
375 reference_view = NULL; // fall back to app menu below. | 371 reference_view = NULL; // fall back to app menu below. |
376 } | 372 } |
377 } else if (type_ == PAGE_ACTION) { | 373 } else if (type_ == PAGE_ACTION) { |
378 LocationBarView* location_bar_view = browser_view->GetLocationBarView(); | 374 LocationBarView* location_bar_view = browser_view->GetLocationBarView(); |
379 location_bar_view->SetPreviewEnabledPageAction(extension_->page_action(), | 375 location_bar_view->SetPreviewEnabledPageAction(extension_->page_action(), |
380 true); // preview_enabled | 376 true); // preview_enabled |
381 reference_view = location_bar_view->GetPageActionView( | 377 reference_view = location_bar_view->GetPageActionView( |
382 extension_->page_action()); | 378 extension_->page_action()); |
383 DCHECK(reference_view); | 379 DCHECK(reference_view); |
384 } else if (type_ == OMNIBOX_KEYWORD) { | 380 } else if (type_ == OMNIBOX_KEYWORD) { |
385 LocationBarView* location_bar_view = browser_view->GetLocationBarView(); | 381 LocationBarView* location_bar_view = browser_view->GetLocationBarView(); |
386 reference_view = location_bar_view; | 382 reference_view = location_bar_view; |
387 DCHECK(reference_view); | 383 DCHECK(reference_view); |
388 } | 384 } |
389 | 385 |
390 // Default case. | 386 // Default case. |
391 if (reference_view == NULL) | 387 if (reference_view == NULL) |
392 reference_view = browser_view->GetToolbarView()->app_menu(); | 388 reference_view = browser_view->GetToolbarView()->app_menu(); |
| 389 set_anchor_view(reference_view); |
393 | 390 |
394 gfx::Point origin; | 391 SetLayoutManager(new views::FillLayout()); |
395 views::View::ConvertPointToScreen(reference_view, &origin); | 392 AddChildView( |
396 gfx::Rect bounds = reference_view->bounds(); | 393 new InstalledBubbleContent(browser_, extension_, type_, &icon_, this)); |
397 bounds.set_origin(origin); | 394 views::BubbleDelegateView::CreateBubble(this); |
398 views::BubbleBorder::ArrowLocation arrow_location = | 395 StartFade(true); |
399 views::BubbleBorder::TOP_RIGHT; | 396 } |
400 | 397 |
| 398 gfx::Point ExtensionInstalledBubble::GetAnchorPoint() { |
401 // For omnibox keyword bubbles, move the arrow to point to the left edge | 399 // For omnibox keyword bubbles, move the arrow to point to the left edge |
402 // of the omnibox, just to the right of the icon. | 400 // of the omnibox, just to the right of the icon. |
403 if (type_ == OMNIBOX_KEYWORD) { | 401 if (type_ == OMNIBOX_KEYWORD) { |
404 bounds.set_origin( | 402 LocationBarView* location_bar_view = |
405 browser_view->GetLocationBarView()->GetLocationEntryOrigin()); | 403 BrowserView::GetBrowserViewForBrowser(browser_)->GetLocationBarView(); |
406 bounds.set_width(0); | 404 return location_bar_view->GetLocationEntryOrigin().Add( |
407 arrow_location = views::BubbleBorder::TOP_LEFT; | 405 gfx::Point(0, location_bar_view->location_entry_view()->height())); |
408 } | 406 } |
409 | 407 return views::BubbleDelegateView::GetAnchorPoint(); |
410 bubble_content_ = new InstalledBubbleContent( | |
411 browser_, extension_, type_, &icon_); | |
412 Bubble* bubble = Bubble::Show(browser_view->GetWidget(), bounds, | |
413 arrow_location, | |
414 views::BubbleBorder::ALIGN_ARROW_TO_MID_ANCHOR, | |
415 bubble_content_, this); | |
416 bubble_content_->set_bubble(bubble); | |
417 } | 408 } |
418 | 409 |
419 // BubbleDelegate | 410 views::BubbleBorder::ArrowLocation |
420 void ExtensionInstalledBubble::BubbleClosing(Bubble* bubble, | 411 ExtensionInstalledBubble::GetArrowLocation() const { |
421 bool closed_by_escape) { | 412 return type_ == OMNIBOX_KEYWORD ? views::BubbleBorder::TOP_LEFT : |
| 413 views::BubbleBorder::TOP_RIGHT; |
| 414 } |
| 415 |
| 416 void ExtensionInstalledBubble::WindowClosing() { |
422 if (extension_ && type_ == PAGE_ACTION) { | 417 if (extension_ && type_ == PAGE_ACTION) { |
423 BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser_); | 418 BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser_); |
424 browser_view->GetLocationBarView()->SetPreviewEnabledPageAction( | 419 browser_view->GetLocationBarView()->SetPreviewEnabledPageAction( |
425 extension_->page_action(), | 420 extension_->page_action(), |
426 false); // preview_enabled | 421 false); // preview_enabled |
427 } | 422 } |
428 | |
429 Release(); // Balanced in ctor. | |
430 } | 423 } |
431 | |
432 bool ExtensionInstalledBubble::CloseOnEscape() { | |
433 return true; | |
434 } | |
435 | |
436 bool ExtensionInstalledBubble::FadeInOnShow() { | |
437 return true; | |
438 } | |
OLD | NEW |