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