Refactor MessageCenterSettingsController.
The CL does refactoring for MessageCenterSettingsController to get rid
of #ifdef macros for CHROME_OS.
1. Define NotifierSource abstract class that provides a list of specific
type of notifiers.
2. Define subclass for each notifier type (APPLICATION, WEB_PAGE,
SYSTEM_COMPONENT, ARC_APPLICATION).
3. Let MessageCenterSettingsController delegate to each source.
BUG=620184
TEST=None
Review-Url: https://codereview.chromium.org/2064363002
Cr-Commit-Position: refs/heads/master@{#400867}
diff --git a/chrome/browser/notifications/application_notifier_source.cc b/chrome/browser/notifications/application_notifier_source.cc
new file mode 100644
index 0000000..132b0f23
--- /dev/null
+++ b/chrome/browser/notifications/application_notifier_source.cc
@@ -0,0 +1,81 @@
+// Copyright (c) 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/notifications/application_notifier_source.h"
+
+#include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/notifications/notifier_state_tracker.h"
+#include "chrome/browser/notifications/notifier_state_tracker_factory.h"
+#include "chrome/browser/profiles/profile.h"
+#include "extensions/common/constants.h"
+#include "extensions/common/extension_set.h"
+#include "extensions/common/permissions/api_permission.h"
+#include "extensions/common/permissions/permissions_data.h"
+#include "ui/message_center/notifier_settings.h"
+
+ApplicationNotifierSource::ApplicationNotifierSource(Observer* observer)
+ : observer_(observer) {}
+
+ApplicationNotifierSource::~ApplicationNotifierSource() {}
+
+std::vector<std::unique_ptr<message_center::Notifier>>
+ApplicationNotifierSource::GetNotifierList(Profile* profile) {
+ std::vector<std::unique_ptr<message_center::Notifier>> notifiers;
+ const extensions::ExtensionSet& extension_set =
+ extensions::ExtensionRegistry::Get(profile)->enabled_extensions();
+ // The extension icon size has to be 32x32 at least to load bigger icons if
+ // the icon doesn't exist for the specified size, and in that case it falls
+ // back to the default icon. The fetched icon will be resized in the
+ // settings dialog. See chrome/browser/extensions/extension_icon_image.cc
+ // and crbug.com/222931
+ app_icon_loader_.reset(new extensions::ExtensionAppIconLoader(
+ profile, extension_misc::EXTENSION_ICON_SMALL, this));
+ for (extensions::ExtensionSet::const_iterator iter = extension_set.begin();
+ iter != extension_set.end(); ++iter) {
+ const extensions::Extension* extension = iter->get();
+ if (!extension->permissions_data()->HasAPIPermission(
+ extensions::APIPermission::kNotifications)) {
+ continue;
+ }
+
+ // Hosted apps are no longer able to affect the notifications permission
+ // state for web notifications.
+ // TODO(dewittj): Deprecate the 'notifications' permission for hosted
+ // apps.
+ if (extension->is_hosted_app())
+ continue;
+
+ message_center::NotifierId notifier_id(
+ message_center::NotifierId::APPLICATION, extension->id());
+ NotifierStateTracker* const notifier_state_tracker =
+ NotifierStateTrackerFactory::GetForProfile(profile);
+ notifiers.emplace_back(new message_center::Notifier(
+ notifier_id, base::UTF8ToUTF16(extension->name()),
+ notifier_state_tracker->IsNotifierEnabled(notifier_id)));
+ app_icon_loader_->FetchImage(extension->id());
+ }
+
+ return notifiers;
+}
+
+void ApplicationNotifierSource::SetNotifierEnabled(
+ Profile* profile,
+ const message_center::Notifier& notifier,
+ bool enabled) {
+ NotifierStateTrackerFactory::GetForProfile(profile)->SetNotifierEnabled(
+ notifier.notifier_id, enabled);
+ observer_->OnNotifierEnabledChanged(notifier.notifier_id, enabled);
+}
+
+message_center::NotifierId::NotifierType
+ApplicationNotifierSource::GetNotifierType() {
+ return message_center::NotifierId::APPLICATION;
+}
+
+void ApplicationNotifierSource::OnAppImageUpdated(const std::string& id,
+ const gfx::ImageSkia& image) {
+ observer_->OnIconImageUpdated(
+ message_center::NotifierId(message_center::NotifierId::APPLICATION, id),
+ gfx::Image(image));
+}
diff --git a/chrome/browser/notifications/application_notifier_source.h b/chrome/browser/notifications/application_notifier_source.h
new file mode 100644
index 0000000..a3604ba
--- /dev/null
+++ b/chrome/browser/notifications/application_notifier_source.h
@@ -0,0 +1,37 @@
+// Copyright (c) 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_NOTIFICATIONS_APPLICATION_NOTIFIER_SOURCE_H_
+#define CHROME_BROWSER_NOTIFICATIONS_APPLICATION_NOTIFIER_SOURCE_H_
+
+#include "chrome/browser/extensions/extension_app_icon_loader.h"
+#include "chrome/browser/notifications/notifier_source.h"
+
+class ApplicationNotifierSource : public NotifierSource,
+ public AppIconLoaderDelegate {
+ public:
+ explicit ApplicationNotifierSource(Observer* observer);
+ ~ApplicationNotifierSource() override;
+
+ std::vector<std::unique_ptr<message_center::Notifier>> GetNotifierList(
+ Profile* profile) override;
+
+ void SetNotifierEnabled(Profile* profile,
+ const message_center::Notifier& notifier,
+ bool enabled) override;
+
+ message_center::NotifierId::NotifierType GetNotifierType() override;
+
+ private:
+ // Overridden from AppIconLoaderDelegate.
+ void OnAppImageUpdated(const std::string& id,
+ const gfx::ImageSkia& image) override;
+
+ std::unique_ptr<AppIconLoader> app_icon_loader_;
+
+ // Lifetime of parent must be longer than the source.
+ Observer* observer_;
+};
+
+#endif // CHROME_BROWSER_NOTIFICATIONS_APPLICATION_NOTIFIER_SOURCE_H_
diff --git a/chrome/browser/notifications/arc_application_notifier_source_chromeos.cc b/chrome/browser/notifications/arc_application_notifier_source_chromeos.cc
new file mode 100644
index 0000000..171268e
--- /dev/null
+++ b/chrome/browser/notifications/arc_application_notifier_source_chromeos.cc
@@ -0,0 +1,69 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/notifications/arc_application_notifier_source_chromeos.h"
+
+#include <set>
+
+#include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h"
+#include "ui/message_center/notifier_settings.h"
+
+namespace arc {
+
+namespace {
+constexpr int kSetNotificationsEnabledMinVersion = 6;
+} // namespace
+
+ArcApplicationNotifierSourceChromeOS::ArcApplicationNotifierSourceChromeOS(
+ Observer* observer)
+ : observer_(observer) {}
+
+std::vector<std::unique_ptr<message_center::Notifier>>
+ArcApplicationNotifierSourceChromeOS::GetNotifierList(Profile* profile) {
+ const ArcAppListPrefs* const app_list = ArcAppListPrefs::Get(profile);
+ const std::vector<std::string>& app_ids = app_list->GetAppIds();
+ std::set<std::string> added_packages;
+ std::vector<std::unique_ptr<message_center::Notifier>> results;
+
+ for (const std::string& app_id : app_ids) {
+ const auto app = app_list->GetApp(app_id);
+ if (!app)
+ continue;
+ // Handle packages having multiple launcher activities.
+ if (added_packages.count(app->package_name))
+ continue;
+
+ added_packages.insert(app->package_name);
+ message_center::NotifierId notifier_id(
+ message_center::NotifierId::ARC_APPLICATION, app->package_name);
+ results.emplace_back(
+ new message_center::Notifier(notifier_id, base::ASCIIToUTF16(app->name),
+ app->notifications_enabled));
+ }
+
+ return results;
+}
+
+void ArcApplicationNotifierSourceChromeOS::SetNotifierEnabled(
+ Profile* profile,
+ const message_center::Notifier& notifier,
+ bool enabled) {
+ auto* const service = arc::ArcBridgeService::Get();
+ if (service) {
+ if (service->app_version() >= kSetNotificationsEnabledMinVersion) {
+ service->app_instance()->SetNotificationsEnabled(notifier.notifier_id.id,
+ enabled);
+ observer_->OnNotifierEnabledChanged(notifier.notifier_id, enabled);
+ }
+ }
+}
+
+message_center::NotifierId::NotifierType
+ArcApplicationNotifierSourceChromeOS::GetNotifierType() {
+ return message_center::NotifierId::ARC_APPLICATION;
+}
+
+} // namespace arc
diff --git a/chrome/browser/notifications/arc_application_notifier_source_chromeos.h b/chrome/browser/notifications/arc_application_notifier_source_chromeos.h
new file mode 100644
index 0000000..35232f6
--- /dev/null
+++ b/chrome/browser/notifications/arc_application_notifier_source_chromeos.h
@@ -0,0 +1,44 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_NOTIFICATIONS_ARC_APPLICATION_NOTIFIER_SOURCE_CHROMEOS_H_
+#define CHROME_BROWSER_NOTIFICATIONS_ARC_APPLICATION_NOTIFIER_SOURCE_CHROMEOS_H_
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "base/macros.h"
+#include "chrome/browser/notifications/notifier_source.h"
+
+namespace content {
+class BrowserContext;
+}
+
+namespace message_center {
+struct Notifier;
+}
+
+namespace arc {
+
+// TODO(hirono): Observe enabled flag change and notify it to message center.
+class ArcApplicationNotifierSourceChromeOS : public NotifierSource {
+ public:
+ explicit ArcApplicationNotifierSourceChromeOS(Observer* observer);
+
+ // TODO(hirono): Rewrite the function with new API to fetch package list.
+ std::vector<std::unique_ptr<message_center::Notifier>> GetNotifierList(
+ Profile* profile) override;
+ void SetNotifierEnabled(Profile* profile,
+ const message_center::Notifier& notifier,
+ bool enabled) override;
+ message_center::NotifierId::NotifierType GetNotifierType() override;
+
+ private:
+ Observer* observer_;
+};
+
+} // namespace arc
+
+#endif // CHROME_BROWSER_NOTIFICATIONS_ARC_APPLICATION_NOTIFIER_SOURCE_CHROMEOS_H_
diff --git a/chrome/browser/notifications/arc_notifier_manager.cc b/chrome/browser/notifications/arc_notifier_manager.cc
deleted file mode 100644
index d6f96b8..0000000
--- a/chrome/browser/notifications/arc_notifier_manager.cc
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/notifications/arc_notifier_manager.h"
-
-#include <set>
-
-#include "base/strings/utf_string_conversions.h"
-#include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h"
-#include "ui/message_center/notifier_settings.h"
-
-namespace arc {
-
-namespace {
-constexpr int kSetNotificationsEnabledMinVersion = 6;
-} // namespace
-
-std::vector<std::unique_ptr<message_center::Notifier>>
-ArcNotifierManager::GetNotifiers(content::BrowserContext* profile) {
- const ArcAppListPrefs* const app_list = ArcAppListPrefs::Get(profile);
- const std::vector<std::string>& app_ids = app_list->GetAppIds();
- std::set<std::string> added_packages;
- std::vector<std::unique_ptr<message_center::Notifier>> results;
-
- for (const std::string& app_id : app_ids) {
- const auto app = app_list->GetApp(app_id);
- if (!app)
- continue;
- // Handle packages having multiple launcher activities.
- if (added_packages.count(app->package_name))
- continue;
-
- added_packages.insert(app->package_name);
- message_center::NotifierId notifier_id(
- message_center::NotifierId::ARC_APPLICATION, app->package_name);
- results.emplace_back(new message_center::Notifier(
- notifier_id,
- base::ASCIIToUTF16(app->name),
- app->notifications_enabled));
- }
-
- return results;
-}
-
-void ArcNotifierManager::SetNotifierEnabled(const std::string& package,
- bool enabled) {
- auto* const service = arc::ArcBridgeService::Get();
- if (service) {
- if (service->app_version() >= kSetNotificationsEnabledMinVersion) {
- service->app_instance()->SetNotificationsEnabled(package, enabled);
- }
- }
-}
-
-} // namespace arc
diff --git a/chrome/browser/notifications/message_center_settings_controller.cc b/chrome/browser/notifications/message_center_settings_controller.cc
index 8de630e..03c8a32 100644
--- a/chrome/browser/notifications/message_center_settings_controller.cc
+++ b/chrome/browser/notifications/message_center_settings_controller.cc
@@ -11,46 +11,26 @@
#include "base/command_line.h"
#include "base/i18n/string_compare.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/task/cancelable_task_tracker.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_notification_types.h"
-#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
-#include "chrome/browser/extensions/extension_app_icon_loader.h"
-#include "chrome/browser/favicon/favicon_service_factory.h"
-#include "chrome/browser/notifications/desktop_notification_profile_util.h"
-#include "chrome/browser/notifications/notifier_state_tracker.h"
-#include "chrome/browser/notifications/notifier_state_tracker_factory.h"
+#include "chrome/browser/notifications/application_notifier_source.h"
+#include "chrome/browser/notifications/web_page_notifier_source.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_attributes_entry.h"
#include "chrome/browser/profiles/profile_attributes_storage.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/common/extensions/api/notifications.h"
-#include "chrome/common/extensions/extension_constants.h"
-#include "components/content_settings/core/browser/host_content_settings_map.h"
-#include "components/favicon/core/favicon_service.h"
-#include "components/favicon_base/favicon_types.h"
-#include "components/history/core/browser/history_types.h"
#include "content/public/browser/notification_service.h"
-#include "content/public/browser/notification_source.h"
#include "extensions/browser/event_router.h"
-#include "extensions/browser/extension_registry.h"
-#include "extensions/common/constants.h"
-#include "extensions/common/extension.h"
-#include "extensions/common/permissions/permissions_data.h"
-#include "grit/theme_resources.h"
-#include "ui/base/l10n/l10n_util.h"
-#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/image/image.h"
#include "ui/message_center/message_center_style.h"
-#include "ui/strings/grit/ui_strings.h"
#if defined(OS_CHROMEOS)
-#include "ash/common/system/system_notifier.h"
#include "chrome/browser/chromeos/profiles/profile_helper.h"
-#include "chrome/browser/notifications/arc_notifier_manager.h"
-#include "components/arc/arc_bridge_service.h"
+#include "chrome/browser/notifications/arc_application_notifier_source_chromeos.h"
+#include "chrome/browser/notifications/system_component_notifier_source_chromeos.h"
#endif
using message_center::Notifier;
@@ -98,6 +78,7 @@
} // namespace message_center
namespace {
+
class NotifierComparator {
public:
explicit NotifierComparator(icu::Collator* collator) : collator_(collator) {}
@@ -139,13 +120,26 @@
profile_attributes_storage_.AddObserver(this);
RebuildNotifierGroups(false);
+ sources_.insert(std::make_pair(
+ NotifierId::APPLICATION,
+ std::unique_ptr<NotifierSource>(new ApplicationNotifierSource(this))));
+ sources_.insert(std::make_pair(
+ NotifierId::WEB_PAGE,
+ std::unique_ptr<NotifierSource>(new WebPageNotifiereSource(this))));
+
#if defined(OS_CHROMEOS)
// UserManager may not exist in some tests.
if (user_manager::UserManager::IsInitialized())
user_manager::UserManager::Get()->AddSessionStateObserver(this);
- // Check if ARC is enabled.
- if (arc::ArcBridgeService::Get())
- arc_notifier_manager_.reset(new arc::ArcNotifierManager());
+ // For system components.
+ sources_.insert(
+ std::make_pair(NotifierId::SYSTEM_COMPONENT,
+ std::unique_ptr<NotifierSource>(
+ new SystemComponentNotifierSourceChromeOS(this))));
+ sources_.insert(
+ std::make_pair(NotifierId::ARC_APPLICATION,
+ std::unique_ptr<NotifierSource>(
+ new arc::ArcApplicationNotifierSourceChromeOS(this))));
#endif
}
@@ -195,9 +189,7 @@
return;
current_notifier_group_ = index;
- FOR_EACH_OBSERVER(message_center::NotifierSettingsObserver,
- observers_,
- NotifierGroupChanged());
+ DispatchNotifierGroupChanged();
}
void MessageCenterSettingsController::GetNotifierList(
@@ -209,101 +201,13 @@
// the default profile is not loaded.
Profile* profile = notifier_groups_[current_notifier_group_]->profile();
- NotifierStateTracker* notifier_state_tracker =
- NotifierStateTrackerFactory::GetForProfile(profile);
-
- const extensions::ExtensionSet& extension_set =
- extensions::ExtensionRegistry::Get(profile)->enabled_extensions();
- // The extension icon size has to be 32x32 at least to load bigger icons if
- // the icon doesn't exist for the specified size, and in that case it falls
- // back to the default icon. The fetched icon will be resized in the settings
- // dialog. See chrome/browser/extensions/extension_icon_image.cc and
- // crbug.com/222931
- app_icon_loader_.reset(new extensions::ExtensionAppIconLoader(
- profile, extension_misc::EXTENSION_ICON_SMALL, this));
- for (extensions::ExtensionSet::const_iterator iter = extension_set.begin();
- iter != extension_set.end();
- ++iter) {
- const extensions::Extension* extension = iter->get();
- if (!extension->permissions_data()->HasAPIPermission(
- extensions::APIPermission::kNotifications)) {
- continue;
- }
-
- // Hosted apps are no longer able to affect the notifications permission
- // state for web notifications.
- // TODO(dewittj): Deprecate the 'notifications' permission for hosted apps.
- if (extension->is_hosted_app())
- continue;
-
- NotifierId notifier_id(NotifierId::APPLICATION, extension->id());
- notifiers->push_back(new Notifier(
- notifier_id,
- base::UTF8ToUTF16(extension->name()),
- notifier_state_tracker->IsNotifierEnabled(notifier_id)));
- app_icon_loader_->FetchImage(extension->id());
- }
-
- ContentSettingsForOneType settings;
- DesktopNotificationProfileUtil::GetNotificationsSettings(profile, &settings);
-
- favicon::FaviconService* favicon_service =
- FaviconServiceFactory::GetForProfile(profile,
- ServiceAccessType::EXPLICIT_ACCESS);
- favicon_tracker_.reset(new base::CancelableTaskTracker());
- patterns_.clear();
- for (ContentSettingsForOneType::const_iterator iter = settings.begin();
- iter != settings.end(); ++iter) {
- if (iter->primary_pattern == ContentSettingsPattern::Wildcard() &&
- iter->secondary_pattern == ContentSettingsPattern::Wildcard() &&
- iter->source != "preference") {
- continue;
- }
-
- std::string url_pattern = iter->primary_pattern.ToString();
- base::string16 name = base::UTF8ToUTF16(url_pattern);
- GURL url(url_pattern);
- NotifierId notifier_id(url);
- notifiers->push_back(new Notifier(
- notifier_id,
- name,
- notifier_state_tracker->IsNotifierEnabled(notifier_id)));
- patterns_[name] = iter->primary_pattern;
- // Note that favicon service obtains the favicon from history. This means
- // that it will fail to obtain the image if there are no history data for
- // that URL.
- favicon_service->GetFaviconImageForPageURL(
- url,
- base::Bind(&MessageCenterSettingsController::OnFaviconLoaded,
- base::Unretained(this),
- url),
- favicon_tracker_.get());
- }
-
-#if defined(OS_CHROMEOS)
- // Add ARC++ apps.
- if (arc_notifier_manager_) {
- auto list = arc_notifier_manager_->GetNotifiers(profile);
- for (auto& notifier : list) {
+ for (auto& source : sources_) {
+ auto source_notifiers = source.second->GetNotifierList(profile);
+ for (auto& notifier : source_notifiers) {
notifiers->push_back(notifier.release());
}
}
- // Screenshot notification feature is only for ChromeOS. See crbug.com/238358
- const base::string16& screenshot_name =
- l10n_util::GetStringUTF16(IDS_MESSAGE_CENTER_NOTIFIER_SCREENSHOT_NAME);
- NotifierId screenshot_notifier_id(
- NotifierId::SYSTEM_COMPONENT, ash::system_notifier::kNotifierScreenshot);
- Notifier* const screenshot_notifier = new Notifier(
- screenshot_notifier_id,
- screenshot_name,
- notifier_state_tracker->IsNotifierEnabled(screenshot_notifier_id));
- screenshot_notifier->icon =
- ui::ResourceBundle::GetSharedInstance().GetImageNamed(
- IDR_SCREENSHOT_NOTIFICATION_ICON);
- notifiers->push_back(screenshot_notifier);
-#endif
-
UErrorCode error = U_ZERO_ERROR;
std::unique_ptr<icu::Collator> collator(icu::Collator::createInstance(error));
std::unique_ptr<NotifierComparator> comparator(
@@ -318,96 +222,19 @@
DCHECK_LT(current_notifier_group_, notifier_groups_.size());
Profile* profile = notifier_groups_[current_notifier_group_]->profile();
- switch (notifier.notifier_id.type) {
- case NotifierId::WEB_PAGE: {
- // WEB_PAGE notifier cannot handle in DesktopNotificationService
- // since it has the exact URL pattern.
- // TODO(mukai): fix this.
- ContentSetting default_setting =
- HostContentSettingsMapFactory::GetForProfile(profile)
- ->GetDefaultContentSetting(CONTENT_SETTINGS_TYPE_NOTIFICATIONS,
- NULL);
-
- DCHECK(default_setting == CONTENT_SETTING_ALLOW ||
- default_setting == CONTENT_SETTING_BLOCK ||
- default_setting == CONTENT_SETTING_ASK);
-
- // The content setting for notifications needs to clear when it changes to
- // the default value or get explicitly set when it differs from the
- // default.
- bool differs_from_default_value =
- (default_setting != CONTENT_SETTING_ALLOW && enabled) ||
- (default_setting == CONTENT_SETTING_ALLOW && !enabled);
-
- if (differs_from_default_value) {
- if (notifier.notifier_id.url.is_valid()) {
- if (enabled) {
- DesktopNotificationProfileUtil::GrantPermission(
- profile, notifier.notifier_id.url);
- } else {
- DesktopNotificationProfileUtil::DenyPermission(
- profile, notifier.notifier_id.url);
- }
- } else {
- LOG(ERROR) << "Invalid url pattern: "
- << notifier.notifier_id.url.spec();
- }
- } else {
- ContentSettingsPattern pattern;
-
- const auto& iter = patterns_.find(notifier.name);
- if (iter != patterns_.end()) {
- pattern = iter->second;
- } else if (notifier.notifier_id.url.is_valid()) {
- pattern = ContentSettingsPattern::FromURLNoWildcard(
- notifier.notifier_id.url);
- } else {
- LOG(ERROR) << "Invalid url pattern: "
- << notifier.notifier_id.url.spec();
- }
-
- if (pattern.IsValid()) {
- // Note that we don't use
- // DesktopNotificationProfileUtil::ClearSetting()
- // here because pattern might be from user manual input and not match
- // the default one used by ClearSetting().
- HostContentSettingsMapFactory::GetForProfile(profile)
- ->SetContentSettingCustomScope(
- pattern, ContentSettingsPattern::Wildcard(),
- CONTENT_SETTINGS_TYPE_NOTIFICATIONS,
- content_settings::ResourceIdentifier(),
- CONTENT_SETTING_DEFAULT);
- }
- }
- break;
- }
- case NotifierId::APPLICATION:
- case NotifierId::SYSTEM_COMPONENT: {
- NotifierStateTrackerFactory::GetForProfile(profile)->SetNotifierEnabled(
- notifier.notifier_id, enabled);
- break;
- }
- case NotifierId::ARC_APPLICATION: {
-#if defined(OS_CHROMEOS)
- if (arc_notifier_manager_) {
- arc_notifier_manager_->SetNotifierEnabled(notifier.notifier_id.id,
- enabled);
- }
-#else
- NOTREACHED();
-#endif
- break;
- }
+ if (!sources_.count(notifier.notifier_id.type)) {
+ NOTREACHED();
+ return;
}
- FOR_EACH_OBSERVER(message_center::NotifierSettingsObserver,
- observers_,
- NotifierEnabledChanged(notifier.notifier_id, enabled));
+
+ sources_[notifier.notifier_id.type]->SetNotifierEnabled(profile, notifier,
+ enabled);
}
void MessageCenterSettingsController::OnNotifierSettingsClosing() {
- DCHECK(favicon_tracker_.get());
- favicon_tracker_->TryCancelAll();
- patterns_.clear();
+ for (auto& source : sources_) {
+ source.second->OnNotifierSettingsClosing();
+ }
}
bool MessageCenterSettingsController::NotifierHasAdvancedSettings(
@@ -453,15 +280,6 @@
event_router->DispatchEventToExtension(extension_id, std::move(event));
}
-void MessageCenterSettingsController::OnFaviconLoaded(
- const GURL& url,
- const favicon_base::FaviconImageResult& favicon_result) {
- FOR_EACH_OBSERVER(message_center::NotifierSettingsObserver,
- observers_,
- UpdateIconImage(NotifierId(url), favicon_result.image));
-}
-
-
#if defined(OS_CHROMEOS)
void MessageCenterSettingsController::ActiveUserChanged(
const user_manager::User* active_user) {
@@ -469,14 +287,6 @@
}
#endif
-void MessageCenterSettingsController::OnAppImageUpdated(
- const std::string& id, const gfx::ImageSkia& image) {
- FOR_EACH_OBSERVER(message_center::NotifierSettingsObserver,
- observers_,
- UpdateIconImage(NotifierId(NotifierId::APPLICATION, id),
- gfx::Image(image)));
-}
-
void MessageCenterSettingsController::Observe(
int type,
const content::NotificationSource& source,
@@ -510,6 +320,25 @@
RebuildNotifierGroups(true);
}
+void MessageCenterSettingsController::OnIconImageUpdated(
+ const message_center::NotifierId& id,
+ const gfx::Image& image) {
+ FOR_EACH_OBSERVER(message_center::NotifierSettingsObserver, observers_,
+ UpdateIconImage(id, image));
+}
+
+void MessageCenterSettingsController::OnNotifierEnabledChanged(
+ const message_center::NotifierId& id,
+ bool enabled) {
+ FOR_EACH_OBSERVER(message_center::NotifierSettingsObserver, observers_,
+ NotifierEnabledChanged(id, enabled));
+}
+
+void MessageCenterSettingsController::DispatchNotifierGroupChanged() {
+ FOR_EACH_OBSERVER(message_center::NotifierSettingsObserver, observers_,
+ NotifierGroupChanged());
+}
+
#if defined(OS_CHROMEOS)
void MessageCenterSettingsController::CreateNotifierGroupForGuestLogin() {
// Already created.
@@ -532,10 +361,7 @@
user->GetDisplayName(), profile));
notifier_groups_.push_back(std::move(group));
-
- FOR_EACH_OBSERVER(message_center::NotifierSettingsObserver,
- observers_,
- NotifierGroupChanged());
+ DispatchNotifierGroupChanged();
}
#endif
@@ -595,9 +421,6 @@
}
#endif
- if (notify) {
- FOR_EACH_OBSERVER(message_center::NotifierSettingsObserver,
- observers_,
- NotifierGroupChanged());
- }
+ if (notify)
+ DispatchNotifierGroupChanged();
}
diff --git a/chrome/browser/notifications/message_center_settings_controller.h b/chrome/browser/notifications/message_center_settings_controller.h
index d25c240..d1cbbc6 100644
--- a/chrome/browser/notifications/message_center_settings_controller.h
+++ b/chrome/browser/notifications/message_center_settings_controller.h
@@ -15,6 +15,7 @@
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "build/build_config.h"
+#include "chrome/browser/notifications/notifier_source.h"
#include "chrome/browser/profiles/profile_attributes_storage.h"
#include "chrome/browser/ui/app_icon_loader.h"
#include "components/content_settings/core/common/content_settings.h"
@@ -30,12 +31,7 @@
#endif
class Profile;
-
-#if defined(OS_CHROMEOS)
-namespace arc {
-class ArcNotifierManager;
-}
-#endif
+class NotifierSource;
namespace base {
class CancelableTaskTracker;
@@ -58,7 +54,7 @@
#if defined(OS_CHROMEOS)
public user_manager::UserManager::UserSessionStateObserver,
#endif
- public AppIconLoaderDelegate {
+ public NotifierSource::Observer {
public:
explicit MessageCenterSettingsController(
ProfileAttributesStorage& profile_attributes_storage);
@@ -90,17 +86,13 @@
void ActiveUserChanged(const user_manager::User* active_user) override;
#endif
- // Overridden from AppIconLoaderDelegate.
- void OnAppImageUpdated(const std::string& id,
- const gfx::ImageSkia& image) override;
-
private:
// Overridden from content::NotificationObserver.
void Observe(int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) override;
- // ProfileAttributesStorage::Observer:
+ // Overridden from ProfileAttributesStorage::Observer.
void OnProfileAdded(const base::FilePath& profile_path) override;
void OnProfileWasRemoved(const base::FilePath& profile_path,
const base::string16& profile_name) override;
@@ -108,8 +100,13 @@
const base::string16& old_profile_name) override;
void OnProfileAuthInfoChanged(const base::FilePath& profile_path) override;
- void OnFaviconLoaded(const GURL& url,
- const favicon_base::FaviconImageResult& favicon_result);
+ // Overridden from NotifierSource::Observer.
+ void OnIconImageUpdated(const message_center::NotifierId&,
+ const gfx::Image&) override;
+ void OnNotifierEnabledChanged(const message_center::NotifierId&,
+ bool) override;
+
+ void DispatchNotifierGroupChanged();
#if defined(OS_CHROMEOS)
// Sets up the notifier group for the guest session. This needs to be
@@ -126,23 +123,17 @@
// The views displaying notifier settings.
base::ObserverList<message_center::NotifierSettingsObserver> observers_;
- // The task tracker for loading favicons.
- std::unique_ptr<base::CancelableTaskTracker> favicon_tracker_;
-
- std::unique_ptr<AppIconLoader> app_icon_loader_;
-
-#if defined(OS_CHROMEOS)
- std::unique_ptr<arc::ArcNotifierManager> arc_notifier_manager_;
-#endif
-
- std::map<base::string16, ContentSettingsPattern> patterns_;
-
// The list of all configurable notifier groups. This is each profile that is
// loaded (and in the ProfileAttributesStorage - so no incognito profiles go
// here).
std::vector<std::unique_ptr<message_center::ProfileNotifierGroup>>
notifier_groups_;
+ // Notifier source for each notifier type.
+ std::map<message_center::NotifierId::NotifierType,
+ std::unique_ptr<NotifierSource>>
+ sources_;
+
size_t current_notifier_group_;
content::NotificationRegistrar registrar_;
diff --git a/chrome/browser/notifications/notifier_source.h b/chrome/browser/notifications/notifier_source.h
new file mode 100644
index 0000000..7c9f4f2e7
--- /dev/null
+++ b/chrome/browser/notifications/notifier_source.h
@@ -0,0 +1,58 @@
+// Copyright (c) 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_NOTIFICATIONS_NOTIFIER_SOURCE_H_
+#define CHROME_BROWSER_NOTIFICATIONS_NOTIFIER_SOURCE_H_
+
+#include <memory>
+#include <vector>
+
+#include "base/macros.h"
+#include "ui/message_center/notifier_settings.h"
+
+class Profile;
+
+namespace message_center {
+struct Notifier;
+class NotifierSettingsObserver;
+}
+
+class NotifierSource {
+ public:
+ class Observer {
+ public:
+ virtual void OnIconImageUpdated(const message_center::NotifierId& id,
+ const gfx::Image& image) = 0;
+ virtual void OnNotifierEnabledChanged(const message_center::NotifierId& id,
+ bool enabled) = 0;
+ };
+
+ NotifierSource() = default;
+ virtual ~NotifierSource() = default;
+
+ // Returns notifiers.
+ // If the source starts loading for icon images, it needs to call
+ // Observer::OnIconImageUpdated after the icon is loaded.
+ virtual std::vector<std::unique_ptr<message_center::Notifier>>
+ GetNotifierList(Profile* profile) = 0;
+
+ // Set notifier enabled. |notifier| must have notifier type that can be
+ // handled by the source. It has responsibility to invoke
+ // Observer::OnNotifierEnabledChanged.
+ virtual void SetNotifierEnabled(Profile* profile,
+ const message_center::Notifier& notifier,
+ bool enabled) = 0;
+
+ // Release temporary resouces tagged with notifier list that is returned last
+ // time.
+ virtual void OnNotifierSettingsClosing() {}
+
+ // Notifier type provided by the source.
+ virtual message_center::NotifierId::NotifierType GetNotifierType() = 0;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(NotifierSource);
+};
+
+#endif // CHROME_BROWSER_NOTIFICATIONS_NOTIFIER_SOURCE_H_
diff --git a/chrome/browser/notifications/system_component_notifier_source_chromeos.cc b/chrome/browser/notifications/system_component_notifier_source_chromeos.cc
new file mode 100644
index 0000000..03d3eed
--- /dev/null
+++ b/chrome/browser/notifications/system_component_notifier_source_chromeos.cc
@@ -0,0 +1,56 @@
+// Copyright (c) 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/notifications/system_component_notifier_source_chromeos.h"
+
+#include "ash/common/system/system_notifier.h"
+#include "chrome/browser/notifications/notifier_state_tracker.h"
+#include "chrome/browser/notifications/notifier_state_tracker_factory.h"
+#include "grit/theme_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/message_center/notifier_settings.h"
+#include "ui/strings/grit/ui_strings.h"
+
+SystemComponentNotifierSourceChromeOS::SystemComponentNotifierSourceChromeOS(
+ Observer* observer)
+ : observer_(observer) {}
+
+std::vector<std::unique_ptr<message_center::Notifier>>
+SystemComponentNotifierSourceChromeOS::GetNotifierList(Profile* profile) {
+ std::vector<std::unique_ptr<message_center::Notifier>> notifiers;
+ NotifierStateTracker* const notifier_state_tracker =
+ NotifierStateTrackerFactory::GetForProfile(profile);
+
+ // Screenshot notification feature is only for ChromeOS. See
+ // crbug.com/238358
+ const base::string16& screenshot_name =
+ l10n_util::GetStringUTF16(IDS_MESSAGE_CENTER_NOTIFIER_SCREENSHOT_NAME);
+ message_center::NotifierId screenshot_notifier_id(
+ message_center::NotifierId::SYSTEM_COMPONENT,
+ ash::system_notifier::kNotifierScreenshot);
+ message_center::Notifier* const screenshot_notifier =
+ new message_center::Notifier(
+ screenshot_notifier_id, screenshot_name,
+ notifier_state_tracker->IsNotifierEnabled(screenshot_notifier_id));
+ screenshot_notifier->icon =
+ ui::ResourceBundle::GetSharedInstance().GetImageNamed(
+ IDR_SCREENSHOT_NOTIFICATION_ICON);
+ notifiers.emplace_back(screenshot_notifier);
+ return notifiers;
+}
+
+void SystemComponentNotifierSourceChromeOS::SetNotifierEnabled(
+ Profile* profile,
+ const message_center::Notifier& notifier,
+ bool enabled) {
+ NotifierStateTrackerFactory::GetForProfile(profile)->SetNotifierEnabled(
+ notifier.notifier_id, enabled);
+ observer_->OnNotifierEnabledChanged(notifier.notifier_id, enabled);
+}
+
+message_center::NotifierId::NotifierType
+SystemComponentNotifierSourceChromeOS::GetNotifierType() {
+ return message_center::NotifierId::SYSTEM_COMPONENT;
+}
diff --git a/chrome/browser/notifications/system_component_notifier_source_chromeos.h b/chrome/browser/notifications/system_component_notifier_source_chromeos.h
new file mode 100644
index 0000000..31250de9
--- /dev/null
+++ b/chrome/browser/notifications/system_component_notifier_source_chromeos.h
@@ -0,0 +1,25 @@
+// Copyright (c) 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_NOTIFICATIONS_SYSTEM_COMPONENT_NOTIFIER_SOURCE_CHROMEOS_H_
+#define CHROME_BROWSER_NOTIFICATIONS_SYSTEM_COMPONENT_NOTIFIER_SOURCE_CHROMEOS_H_
+
+#include "chrome/browser/notifications/notifier_source.h"
+
+class SystemComponentNotifierSourceChromeOS : public NotifierSource {
+ public:
+ explicit SystemComponentNotifierSourceChromeOS(Observer* observer);
+ std::vector<std::unique_ptr<message_center::Notifier>> GetNotifierList(
+ Profile* profile) override;
+ void SetNotifierEnabled(Profile* profile,
+ const message_center::Notifier& notifier,
+ bool enabled) override;
+ message_center::NotifierId::NotifierType GetNotifierType() override;
+
+ private:
+ // Lifetime of parent must be longer than the source.
+ Observer* observer_;
+};
+
+#endif // CHROME_BROWSER_NOTIFICATIONS_SYSTEM_COMPONENT_NOTIFIER_SOURCE_CHROMEOS_H_
diff --git a/chrome/browser/notifications/web_page_notifier_source.cc b/chrome/browser/notifications/web_page_notifier_source.cc
new file mode 100644
index 0000000..74b54cd
--- /dev/null
+++ b/chrome/browser/notifications/web_page_notifier_source.cc
@@ -0,0 +1,144 @@
+// Copyright (c) 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/notifications/web_page_notifier_source.h"
+
+#include "base/strings/utf_string_conversions.h"
+#include "base/task/cancelable_task_tracker.h"
+#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
+#include "chrome/browser/favicon/favicon_service_factory.h"
+#include "chrome/browser/notifications/desktop_notification_profile_util.h"
+#include "chrome/browser/notifications/notifier_state_tracker.h"
+#include "chrome/browser/notifications/notifier_state_tracker_factory.h"
+#include "components/content_settings/core/browser/host_content_settings_map.h"
+#include "components/content_settings/core/common/content_settings.h"
+#include "components/favicon/core/favicon_service.h"
+
+WebPageNotifiereSource::WebPageNotifiereSource(Observer* observer)
+ : observer_(observer) {}
+
+WebPageNotifiereSource::~WebPageNotifiereSource() {}
+
+std::vector<std::unique_ptr<message_center::Notifier>>
+WebPageNotifiereSource::GetNotifierList(Profile* profile) {
+ std::vector<std::unique_ptr<message_center::Notifier>> notifiers;
+
+ ContentSettingsForOneType settings;
+ DesktopNotificationProfileUtil::GetNotificationsSettings(profile, &settings);
+
+ favicon::FaviconService* const favicon_service =
+ FaviconServiceFactory::GetForProfile(profile,
+ ServiceAccessType::EXPLICIT_ACCESS);
+ favicon_tracker_.reset(new base::CancelableTaskTracker());
+ patterns_.clear();
+ for (ContentSettingsForOneType::const_iterator iter = settings.begin();
+ iter != settings.end(); ++iter) {
+ if (iter->primary_pattern == ContentSettingsPattern::Wildcard() &&
+ iter->secondary_pattern == ContentSettingsPattern::Wildcard() &&
+ iter->source != "preference") {
+ continue;
+ }
+
+ std::string url_pattern = iter->primary_pattern.ToString();
+ base::string16 name = base::UTF8ToUTF16(url_pattern);
+ GURL url(url_pattern);
+ message_center::NotifierId notifier_id(url);
+ NotifierStateTracker* const notifier_state_tracker =
+ NotifierStateTrackerFactory::GetForProfile(profile);
+ notifiers.emplace_back(new message_center::Notifier(
+ notifier_id, name,
+ notifier_state_tracker->IsNotifierEnabled(notifier_id)));
+ patterns_[name] = iter->primary_pattern;
+ // Note that favicon service obtains the favicon from history. This means
+ // that it will fail to obtain the image if there are no history data for
+ // that URL.
+ favicon_service->GetFaviconImageForPageURL(
+ url, base::Bind(&WebPageNotifiereSource::OnFaviconLoaded,
+ base::Unretained(this), url),
+ favicon_tracker_.get());
+ }
+
+ return notifiers;
+}
+
+void WebPageNotifiereSource::SetNotifierEnabled(
+ Profile* profile,
+ const message_center::Notifier& notifier,
+ bool enabled) {
+ // WEB_PAGE notifier cannot handle in DesktopNotificationService
+ // since it has the exact URL pattern.
+ // TODO(mukai): fix this.
+ ContentSetting default_setting =
+ HostContentSettingsMapFactory::GetForProfile(profile)
+ ->GetDefaultContentSetting(CONTENT_SETTINGS_TYPE_NOTIFICATIONS, NULL);
+
+ DCHECK(default_setting == CONTENT_SETTING_ALLOW ||
+ default_setting == CONTENT_SETTING_BLOCK ||
+ default_setting == CONTENT_SETTING_ASK);
+
+ // The content setting for notifications needs to clear when it changes to
+ // the default value or get explicitly set when it differs from the
+ // default.
+ bool differs_from_default_value =
+ (default_setting != CONTENT_SETTING_ALLOW && enabled) ||
+ (default_setting == CONTENT_SETTING_ALLOW && !enabled);
+
+ if (differs_from_default_value) {
+ if (notifier.notifier_id.url.is_valid()) {
+ if (enabled) {
+ DesktopNotificationProfileUtil::GrantPermission(
+ profile, notifier.notifier_id.url);
+ } else {
+ DesktopNotificationProfileUtil::DenyPermission(
+ profile, notifier.notifier_id.url);
+ }
+ } else {
+ LOG(ERROR) << "Invalid url pattern: " << notifier.notifier_id.url.spec();
+ }
+ } else {
+ ContentSettingsPattern pattern;
+
+ const auto& iter = patterns_.find(notifier.name);
+ if (iter != patterns_.end()) {
+ pattern = iter->second;
+ } else if (notifier.notifier_id.url.is_valid()) {
+ pattern =
+ ContentSettingsPattern::FromURLNoWildcard(notifier.notifier_id.url);
+ } else {
+ LOG(ERROR) << "Invalid url pattern: " << notifier.notifier_id.url.spec();
+ }
+
+ if (pattern.IsValid()) {
+ // Note that we don't use
+ // DesktopNotificationProfileUtil::ClearSetting()
+ // here because pattern might be from user manual input and not match
+ // the default one used by ClearSetting().
+ HostContentSettingsMapFactory::GetForProfile(profile)
+ ->SetContentSettingCustomScope(
+ pattern, ContentSettingsPattern::Wildcard(),
+ CONTENT_SETTINGS_TYPE_NOTIFICATIONS,
+ content_settings::ResourceIdentifier(), CONTENT_SETTING_DEFAULT);
+ }
+ }
+
+ observer_->OnNotifierEnabledChanged(notifier.notifier_id, enabled);
+}
+
+void WebPageNotifiereSource::OnNotifierSettingsClosing() {
+ DCHECK(favicon_tracker_.get());
+ favicon_tracker_->TryCancelAll();
+ patterns_.clear();
+}
+
+message_center::NotifierId::NotifierType
+WebPageNotifiereSource::GetNotifierType() {
+ return message_center::NotifierId::WEB_PAGE;
+}
+
+void WebPageNotifiereSource::OnFaviconLoaded(
+ const GURL& url,
+ const favicon_base::FaviconImageResult& favicon_result) {
+ observer_->OnIconImageUpdated(message_center::NotifierId(url),
+ favicon_result.image);
+}
diff --git a/chrome/browser/notifications/web_page_notifier_source.h b/chrome/browser/notifications/web_page_notifier_source.h
new file mode 100644
index 0000000..2b9fe38
--- /dev/null
+++ b/chrome/browser/notifications/web_page_notifier_source.h
@@ -0,0 +1,48 @@
+// Copyright (c) 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_NOTIFICATIONS_WEB_PAGE_NOTIFIER_SOURCE_H_
+#define CHROME_BROWSER_NOTIFICATIONS_WEB_PAGE_NOTIFIER_SOURCE_H_
+
+#include "chrome/browser/notifications/notifier_source.h"
+#include "components/content_settings/core/common/content_settings_pattern.h"
+
+namespace base {
+class CancelableTaskTracker;
+}
+
+namespace favicon_base {
+struct FaviconImageResult;
+}
+
+class WebPageNotifiereSource : public NotifierSource {
+ public:
+ explicit WebPageNotifiereSource(Observer* observer);
+ ~WebPageNotifiereSource() override;
+
+ std::vector<std::unique_ptr<message_center::Notifier>> GetNotifierList(
+ Profile* profile) override;
+
+ void SetNotifierEnabled(Profile* profile,
+ const message_center::Notifier& notifier,
+ bool enabled) override;
+
+ void OnNotifierSettingsClosing() override;
+
+ message_center::NotifierId::NotifierType GetNotifierType() override;
+
+ private:
+ void OnFaviconLoaded(const GURL& url,
+ const favicon_base::FaviconImageResult& favicon_result);
+
+ std::map<base::string16, ContentSettingsPattern> patterns_;
+
+ // The task tracker for loading favicons.
+ std::unique_ptr<base::CancelableTaskTracker> favicon_tracker_;
+
+ // Lifetime of parent must be longer than the source.
+ Observer* observer_;
+};
+
+#endif // CHROME_BROWSER_NOTIFICATIONS_WEB_PAGE_NOTIFIER_SOURCE_H_