1 // Copyright 2019 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/ui/views/location_bar/cookie_controls_icon_view.h"
6 
7 #include <memory>
8 
9 #include "base/strings/utf_string_conversions.h"
10 #include "chrome/app/vector_icons/vector_icons.h"
11 #include "chrome/browser/content_settings/cookie_settings_factory.h"
12 #include "chrome/browser/profiles/profile.h"
13 #include "chrome/browser/ui/view_ids.h"
14 #include "chrome/browser/ui/views/location_bar/cookie_controls_bubble_view.h"
15 #include "chrome/grit/generated_resources.h"
16 #include "components/content_settings/browser/ui/cookie_controls_controller.h"
17 #include "content/public/browser/browser_context.h"
18 #include "ui/base/l10n/l10n_util.h"
19 #include "ui/gfx/geometry/size.h"
20 #include "ui/gfx/paint_vector_icon.h"
21 
CookieControlsIconView(IconLabelBubbleView::Delegate * icon_label_bubble_delegate,PageActionIconView::Delegate * page_action_icon_delegate)22 CookieControlsIconView::CookieControlsIconView(
23     IconLabelBubbleView::Delegate* icon_label_bubble_delegate,
24     PageActionIconView::Delegate* page_action_icon_delegate)
25     : PageActionIconView(nullptr,
26                          0,
27                          icon_label_bubble_delegate,
28                          page_action_icon_delegate) {
29   SetVisible(false);
30 }
31 
32 CookieControlsIconView::~CookieControlsIconView() = default;
33 
UpdateImpl()34 void CookieControlsIconView::UpdateImpl() {
35   auto* web_contents = delegate()->GetWebContentsForPageActionIconView();
36   if (web_contents) {
37     if (!controller_) {
38       Profile* profile =
39           Profile::FromBrowserContext(web_contents->GetBrowserContext());
40       controller_ =
41           std::make_unique<content_settings::CookieControlsController>(
42               CookieSettingsFactory::GetForProfile(profile),
43               profile->IsOffTheRecord() ? CookieSettingsFactory::GetForProfile(
44                                               profile->GetOriginalProfile())
45                                         : nullptr);
46       observer_.Add(controller_.get());
47     }
48     controller_->Update(web_contents);
49   }
50   SetVisible(ShouldBeVisible());
51 }
52 
OnStatusChanged(CookieControlsStatus status,CookieControlsEnforcement enforcement,int allowed_cookies,int blocked_cookies)53 void CookieControlsIconView::OnStatusChanged(
54     CookieControlsStatus status,
55     CookieControlsEnforcement enforcement,
56     int allowed_cookies,
57     int blocked_cookies) {
58   if (status_ != status) {
59     status_ = status;
60     SetVisible(ShouldBeVisible());
61     UpdateIconImage();
62   }
63   OnCookiesCountChanged(allowed_cookies, blocked_cookies);
64 }
65 
OnCookiesCountChanged(int allowed_cookies,int blocked_cookies)66 void CookieControlsIconView::OnCookiesCountChanged(int allowed_cookies,
67                                                    int blocked_cookies) {
68   // The blocked cookie count changes quite frequently, so avoid unnecessary
69   // UI updates.
70   if (has_blocked_cookies_ != blocked_cookies > 0) {
71     has_blocked_cookies_ = blocked_cookies > 0;
72     SetVisible(ShouldBeVisible());
73   }
74 }
75 
ShouldBeVisible() const76 bool CookieControlsIconView::ShouldBeVisible() const {
77   if (delegate()->ShouldHidePageActionIcons())
78     return false;
79 
80   if (HasAssociatedBubble())
81     return true;
82 
83   if (!delegate()->GetWebContentsForPageActionIconView())
84     return false;
85 
86   switch (status_) {
87     case CookieControlsStatus::kDisabledForSite:
88       return true;
89     case CookieControlsStatus::kEnabled:
90       return has_blocked_cookies_;
91     case CookieControlsStatus::kDisabled:
92     case CookieControlsStatus::kUninitialized:
93       return false;
94   }
95 }
96 
HasAssociatedBubble() const97 bool CookieControlsIconView::HasAssociatedBubble() const {
98   if (!GetBubble())
99     return false;
100 
101   // There may be multiple icons but only a single bubble can be displayed
102   // at a time. Check if the bubble belongs to this icon.
103   if (!GetBubble()->GetAnchorView())
104     return false;
105   return GetBubble()->GetAnchorView()->GetWidget() == GetWidget();
106 }
107 
OnExecuting(PageActionIconView::ExecuteSource source)108 void CookieControlsIconView::OnExecuting(
109     PageActionIconView::ExecuteSource source) {
110   CookieControlsBubbleView::ShowBubble(
111       this, this, delegate()->GetWebContentsForPageActionIconView(),
112       controller_.get(), status_);
113 }
114 
GetBubble() const115 views::BubbleDialogDelegate* CookieControlsIconView::GetBubble() const {
116   return CookieControlsBubbleView::GetCookieBubble();
117 }
118 
GetVectorIcon() const119 const gfx::VectorIcon& CookieControlsIconView::GetVectorIcon() const {
120   if (status_ == CookieControlsStatus::kDisabledForSite)
121     return kEyeIcon;
122   return kEyeCrossedIcon;
123 }
124 
GetClassName() const125 const char* CookieControlsIconView::GetClassName() const {
126   return "CookieControlsIconView";
127 }
128 
GetTextForTooltipAndAccessibleName() const129 base::string16 CookieControlsIconView::GetTextForTooltipAndAccessibleName()
130     const {
131   return l10n_util::GetStringUTF16(IDS_COOKIE_CONTROLS_TOOLTIP);
132 }
133