1// Copyright 2014 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#ifndef CHROME_BROWSER_NOTIFICATIONS_EXTENSION_WELCOME_NOTIFICATION_H_
6#define CHROME_BROWSER_NOTIFICATIONS_EXTENSION_WELCOME_NOTIFICATION_H_
7
8#include <string>
9
10#include "base/memory/scoped_ptr.h"
11#include "base/prefs/pref_member.h"
12#include "base/timer/timer.h"
13#include "chrome/browser/prefs/pref_service_syncable_observer.h"
14#include "components/keyed_service/core/keyed_service.h"
15#include "ui/message_center/notifier_settings.h"
16
17namespace base {
18typedef Callback<void(void)> Closure;
19}
20
21namespace message_center {
22class MessageCenter;
23}
24
25namespace tracked_objects {
26class Location;
27}
28
29namespace user_prefs {
30class PrefRegistrySyncable;
31}
32
33class Notification;
34class Profile;
35
36// ExtensionWelcomeNotification is a keyed service which manages showing and
37// hiding a welcome notification for built-in components that show
38// notifications. The Welcome Notification presumes network connectivity since
39// it relies on synced preferences to work. This is generally fine since the
40// current consumers on the welcome notification also presume network
41// connectivity.
42//
43// This class expects to be created and called from the UI thread.
44class ExtensionWelcomeNotification : public KeyedService,
45                                     public PrefServiceSyncableObserver {
46 public:
47  // Allows for overriding global calls.
48  class Delegate {
49   public:
50    Delegate() {}
51    virtual ~Delegate() {}
52    virtual message_center::MessageCenter* GetMessageCenter() = 0;
53    virtual base::Time GetCurrentTime() = 0;
54    virtual void PostTask(
55        const tracked_objects::Location& from_here,
56        const base::Closure& task) = 0;
57   private:
58    DISALLOW_COPY_AND_ASSIGN(Delegate);
59  };
60
61  // Requested time from showing the welcome notification to expiration.
62  static const int kRequestedShowTimeDays;
63
64  // The extension Id associated with the Google Now extension.
65  static const char kChromeNowExtensionID[];
66
67  virtual ~ExtensionWelcomeNotification();
68
69  // To workaround the lack of delegating constructors prior to C++11, we use
70  // static Create methods.
71  // Creates an ExtensionWelcomeNotification with the default delegate.
72  static ExtensionWelcomeNotification* Create(Profile* const profile);
73
74  // Creates an ExtensionWelcomeNotification with the specified delegate.
75  static ExtensionWelcomeNotification* Create(Profile* const profile,
76                                              Delegate* const delegate);
77
78  // PrefServiceSyncableObserver
79  virtual void OnIsSyncingChanged() OVERRIDE;
80
81  // Adds in the welcome notification if required for components built
82  // into Chrome that show notifications like Chrome Now.
83  void ShowWelcomeNotificationIfNecessary(const Notification& notification);
84
85  // Handles Preference Registration for the Welcome Notification.
86  static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* prefs);
87
88 private:
89  enum PopUpRequest { POP_UP_HIDDEN = 0, POP_UP_SHOWN = 1, };
90
91  ExtensionWelcomeNotification(
92      Profile* const profile,
93      ExtensionWelcomeNotification::Delegate* const delegate);
94
95  // Gets the message center from the delegate.
96  message_center::MessageCenter* GetMessageCenter() const;
97
98  // Unconditionally shows the welcome notification.
99  void ShowWelcomeNotification(const base::string16& display_source,
100                               const PopUpRequest pop_up_request);
101
102  // Hides the welcome notification.
103  void HideWelcomeNotification();
104
105  // Whether the notification has been dismissed.
106  bool UserHasDismissedWelcomeNotification() const;
107
108  // Called when the Welcome Notification Dismissed pref has been changed.
109  void OnWelcomeNotificationDismissedChanged();
110
111  // Starts the welcome notification expiration timer.
112  void StartExpirationTimer();
113
114  // Stops the welcome notification expiration timer.
115  void StopExpirationTimer();
116
117  // Expires the welcome notification by hiding it and marking it dismissed.
118  void ExpireWelcomeNotification();
119
120  // Gets the expiration timestamp or a null time is there is none.
121  base::Time GetExpirationTimestamp() const;
122
123  // Sets the expiration timestamp from now.
124  void SetExpirationTimestampFromNow();
125
126  // True if the welcome notification has expired, false otherwise.
127  bool IsWelcomeNotificationExpired() const;
128
129  // Prefs listener for welcome_notification_dismissed.
130  BooleanPrefMember welcome_notification_dismissed_pref_;
131
132  // Prefs listener for welcome_notification_dismissed_local.
133  // Dismissal flag migrated from a synced pref to a local one.
134  BooleanPrefMember welcome_notification_dismissed_local_pref_;
135
136  // The notifier for the extension that we're listening for.
137  message_center::NotifierId notifier_id_;
138
139  // The profile which owns this object.
140  Profile* profile_;
141
142  // Notification ID of the Welcome Notification.
143  std::string welcome_notification_id_;
144
145  // If the preferences are still syncing, store the last notification here
146  // so we can replay ShowWelcomeNotificationIfNecessary once the sync finishes.
147  // Simplifying Assumption: The delayed notification has passed the
148  // extension ID check. This means we do not need to store all of the
149  // notifications that may also show a welcome notification.
150  scoped_ptr<Notification> delayed_notification_;
151
152  // If the welcome notification is shown, this timer tracks when to hide the
153  // welcome notification.
154  scoped_ptr<base::OneShotTimer<ExtensionWelcomeNotification> >
155      expiration_timer_;
156
157  // Delegate for Chrome global calls like base::Time::GetTime() for
158  // testability.
159  scoped_ptr<Delegate> delegate_;
160
161  DISALLOW_COPY_AND_ASSIGN(ExtensionWelcomeNotification);
162};
163
164#endif  // CHROME_BROWSER_NOTIFICATIONS_EXTENSION_WELCOME_NOTIFICATION_H_
165