15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/views/accessibility/invert_bubble_view.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/prefs/pref_service.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser.h"
10a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "chrome/browser/ui/views/frame/browser_view.h"
11a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "chrome/browser/ui/views/toolbar/toolbar_view.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/pref_names.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/page_navigator.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/generated_resources.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/l10n/l10n_util.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/resource/resource_bundle.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/base/window_open_disposition.h"
185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "ui/gfx/sys_color_change_listener.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/bubble/bubble_delegate.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/controls/label.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/controls/link.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/controls/link_listener.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/layout/grid_layout.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/layout/layout_constants.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/widget/widget.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char kHighContrastExtensionUrl[] =
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "https://chrome.google.com/webstore/detail/djcfdncoelnlbldjfhinnjlhdjlikmph";
315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char kDarkThemeSearchUrl[] =
325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "https://chrome.google.com/webstore/search-themes/dark";
335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char kLearnMoreUrl[] =
345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "https://groups.google.com/a/googleproductforums.com/d/topic/chrome/Xrco2HsXS-8/discussion";
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class InvertBubbleView : public views::BubbleDelegateView,
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         public views::LinkListener {
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InvertBubbleView(Browser* browser, views::View* anchor_view);
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~InvertBubbleView();
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Overridden from views::BubbleDelegateView:
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void Init() OVERRIDE;
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Overridden from views::LinkListener:
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void LinkClicked(views::Link* source, int event_flags) OVERRIDE;
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OpenLink(const std::string& url, int event_flags);
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Browser* browser_;
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  views::Link* high_contrast_;
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  views::Link* dark_theme_;
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  views::Link* learn_more_;
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  views::Link* close_;
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(InvertBubbleView);
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)InvertBubbleView::InvertBubbleView(Browser* browser, views::View* anchor_view)
61a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    : views::BubbleDelegateView(anchor_view, views::BubbleBorder::TOP_RIGHT),
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      browser_(browser),
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      high_contrast_(NULL),
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      dark_theme_(NULL),
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      learn_more_(NULL),
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      close_(NULL) {
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)InvertBubbleView::~InvertBubbleView() {
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InvertBubbleView::Init() {
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const gfx::FontList& original_font_list =
755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      rb.GetFontList(ui::ResourceBundle::MediumFont);
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  views::Label* title = new views::Label(
78effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      base::string16(), original_font_list.Derive(2, gfx::Font::BOLD));
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  title->SetMultiLine(true);
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  learn_more_ = new views::Link(l10n_util::GetStringUTF16(IDS_LEARN_MORE));
825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  learn_more_->SetFontList(original_font_list);
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  learn_more_->set_listener(this);
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  high_contrast_ =
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new views::Link(l10n_util::GetStringUTF16(IDS_HIGH_CONTRAST_EXT));
875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  high_contrast_->SetFontList(original_font_list);
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  high_contrast_->set_listener(this);
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
90effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  dark_theme_ = new views::Link(l10n_util::GetStringUTF16(IDS_DARK_THEME));
915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  dark_theme_->SetFontList(original_font_list);
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dark_theme_->set_listener(this);
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  close_ = new views::Link(l10n_util::GetStringUTF16(IDS_CLOSE));
955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  close_->SetFontList(original_font_list);
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  close_->set_listener(this);
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  views::GridLayout* layout = views::GridLayout::CreatePanel(this);
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetLayoutManager(layout);
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  views::ColumnSet* columns = layout->AddColumnSet(0);
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < 4; i++) {
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    columns->AddColumn(views::GridLayout::LEADING,
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       views::GridLayout::LEADING, 0,
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       views::GridLayout::USE_PREF, 0, 0);
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  layout->StartRow(0, 0);
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  layout->AddView(title, 4, 1);
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  layout->StartRowWithPadding(0, 0, 0,
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              views::kRelatedControlSmallVerticalSpacing);
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  layout->AddView(high_contrast_);
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  layout->AddView(dark_theme_);
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  layout->AddView(learn_more_);
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  layout->AddView(close_);
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
117effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // Fit the message to the width of the links in the bubble.
118effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  const gfx::Size size(GetPreferredSize());
119effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  title->SetText(l10n_util::GetStringUTF16(IDS_HIGH_CONTRAST_NOTIFICATION));
120effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  title->SizeToFit(size.width());
121effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Switching to high-contrast mode has a nasty habit of causing Chrome
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // top-level windows to lose focus, so closing the bubble on deactivate
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // makes it disappear before the user has even seen it. This forces the
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // user to close it explicitly, which should be okay because it affects
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // a small minority of users, and only once.
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  set_close_on_deactivate(false);
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InvertBubbleView::LinkClicked(views::Link* source, int event_flags) {
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (source == high_contrast_)
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OpenLink(kHighContrastExtensionUrl, event_flags);
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else if (source == dark_theme_)
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OpenLink(kDarkThemeSearchUrl, event_flags);
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else if (source == learn_more_)
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OpenLink(kLearnMoreUrl, event_flags);
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else if (source == close_)
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GetWidget()->Close();
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InvertBubbleView::OpenLink(const std::string& url, int event_flags) {
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WindowOpenDisposition disposition =
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ui::DispositionFromEventFlags(event_flags);
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::OpenURLParams params(
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GURL(url), content::Referrer(),
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      disposition == CURRENT_TAB ? NEW_FOREGROUND_TAB : disposition,
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content::PAGE_TRANSITION_LINK, false);
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  browser_->OpenURL(params);
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace chrome {
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
157a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void MaybeShowInvertBubbleView(BrowserView* browser_view) {
158a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  Browser* browser = browser_view->browser();
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PrefService* pref_service = browser->profile()->GetPrefs();
160a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  views::View* anchor = browser_view->toolbar()->app_menu();
161a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (gfx::IsInvertedColorScheme() && anchor && anchor->GetWidget() &&
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !pref_service->GetBoolean(prefs::kInvertNotificationShown)) {
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pref_service->SetBoolean(prefs::kInvertNotificationShown, true);
164a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    InvertBubbleView* delegate = new InvertBubbleView(browser, anchor);
165a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    views::BubbleDelegateView::CreateBubble(delegate)->Show();
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace chrome
170