root/chrome/browser/notifications/sync_notifier/chrome_notifier_service.h

/* [<][>][^][v][top][bottom][index][help] */

INCLUDED FROM


// Copyright (c) 2012 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_SYNC_NOTIFIER_CHROME_NOTIFIER_SERVICE_H_
#define CHROME_BROWSER_NOTIFICATIONS_SYNC_NOTIFIER_CHROME_NOTIFIER_SERVICE_H_

#include <set>
#include <string>

#include "base/basictypes.h"
#include "base/memory/scoped_vector.h"
#include "base/prefs/pref_member.h"
#include "base/threading/thread_checker.h"
#include "chrome/browser/notifications/notification.h"
#include "chrome/browser/notifications/sync_notifier/synced_notification.h"
#include "components/keyed_service/core/keyed_service.h"
#include "sync/api/syncable_service.h"
#include "ui/message_center/notifier_settings.h"

class NotificationUIManager;
class Profile;

namespace user_prefs {
class PrefRegistrySyncable;
}

namespace message_center {
struct Notifier;
}

namespace notifier {
class SyncedNotificationAppInfo;
class SyncedNotificationAppInfoService;

// The name of our first synced notification service.
// TODO(petewil): Remove this once we figure out how to do UMA for each sending
// service name without knowing the name in advance.
extern const char kFirstSyncedNotificationServiceId[];
extern const char kServiceEnabledOnce[];
extern const char kSyncedNotificationFirstRun[];
extern const char kSyncedNotificationsWelcomeOrigin[];

enum ChromeNotifierServiceActionType {
  CHROME_NOTIFIER_SERVICE_ACTION_UNKNOWN,
  CHROME_NOTIFIER_SERVICE_ACTION_FIRST_SERVICE_ENABLED,
  CHROME_NOTIFIER_SERVICE_ACTION_FIRST_SERVICE_DISABLED,
  // NOTE: Add new action types only immediately above this line. Also,
  // make sure the enum list in tools/histogram/histograms.xml is
  // updated with any change in here.
  CHROME_NOTIFIER_SERVICE_ACTION_COUNT
};

// The ChromeNotifierService holds notifications which represent the state of
// delivered notifications for chrome. These are obtained from the sync service
// and kept up to date.
class ChromeNotifierService : public syncer::SyncableService,
                              public KeyedService {
 public:
  ChromeNotifierService(Profile* profile, NotificationUIManager* manager);
  virtual ~ChromeNotifierService();

  // Methods from KeyedService.
  virtual void Shutdown() OVERRIDE;

  // syncer::SyncableService implementation.
  virtual syncer::SyncMergeResult MergeDataAndStartSyncing(
      syncer::ModelType type,
      const syncer::SyncDataList& initial_sync_data,
      scoped_ptr<syncer::SyncChangeProcessor> sync_processor,
      scoped_ptr<syncer::SyncErrorFactory> error_handler) OVERRIDE;
  virtual void StopSyncing(syncer::ModelType type) OVERRIDE;
  virtual syncer::SyncDataList GetAllSyncData(
      syncer::ModelType type) const OVERRIDE;
  virtual syncer::SyncError ProcessSyncChanges(
      const tracked_objects::Location& from_here,
      const syncer::SyncChangeList& change_list) OVERRIDE;

  // Convert from internal representation to SyncData representation.
  static syncer::SyncData CreateSyncDataFromNotification(
      const SyncedNotification& notification);

  // Convert from SyncData representation to internal representation.
  scoped_ptr<SyncedNotification> CreateNotificationFromSyncData(
      const syncer::SyncData& sync_data);

  // Get a pointer to a notification.  ChromeNotifierService owns this pointer.
  virtual notifier::SyncedNotification* FindNotificationById(
      const std::string& notification_id);

  // Get the list of synced notification services and fill their meta data to
  // |notifiers|.
  void GetSyncedNotificationServices(
      std::vector<message_center::Notifier*>* notifiers);

  // Called when we dismiss a notification.  This is virtual so that test
  // subclasses can override it.
  virtual void MarkNotificationAsRead(const std::string& id);

  // Called when a notier is enabled or disabled.
  void OnSyncedNotificationServiceEnabled(
      const std::string& notifier_id,
      bool enabled);

  // When app ids are added or removed, unblock or remove associated messages.
  void OnAddedAppIds(std::vector<std::string> added_app_ids);
  void OnRemovedAppIds(std::vector<std::string> removed_app_ids);

  // Register the preferences we use to save state.
  static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);

  Profile* profile() const { return profile_; }

  // Find and retun the sending service Id for this notification.
  std::string GetSendingServiceId(
      const SyncedNotification* synced_notification);

  // Functions for test.
  void AddForTest(scoped_ptr<notifier::SyncedNotification> notification);

  void SetSyncedNotificationAppInfoServiceForTest(
      SyncedNotificationAppInfoService* synced_notification_app_info_service);

  // If we allow the tests to do bitmap fetching, they will attempt to fetch
  // a URL from the web, which will fail.  We can already test the majority
  // of what we want without also trying to fetch bitmaps.  Other tests will
  // cover bitmap fetching.
  static void set_avoid_bitmap_fetching_for_test(bool avoid) {
    avoid_bitmap_fetching_for_test_ = avoid;
  }

  // Initialize the preferences we use for the ChromeNotificationService.
  void InitializePrefs();

  void ShowWelcomeToastIfNecessary(
      const SyncedNotification* notification,
      NotificationUIManager* notification_ui_manager);

 private:
  // Add a notification to our list.  This takes ownership of the pointer.
  void Add(scoped_ptr<notifier::SyncedNotification> notification);

  // Display this notification in the notification center, or remove it.
  void UpdateInMessageCenter(notifier::SyncedNotification* notification);

  // Display a notification in the notification center (eventually).
  void Display(notifier::SyncedNotification* notification);

  // Remove a notification from our store.
  void FreeNotificationById(const std::string& notification_id);

  // When a service it turned on, scan our cache for any notifications
  // for that service, and display them if they are unread.
  void DisplayUnreadNotificationsFromSource(const std::string& notifier_id);

  // When a service it turned off, scan our cache for any notifications
  // for that service, and remove them from the message center.
  void RemoveUnreadNotificationsFromSource(const std::string& notifier_id);

  // When we turn a sending service on or off, collect statistics about
  // how often users turn it on or off.
  void CollectPerServiceEnablingStatistics(const std::string& notifier_id,
                                           bool enabled);

  // Called when the string list pref has been changed.
  void OnEnabledSendingServiceListPrefChanged(std::set<std::string>* ids_field);

  // Called when the string list pref has been changed.
  void OnInitializedSendingServiceListPrefChanged(
      std::set<std::string>* ids_field);

  // Called when our "first run" boolean pref has been changed.
  void OnSyncedNotificationFirstRunBooleanPrefChanged(bool* new_value);

  // Convert our internal set of strings to a list value.
  // The second param is an outparam which the function fills in.
  void BuildServiceListValueInplace(
      std::set<std::string> services, base::ListValue* list_value);

  // Finds an app info by using the AppId
  notifier::SyncedNotificationAppInfo* FindAppInfoByAppId(
      const std::string& app_id) const;

  // Builds a welcome notification for the listed sending service.
  const Notification CreateWelcomeNotificationForService(
      SyncedNotificationAppInfo* app_info);

  // Preferences for storing which SyncedNotificationServices are enabled
  StringListPrefMember enabled_sending_services_prefs_;
  StringListPrefMember initialized_sending_services_prefs_;

  // Preferences to avoid toasting on SyncedNotification first run.
  BooleanPrefMember synced_notification_first_run_prefs_;

  // Back pointer to the owning profile.
  Profile* const profile_;
  NotificationUIManager* const notification_manager_;
  scoped_ptr<syncer::SyncChangeProcessor> sync_processor_;
  std::set<std::string> enabled_sending_services_;
  std::set<std::string> initialized_sending_services_;
  bool synced_notification_first_run_;
  static bool avoid_bitmap_fetching_for_test_;
  base::ThreadChecker thread_checker_;
  // Unowned pointer to the App Info service.  The lifetime is managed by the
  // profile service, this service depends on the App Info service, so it should
  // always be in scope whenever our service is active.
  SyncedNotificationAppInfoService* synced_notification_app_info_service_;

  // TODO(petewil): Consider whether a map would better suit our data.
  // If there are many entries, lookup time may trump locality of reference.
  ScopedVector<SyncedNotification> notification_data_;

  friend class ChromeNotifierServiceTest;
  FRIEND_TEST_ALL_PREFIXES(ChromeNotifierServiceTest, ServiceEnabledTest);
  FRIEND_TEST_ALL_PREFIXES(ChromeNotifierServiceTest,
                           AddNewSendingServicesTest);
  FRIEND_TEST_ALL_PREFIXES(ChromeNotifierServiceTest,
                           CheckInitializedServicesTest);
  FRIEND_TEST_ALL_PREFIXES(ChromeNotifierServiceTest,
                           GetEnabledSendingServicesFromPreferencesTest);
  FRIEND_TEST_ALL_PREFIXES(ChromeNotifierServiceTest, CheckFindAppInfo);
  FRIEND_TEST_ALL_PREFIXES(ChromeNotifierServiceTest, SetAddedAppIdsTest);
  FRIEND_TEST_ALL_PREFIXES(ChromeNotifierServiceTest, SetRemovedAppIdsTest);

  DISALLOW_COPY_AND_ASSIGN(ChromeNotifierService);
};

}  // namespace notifier

#endif  // CHROME_BROWSER_NOTIFICATIONS_SYNC_NOTIFIER_CHROME_NOTIFIER_SERVICE_H_

/* [<][>][^][v][top][bottom][index][help] */