blob: 74b54cdc697f56a63d10ec477b7dda5260014628 [file] [log] [blame]
hironod36c21d2016-06-21 01:25:221// Copyright (c) 2016 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/notifications/web_page_notifier_source.h"
6
7#include "base/strings/utf_string_conversions.h"
8#include "base/task/cancelable_task_tracker.h"
9#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
10#include "chrome/browser/favicon/favicon_service_factory.h"
11#include "chrome/browser/notifications/desktop_notification_profile_util.h"
12#include "chrome/browser/notifications/notifier_state_tracker.h"
13#include "chrome/browser/notifications/notifier_state_tracker_factory.h"
14#include "components/content_settings/core/browser/host_content_settings_map.h"
15#include "components/content_settings/core/common/content_settings.h"
16#include "components/favicon/core/favicon_service.h"
17
18WebPageNotifiereSource::WebPageNotifiereSource(Observer* observer)
19 : observer_(observer) {}
20
21WebPageNotifiereSource::~WebPageNotifiereSource() {}
22
23std::vector<std::unique_ptr<message_center::Notifier>>
24WebPageNotifiereSource::GetNotifierList(Profile* profile) {
25 std::vector<std::unique_ptr<message_center::Notifier>> notifiers;
26
27 ContentSettingsForOneType settings;
28 DesktopNotificationProfileUtil::GetNotificationsSettings(profile, &settings);
29
30 favicon::FaviconService* const favicon_service =
31 FaviconServiceFactory::GetForProfile(profile,
32 ServiceAccessType::EXPLICIT_ACCESS);
33 favicon_tracker_.reset(new base::CancelableTaskTracker());
34 patterns_.clear();
35 for (ContentSettingsForOneType::const_iterator iter = settings.begin();
36 iter != settings.end(); ++iter) {
37 if (iter->primary_pattern == ContentSettingsPattern::Wildcard() &&
38 iter->secondary_pattern == ContentSettingsPattern::Wildcard() &&
39 iter->source != "preference") {
40 continue;
41 }
42
43 std::string url_pattern = iter->primary_pattern.ToString();
44 base::string16 name = base::UTF8ToUTF16(url_pattern);
45 GURL url(url_pattern);
46 message_center::NotifierId notifier_id(url);
47 NotifierStateTracker* const notifier_state_tracker =
48 NotifierStateTrackerFactory::GetForProfile(profile);
49 notifiers.emplace_back(new message_center::Notifier(
50 notifier_id, name,
51 notifier_state_tracker->IsNotifierEnabled(notifier_id)));
52 patterns_[name] = iter->primary_pattern;
53 // Note that favicon service obtains the favicon from history. This means
54 // that it will fail to obtain the image if there are no history data for
55 // that URL.
56 favicon_service->GetFaviconImageForPageURL(
57 url, base::Bind(&WebPageNotifiereSource::OnFaviconLoaded,
58 base::Unretained(this), url),
59 favicon_tracker_.get());
60 }
61
62 return notifiers;
63}
64
65void WebPageNotifiereSource::SetNotifierEnabled(
66 Profile* profile,
67 const message_center::Notifier& notifier,
68 bool enabled) {
69 // WEB_PAGE notifier cannot handle in DesktopNotificationService
70 // since it has the exact URL pattern.
71 // TODO(mukai): fix this.
72 ContentSetting default_setting =
73 HostContentSettingsMapFactory::GetForProfile(profile)
74 ->GetDefaultContentSetting(CONTENT_SETTINGS_TYPE_NOTIFICATIONS, NULL);
75
76 DCHECK(default_setting == CONTENT_SETTING_ALLOW ||
77 default_setting == CONTENT_SETTING_BLOCK ||
78 default_setting == CONTENT_SETTING_ASK);
79
80 // The content setting for notifications needs to clear when it changes to
81 // the default value or get explicitly set when it differs from the
82 // default.
83 bool differs_from_default_value =
84 (default_setting != CONTENT_SETTING_ALLOW && enabled) ||
85 (default_setting == CONTENT_SETTING_ALLOW && !enabled);
86
87 if (differs_from_default_value) {
88 if (notifier.notifier_id.url.is_valid()) {
89 if (enabled) {
90 DesktopNotificationProfileUtil::GrantPermission(
91 profile, notifier.notifier_id.url);
92 } else {
93 DesktopNotificationProfileUtil::DenyPermission(
94 profile, notifier.notifier_id.url);
95 }
96 } else {
97 LOG(ERROR) << "Invalid url pattern: " << notifier.notifier_id.url.spec();
98 }
99 } else {
100 ContentSettingsPattern pattern;
101
102 const auto& iter = patterns_.find(notifier.name);
103 if (iter != patterns_.end()) {
104 pattern = iter->second;
105 } else if (notifier.notifier_id.url.is_valid()) {
106 pattern =
107 ContentSettingsPattern::FromURLNoWildcard(notifier.notifier_id.url);
108 } else {
109 LOG(ERROR) << "Invalid url pattern: " << notifier.notifier_id.url.spec();
110 }
111
112 if (pattern.IsValid()) {
113 // Note that we don't use
114 // DesktopNotificationProfileUtil::ClearSetting()
115 // here because pattern might be from user manual input and not match
116 // the default one used by ClearSetting().
117 HostContentSettingsMapFactory::GetForProfile(profile)
118 ->SetContentSettingCustomScope(
119 pattern, ContentSettingsPattern::Wildcard(),
120 CONTENT_SETTINGS_TYPE_NOTIFICATIONS,
121 content_settings::ResourceIdentifier(), CONTENT_SETTING_DEFAULT);
122 }
123 }
124
125 observer_->OnNotifierEnabledChanged(notifier.notifier_id, enabled);
126}
127
128void WebPageNotifiereSource::OnNotifierSettingsClosing() {
129 DCHECK(favicon_tracker_.get());
130 favicon_tracker_->TryCancelAll();
131 patterns_.clear();
132}
133
134message_center::NotifierId::NotifierType
135WebPageNotifiereSource::GetNotifierType() {
136 return message_center::NotifierId::WEB_PAGE;
137}
138
139void WebPageNotifiereSource::OnFaviconLoaded(
140 const GURL& url,
141 const favicon_base::FaviconImageResult& favicon_result) {
142 observer_->OnIconImageUpdated(message_center::NotifierId(url),
143 favicon_result.image);
144}