15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
25d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// found in the LICENSE file.
45d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#ifndef CHROME_BROWSER_NOTIFICATIONS_EXTENSION_WELCOME_NOTIFICATION_H_
65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#define CHROME_BROWSER_NOTIFICATIONS_EXTENSION_WELCOME_NOTIFICATION_H_
75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <string>
95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/prefs/pref_member.h"
125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/timer/timer.h"
135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/prefs/pref_service_syncable_observer.h"
141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "components/keyed_service/core/keyed_service.h"
155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/message_center/notifier_settings.h"
165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace base {
185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)typedef Callback<void(void)> Closure;
195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace message_center {
225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class MessageCenter;
235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace tracked_objects {
265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class Location;
275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace user_prefs {
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class PrefRegistrySyncable;
315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class Notification;
345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class Profile;
355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// ExtensionWelcomeNotification is a keyed service which manages showing and
371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// hiding a welcome notification for built-in components that show
381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// notifications. The Welcome Notification presumes network connectivity since
391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// it relies on synced preferences to work. This is generally fine since the
401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// current consumers on the welcome notification also presume network
411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// connectivity.
421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci//
435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// This class expects to be created and called from the UI thread.
441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciclass ExtensionWelcomeNotification : public KeyedService,
451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                     public PrefServiceSyncableObserver {
465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public:
475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Allows for overriding global calls.
485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  class Delegate {
495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)   public:
505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    Delegate() {}
515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    virtual ~Delegate() {}
525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    virtual message_center::MessageCenter* GetMessageCenter() = 0;
535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    virtual base::Time GetCurrentTime() = 0;
545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    virtual void PostTask(
555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        const tracked_objects::Location& from_here,
565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        const base::Closure& task) = 0;
575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)   private:
585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DISALLOW_COPY_AND_ASSIGN(Delegate);
595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  };
605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Requested time from showing the welcome notification to expiration.
625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  static const int kRequestedShowTimeDays;
635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // The extension Id associated with the Google Now extension.
651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  static const char kChromeNowExtensionID[];
661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual ~ExtensionWelcomeNotification();
685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // To workaround the lack of delegating constructors prior to C++11, we use
705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // static Create methods.
711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Creates an ExtensionWelcomeNotification with the default delegate.
721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  static ExtensionWelcomeNotification* Create(Profile* const profile);
731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Creates an ExtensionWelcomeNotification with the specified delegate.
751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  static ExtensionWelcomeNotification* Create(Profile* const profile,
761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                              Delegate* const delegate);
775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // PrefServiceSyncableObserver
795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void OnIsSyncingChanged() OVERRIDE;
805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Adds in the welcome notification if required for components built
825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // into Chrome that show notifications like Chrome Now.
835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void ShowWelcomeNotificationIfNecessary(const Notification& notification);
845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Handles Preference Registration for the Welcome Notification.
865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* prefs);
875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private:
895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  enum PopUpRequest { POP_UP_HIDDEN = 0, POP_UP_SHOWN = 1, };
905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ExtensionWelcomeNotification(
925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      Profile* const profile,
935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      ExtensionWelcomeNotification::Delegate* const delegate);
945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Gets the message center from the delegate.
965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  message_center::MessageCenter* GetMessageCenter() const;
975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Unconditionally shows the welcome notification.
995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void ShowWelcomeNotification(const base::string16& display_source,
1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                               const PopUpRequest pop_up_request);
1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Hides the welcome notification.
1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void HideWelcomeNotification();
1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1050529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  // Whether the notification has been dismissed.
1060529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  bool UserHasDismissedWelcomeNotification() const;
1070529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Called when the Welcome Notification Dismissed pref has been changed.
1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void OnWelcomeNotificationDismissedChanged();
1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Starts the welcome notification expiration timer.
1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void StartExpirationTimer();
1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Stops the welcome notification expiration timer.
1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void StopExpirationTimer();
1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Expires the welcome notification by hiding it and marking it dismissed.
1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void ExpireWelcomeNotification();
1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Gets the expiration timestamp or a null time is there is none.
1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::Time GetExpirationTimestamp() const;
1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Sets the expiration timestamp from now.
1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void SetExpirationTimestampFromNow();
1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // True if the welcome notification has expired, false otherwise.
1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bool IsWelcomeNotificationExpired() const;
1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Prefs listener for welcome_notification_dismissed.
1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  BooleanPrefMember welcome_notification_dismissed_pref_;
1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1320529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  // Prefs listener for welcome_notification_dismissed_local.
1330529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  // Dismissal flag migrated from a synced pref to a local one.
1340529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  BooleanPrefMember welcome_notification_dismissed_local_pref_;
1350529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // The notifier for the extension that we're listening for.
1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  message_center::NotifierId notifier_id_;
1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // The profile which owns this object.
1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  Profile* profile_;
1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Notification ID of the Welcome Notification.
1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string welcome_notification_id_;
1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // If the preferences are still syncing, store the last notification here
1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // so we can replay ShowWelcomeNotificationIfNecessary once the sync finishes.
1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Simplifying Assumption: The delayed notification has passed the
1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // extension ID check. This means we do not need to store all of the
1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // notifications that may also show a welcome notification.
1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<Notification> delayed_notification_;
1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // If the welcome notification is shown, this timer tracks when to hide the
1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // welcome notification.
1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<base::OneShotTimer<ExtensionWelcomeNotification> >
1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      expiration_timer_;
1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Delegate for Chrome global calls like base::Time::GetTime() for
1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // testability.
1595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<Delegate> delegate_;
1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(ExtensionWelcomeNotification);
1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)};
1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif  // CHROME_BROWSER_NOTIFICATIONS_EXTENSION_WELCOME_NOTIFICATION_H_
165