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"
136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "chrome/grit/generated_resources.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/page_navigator.h"
151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "grit/components_strings.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/l10n/l10n_util.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/resource/resource_bundle.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/base/window_open_disposition.h"
195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "ui/gfx/sys_color_change_listener.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/bubble/bubble_delegate.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/controls/label.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/controls/link.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/controls/link_listener.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/layout/grid_layout.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/layout/layout_constants.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/widget/widget.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char kHighContrastExtensionUrl[] =
315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "https://chrome.google.com/webstore/detail/djcfdncoelnlbldjfhinnjlhdjlikmph";
325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char kDarkThemeSearchUrl[] =
335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "https://chrome.google.com/webstore/search-themes/dark";
345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char kLearnMoreUrl[] =
355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "https://groups.google.com/a/googleproductforums.com/d/topic/chrome/Xrco2HsXS-8/discussion";
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class InvertBubbleView : public views::BubbleDelegateView,
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         public views::LinkListener {
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InvertBubbleView(Browser* browser, views::View* anchor_view);
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~InvertBubbleView();
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Overridden from views::BubbleDelegateView:
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void Init() OVERRIDE;
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Overridden from views::LinkListener:
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void LinkClicked(views::Link* source, int event_flags) OVERRIDE;
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OpenLink(const std::string& url, int event_flags);
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Browser* browser_;
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  views::Link* high_contrast_;
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  views::Link* dark_theme_;
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  views::Link* learn_more_;
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  views::Link* close_;
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(InvertBubbleView);
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)InvertBubbleView::InvertBubbleView(Browser* browser, views::View* anchor_view)
62a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    : views::BubbleDelegateView(anchor_view, views::BubbleBorder::TOP_RIGHT),
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      browser_(browser),
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      high_contrast_(NULL),
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      dark_theme_(NULL),
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      learn_more_(NULL),
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      close_(NULL) {
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)InvertBubbleView::~InvertBubbleView() {
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InvertBubbleView::Init() {
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const gfx::FontList& original_font_list =
765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      rb.GetFontList(ui::ResourceBundle::MediumFont);
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  views::Label* title = new views::Label(
79effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      base::string16(), original_font_list.Derive(2, gfx::Font::BOLD));
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  title->SetMultiLine(true);
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  learn_more_ = new views::Link(l10n_util::GetStringUTF16(IDS_LEARN_MORE));
835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  learn_more_->SetFontList(original_font_list);
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  learn_more_->set_listener(this);
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  high_contrast_ =
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new views::Link(l10n_util::GetStringUTF16(IDS_HIGH_CONTRAST_EXT));
885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  high_contrast_->SetFontList(original_font_list);
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  high_contrast_->set_listener(this);
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
91effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  dark_theme_ = new views::Link(l10n_util::GetStringUTF16(IDS_DARK_THEME));
925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  dark_theme_->SetFontList(original_font_list);
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dark_theme_->set_listener(this);
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  close_ = new views::Link(l10n_util::GetStringUTF16(IDS_CLOSE));
965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  close_->SetFontList(original_font_list);
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  close_->set_listener(this);
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  views::GridLayout* layout = views::GridLayout::CreatePanel(this);
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetLayoutManager(layout);
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  views::ColumnSet* columns = layout->AddColumnSet(0);
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < 4; i++) {
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    columns->AddColumn(views::GridLayout::LEADING,
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       views::GridLayout::LEADING, 0,
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       views::GridLayout::USE_PREF, 0, 0);
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  layout->StartRow(0, 0);
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  layout->AddView(title, 4, 1);
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  layout->StartRowWithPadding(0, 0, 0,
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              views::kRelatedControlSmallVerticalSpacing);
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  layout->AddView(high_contrast_);
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  layout->AddView(dark_theme_);
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  layout->AddView(learn_more_);
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  layout->AddView(close_);
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
118effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // Fit the message to the width of the links in the bubble.
119effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  const gfx::Size size(GetPreferredSize());
120effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  title->SetText(l10n_util::GetStringUTF16(IDS_HIGH_CONTRAST_NOTIFICATION));
121effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  title->SizeToFit(size.width());
122effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Switching to high-contrast mode has a nasty habit of causing Chrome
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // top-level windows to lose focus, so closing the bubble on deactivate
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // makes it disappear before the user has even seen it. This forces the
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // user to close it explicitly, which should be okay because it affects
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // a small minority of users, and only once.
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  set_close_on_deactivate(false);
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InvertBubbleView::LinkClicked(views::Link* source, int event_flags) {
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (source == high_contrast_)
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OpenLink(kHighContrastExtensionUrl, event_flags);
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else if (source == dark_theme_)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OpenLink(kDarkThemeSearchUrl, event_flags);
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else if (source == learn_more_)
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OpenLink(kLearnMoreUrl, event_flags);
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else if (source == close_)
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GetWidget()->Close();
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InvertBubbleView::OpenLink(const std::string& url, int event_flags) {
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WindowOpenDisposition disposition =
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ui::DispositionFromEventFlags(event_flags);
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::OpenURLParams params(
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GURL(url), content::Referrer(),
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      disposition == CURRENT_TAB ? NEW_FOREGROUND_TAB : disposition,
1501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      ui::PAGE_TRANSITION_LINK, false);
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  browser_->OpenURL(params);
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace chrome {
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
158a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void MaybeShowInvertBubbleView(BrowserView* browser_view) {
159a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  Browser* browser = browser_view->browser();
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PrefService* pref_service = browser->profile()->GetPrefs();
161a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  views::View* anchor = browser_view->toolbar()->app_menu();
162a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (gfx::IsInvertedColorScheme() && anchor && anchor->GetWidget() &&
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !pref_service->GetBoolean(prefs::kInvertNotificationShown)) {
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pref_service->SetBoolean(prefs::kInvertNotificationShown, true);
165a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    InvertBubbleView* delegate = new InvertBubbleView(browser, anchor);
166a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    views::BubbleDelegateView::CreateBubble(delegate)->Show();
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace chrome
171