Avi Drissman | 4a8573c | 2022-09-09 19:35:54 | [diff] [blame] | 1 | // Copyright 2016 The Chromium Authors |
hirono | d36c21d | 2016-06-21 01:25:22 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
Evan Stade | d6d837f | 2017-09-29 02:51:02 | [diff] [blame] | 5 | #include "chrome/browser/notifications/web_page_notifier_controller.h" |
hirono | d36c21d | 2016-06-21 01:25:22 | [diff] [blame] | 6 | |
Peter Boström | 6b70182 | 2021-04-15 03:53:08 | [diff] [blame] | 7 | #include <memory> |
| 8 | |
Evan Stade | ecfc48c | 2019-06-17 21:35:23 | [diff] [blame] | 9 | #include "ash/public/cpp/notifier_metadata.h" |
Sebastien Marchand | f1349f5 | 2019-01-25 03:16:41 | [diff] [blame] | 10 | #include "base/bind.h" |
Kent Tamura | 49b48d5c | 2020-07-14 05:55:41 | [diff] [blame] | 11 | #include "base/logging.h" |
hirono | d36c21d | 2016-06-21 01:25:22 | [diff] [blame] | 12 | #include "base/strings/utf_string_conversions.h" |
| 13 | #include "base/task/cancelable_task_tracker.h" |
| 14 | #include "chrome/browser/content_settings/host_content_settings_map_factory.h" |
| 15 | #include "chrome/browser/favicon/favicon_service_factory.h" |
Peter Beverloo | dd4ef1e | 2018-06-21 15:41:04 | [diff] [blame] | 16 | #include "chrome/browser/notifications/notification_permission_context.h" |
hirono | d36c21d | 2016-06-21 01:25:22 | [diff] [blame] | 17 | #include "chrome/browser/notifications/notifier_state_tracker.h" |
| 18 | #include "chrome/browser/notifications/notifier_state_tracker_factory.h" |
Clark DuVall | a11361ad3 | 2020-02-20 22:14:27 | [diff] [blame] | 19 | #include "chrome/browser/profiles/profile.h" |
hirono | d36c21d | 2016-06-21 01:25:22 | [diff] [blame] | 20 | #include "components/content_settings/core/browser/host_content_settings_map.h" |
| 21 | #include "components/content_settings/core/common/content_settings.h" |
| 22 | #include "components/favicon/core/favicon_service.h" |
| 23 | |
Evan Stade | d6d837f | 2017-09-29 02:51:02 | [diff] [blame] | 24 | WebPageNotifierController::WebPageNotifierController(Observer* observer) |
hirono | d36c21d | 2016-06-21 01:25:22 | [diff] [blame] | 25 | : observer_(observer) {} |
| 26 | |
Evan Stade | d6d837f | 2017-09-29 02:51:02 | [diff] [blame] | 27 | WebPageNotifierController::~WebPageNotifierController() {} |
hirono | d36c21d | 2016-06-21 01:25:22 | [diff] [blame] | 28 | |
Evan Stade | ecfc48c | 2019-06-17 21:35:23 | [diff] [blame] | 29 | std::vector<ash::NotifierMetadata> WebPageNotifierController::GetNotifierList( |
| 30 | Profile* profile) { |
| 31 | std::vector<ash::NotifierMetadata> notifiers; |
hirono | d36c21d | 2016-06-21 01:25:22 | [diff] [blame] | 32 | |
| 33 | ContentSettingsForOneType settings; |
Peter Beverloo | dd4ef1e | 2018-06-21 15:41:04 | [diff] [blame] | 34 | HostContentSettingsMapFactory::GetForProfile(profile)->GetSettingsForOneType( |
Illia Klimov | 48f643c | 2020-11-05 20:06:14 | [diff] [blame] | 35 | ContentSettingsType::NOTIFICATIONS, &settings); |
hirono | d36c21d | 2016-06-21 01:25:22 | [diff] [blame] | 36 | |
| 37 | favicon::FaviconService* const favicon_service = |
| 38 | FaviconServiceFactory::GetForProfile(profile, |
| 39 | ServiceAccessType::EXPLICIT_ACCESS); |
Peter Boström | 6b70182 | 2021-04-15 03:53:08 | [diff] [blame] | 40 | favicon_tracker_ = std::make_unique<base::CancelableTaskTracker>(); |
hirono | d36c21d | 2016-06-21 01:25:22 | [diff] [blame] | 41 | patterns_.clear(); |
| 42 | for (ContentSettingsForOneType::const_iterator iter = settings.begin(); |
| 43 | iter != settings.end(); ++iter) { |
| 44 | if (iter->primary_pattern == ContentSettingsPattern::Wildcard() && |
| 45 | iter->secondary_pattern == ContentSettingsPattern::Wildcard() && |
| 46 | iter->source != "preference") { |
| 47 | continue; |
| 48 | } |
| 49 | |
| 50 | std::string url_pattern = iter->primary_pattern.ToString(); |
Jan Wilken Dörrie | dec9912 | 2021-03-11 18:02:30 | [diff] [blame] | 51 | std::u16string name = base::UTF8ToUTF16(url_pattern); |
hirono | d36c21d | 2016-06-21 01:25:22 | [diff] [blame] | 52 | GURL url(url_pattern); |
| 53 | message_center::NotifierId notifier_id(url); |
| 54 | NotifierStateTracker* const notifier_state_tracker = |
| 55 | NotifierStateTrackerFactory::GetForProfile(profile); |
Tetsui Ohkubo | 39c8129 | 2017-12-14 02:32:39 | [diff] [blame] | 56 | content_settings::SettingInfo info; |
| 57 | HostContentSettingsMapFactory::GetForProfile(profile)->GetWebsiteSetting( |
Illia Klimov | 48f643c | 2020-11-05 20:06:14 | [diff] [blame] | 58 | url, GURL(), ContentSettingsType::NOTIFICATIONS, &info); |
Evan Stade | ecfc48c | 2019-06-17 21:35:23 | [diff] [blame] | 59 | notifiers.emplace_back( |
Tetsui Ohkubo | c27a5dc | 2018-01-11 05:56:52 | [diff] [blame] | 60 | notifier_id, name, |
Evan Stade | 55575d8 | 2017-11-02 00:52:36 | [diff] [blame] | 61 | notifier_state_tracker->IsNotifierEnabled(notifier_id), |
Tetsui Ohkubo | 39c8129 | 2017-12-14 02:32:39 | [diff] [blame] | 62 | info.source == content_settings::SETTING_SOURCE_POLICY, |
Evan Stade | ecfc48c | 2019-06-17 21:35:23 | [diff] [blame] | 63 | gfx::ImageSkia()); |
Evan Stade | 844ad7f | 2017-09-20 18:05:31 | [diff] [blame] | 64 | patterns_[url_pattern] = iter->primary_pattern; |
hirono | d36c21d | 2016-06-21 01:25:22 | [diff] [blame] | 65 | // Note that favicon service obtains the favicon from history. This means |
| 66 | // that it will fail to obtain the image if there are no history data for |
| 67 | // that URL. |
| 68 | favicon_service->GetFaviconImageForPageURL( |
Evan Stade | 844ad7f | 2017-09-20 18:05:31 | [diff] [blame] | 69 | url, |
Jan Wilken Dörrie | 8b2247e | 2020-04-20 10:04:40 | [diff] [blame] | 70 | base::BindOnce(&WebPageNotifierController::OnFaviconLoaded, |
| 71 | base::Unretained(this), url), |
hirono | d36c21d | 2016-06-21 01:25:22 | [diff] [blame] | 72 | favicon_tracker_.get()); |
| 73 | } |
| 74 | |
| 75 | return notifiers; |
| 76 | } |
| 77 | |
Evan Stade | d6d837f | 2017-09-29 02:51:02 | [diff] [blame] | 78 | void WebPageNotifierController::SetNotifierEnabled( |
hirono | d36c21d | 2016-06-21 01:25:22 | [diff] [blame] | 79 | Profile* profile, |
Evan Stade | 844ad7f | 2017-09-20 18:05:31 | [diff] [blame] | 80 | const message_center::NotifierId& notifier_id, |
hirono | d36c21d | 2016-06-21 01:25:22 | [diff] [blame] | 81 | bool enabled) { |
| 82 | // WEB_PAGE notifier cannot handle in DesktopNotificationService |
| 83 | // since it has the exact URL pattern. |
| 84 | // TODO(mukai): fix this. |
| 85 | ContentSetting default_setting = |
| 86 | HostContentSettingsMapFactory::GetForProfile(profile) |
Claudio DeSouza | c2c9f0f | 2022-09-02 23:59:18 | [diff] [blame] | 87 | ->GetDefaultContentSetting(ContentSettingsType::NOTIFICATIONS, |
| 88 | nullptr); |
hirono | d36c21d | 2016-06-21 01:25:22 | [diff] [blame] | 89 | |
| 90 | DCHECK(default_setting == CONTENT_SETTING_ALLOW || |
| 91 | default_setting == CONTENT_SETTING_BLOCK || |
| 92 | default_setting == CONTENT_SETTING_ASK); |
| 93 | |
| 94 | // The content setting for notifications needs to clear when it changes to |
| 95 | // the default value or get explicitly set when it differs from the |
| 96 | // default. |
| 97 | bool differs_from_default_value = |
| 98 | (default_setting != CONTENT_SETTING_ALLOW && enabled) || |
| 99 | (default_setting == CONTENT_SETTING_ALLOW && !enabled); |
| 100 | |
| 101 | if (differs_from_default_value) { |
Evan Stade | 844ad7f | 2017-09-20 18:05:31 | [diff] [blame] | 102 | if (notifier_id.url.is_valid()) { |
Peter Beverloo | dd4ef1e | 2018-06-21 15:41:04 | [diff] [blame] | 103 | NotificationPermissionContext::UpdatePermission( |
| 104 | profile, notifier_id.url, |
| 105 | enabled ? CONTENT_SETTING_ALLOW : CONTENT_SETTING_BLOCK); |
hirono | d36c21d | 2016-06-21 01:25:22 | [diff] [blame] | 106 | } else { |
Evan Stade | 844ad7f | 2017-09-20 18:05:31 | [diff] [blame] | 107 | LOG(ERROR) << "Invalid url pattern: " |
| 108 | << notifier_id.url.possibly_invalid_spec(); |
hirono | d36c21d | 2016-06-21 01:25:22 | [diff] [blame] | 109 | } |
| 110 | } else { |
| 111 | ContentSettingsPattern pattern; |
| 112 | |
Evan Stade | 844ad7f | 2017-09-20 18:05:31 | [diff] [blame] | 113 | const auto& iter = patterns_.find(notifier_id.url.possibly_invalid_spec()); |
hirono | d36c21d | 2016-06-21 01:25:22 | [diff] [blame] | 114 | if (iter != patterns_.end()) { |
| 115 | pattern = iter->second; |
Evan Stade | 844ad7f | 2017-09-20 18:05:31 | [diff] [blame] | 116 | } else if (notifier_id.url.is_valid()) { |
| 117 | pattern = ContentSettingsPattern::FromURLNoWildcard(notifier_id.url); |
hirono | d36c21d | 2016-06-21 01:25:22 | [diff] [blame] | 118 | } else { |
Evan Stade | 844ad7f | 2017-09-20 18:05:31 | [diff] [blame] | 119 | LOG(ERROR) << "Invalid url pattern: " |
| 120 | << notifier_id.url.possibly_invalid_spec(); |
hirono | d36c21d | 2016-06-21 01:25:22 | [diff] [blame] | 121 | } |
| 122 | |
| 123 | if (pattern.IsValid()) { |
| 124 | // Note that we don't use |
Peter Beverloo | dd4ef1e | 2018-06-21 15:41:04 | [diff] [blame] | 125 | // NotificationPermissionContext::UpdatePermission() |
hirono | d36c21d | 2016-06-21 01:25:22 | [diff] [blame] | 126 | // here because pattern might be from user manual input and not match |
| 127 | // the default one used by ClearSetting(). |
| 128 | HostContentSettingsMapFactory::GetForProfile(profile) |
| 129 | ->SetContentSettingCustomScope( |
| 130 | pattern, ContentSettingsPattern::Wildcard(), |
Illia Klimov | 48f643c | 2020-11-05 20:06:14 | [diff] [blame] | 131 | ContentSettingsType::NOTIFICATIONS, CONTENT_SETTING_DEFAULT); |
hirono | d36c21d | 2016-06-21 01:25:22 | [diff] [blame] | 132 | } |
| 133 | } |
| 134 | |
Evan Stade | 844ad7f | 2017-09-20 18:05:31 | [diff] [blame] | 135 | observer_->OnNotifierEnabledChanged(notifier_id, enabled); |
hirono | d36c21d | 2016-06-21 01:25:22 | [diff] [blame] | 136 | } |
| 137 | |
Evan Stade | d6d837f | 2017-09-29 02:51:02 | [diff] [blame] | 138 | void WebPageNotifierController::OnFaviconLoaded( |
hirono | d36c21d | 2016-06-21 01:25:22 | [diff] [blame] | 139 | const GURL& url, |
| 140 | const favicon_base::FaviconImageResult& favicon_result) { |
| 141 | observer_->OnIconImageUpdated(message_center::NotifierId(url), |
Evan Stade | 55575d8 | 2017-11-02 00:52:36 | [diff] [blame] | 142 | favicon_result.image.AsImageSkia()); |
hirono | d36c21d | 2016-06-21 01:25:22 | [diff] [blame] | 143 | } |