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)#include "chrome/browser/notifications/extension_welcome_notification.h"
65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/guid.h"
85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/lazy_instance.h"
95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/message_loop/message_loop.h"
105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/prefs/pref_service.h"
115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/browser_process.h"
135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/notifications/notification.h"
145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/prefs/pref_service_syncable.h"
155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/profiles/profile.h"
165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/ui/browser_navigator.h"
175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/common/pref_names.h"
185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/common/url_constants.h"
19cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "components/pref_registry/pref_registry_syncable.h"
205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "grit/generated_resources.h"
215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "grit/theme_resources.h"
225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/base/l10n/l10n_util.h"
235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/base/resource/resource_bundle.h"
245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/message_center/message_center.h"
255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/message_center/notification.h"
265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/message_center/notification_delegate.h"
275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/message_center/notification_types.h"
285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
290529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochconst int ExtensionWelcomeNotification::kRequestedShowTimeDays = 14;
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace {
325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class NotificationCallbacks
345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    : public message_center::NotificationDelegate {
355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public:
365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  NotificationCallbacks(
375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      Profile* profile,
380529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      const message_center::NotifierId notifier_id,
390529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      const std::string& welcome_notification_id,
405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      ExtensionWelcomeNotification::Delegate* delegate)
415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      : profile_(profile),
420529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        notifier_id_(notifier_id.type, notifier_id.id),
430529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        welcome_notification_id_(welcome_notification_id),
445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        delegate_(delegate) {
455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Overridden from NotificationDelegate:
485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void Display() OVERRIDE {}
495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void Error() OVERRIDE {}
505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void Close(bool by_user) OVERRIDE {
525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (by_user) {
535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // Setting the preference here may cause the notification erasing
545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // to reenter. Posting a task avoids this issue.
555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      delegate_->PostTask(
565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          FROM_HERE,
575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          base::Bind(&NotificationCallbacks::MarkAsDismissed, this));
585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void Click() OVERRIDE {}
625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void ButtonClick(int index) OVERRIDE {
630529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    if (index == 0) {
640529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      OpenNotificationLearnMoreTab();
650529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    } else if (index == 1) {
660529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      DisableNotificationProvider();
670529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      Close(true);
680529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    } else {
690529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      NOTREACHED();
700529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    }
715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private:
745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void MarkAsDismissed() {
750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    profile_->GetPrefs()->SetBoolean(prefs::kWelcomeNotificationDismissedLocal,
765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                     true);
775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void OpenNotificationLearnMoreTab() {
805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    chrome::NavigateParams params(
815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        profile_,
825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        GURL(chrome::kNotificationWelcomeLearnMoreURL),
835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        content::PAGE_TRANSITION_LINK);
845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    params.disposition = NEW_FOREGROUND_TAB;
855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    params.window_action = chrome::NavigateParams::SHOW_WINDOW;
865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    chrome::Navigate(&params);
875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
890529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  void DisableNotificationProvider() {
900529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    message_center::Notifier notifier(notifier_id_, base::string16(), true);
910529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    message_center::MessageCenter* message_center =
920529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        delegate_->GetMessageCenter();
930529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    message_center->DisableNotificationsByNotifier(notifier_id_);
945c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    message_center->RemoveNotification(welcome_notification_id_, false);
950529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    message_center->GetNotifierSettingsProvider()->SetNotifierEnabled(
960529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        notifier, false);
970529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  }
980529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual ~NotificationCallbacks() {}
1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  Profile* const profile_;
1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1030529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  const message_center::NotifierId notifier_id_;
1040529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
1050529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  std::string welcome_notification_id_;
1060529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Weak ref owned by ExtensionWelcomeNotification.
1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ExtensionWelcomeNotification::Delegate* const delegate_;
1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(NotificationCallbacks);
1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)};
1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class DefaultDelegate : public ExtensionWelcomeNotification::Delegate {
1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public:
1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DefaultDelegate() {}
1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual message_center::MessageCenter* GetMessageCenter() OVERRIDE {
1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return g_browser_process->message_center();
1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual base::Time GetCurrentTime() OVERRIDE {
1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return base::Time::Now();
1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void PostTask(
1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      const tracked_objects::Location& from_here,
1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      const base::Closure& task) OVERRIDE {
1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::MessageLoop::current()->PostTask(from_here, task);
1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private:
1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(DefaultDelegate);
1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)};
1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}  // namespace
1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)ExtensionWelcomeNotification::ExtensionWelcomeNotification(
1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const std::string& extension_id,
1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    Profile* const profile,
1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ExtensionWelcomeNotification::Delegate* const delegate)
1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    : notifier_id_(message_center::NotifierId::APPLICATION, extension_id),
1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      profile_(profile),
1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      delegate_(delegate) {
1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  welcome_notification_dismissed_pref_.Init(
1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      prefs::kWelcomeNotificationDismissed,
1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      profile_->GetPrefs(),
1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::Bind(
1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          &ExtensionWelcomeNotification::OnWelcomeNotificationDismissedChanged,
1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          base::Unretained(this)));
1500529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  welcome_notification_dismissed_local_pref_.Init(
1510529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      prefs::kWelcomeNotificationDismissedLocal,
1520529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      profile_->GetPrefs());
1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// static
1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)scoped_ptr<ExtensionWelcomeNotification> ExtensionWelcomeNotification::Create(
1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const std::string& extension_id,
1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    Profile* const profile) {
1595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return Create(extension_id, profile, new DefaultDelegate()).Pass();
1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// static
1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)scoped_ptr<ExtensionWelcomeNotification> ExtensionWelcomeNotification::Create(
1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const std::string& extension_id,
1655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    Profile* const profile,
1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    Delegate* const delegate) {
1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return scoped_ptr<ExtensionWelcomeNotification>(
1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      new ExtensionWelcomeNotification(extension_id, profile, delegate)).Pass();
1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)ExtensionWelcomeNotification::~ExtensionWelcomeNotification() {
1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (delayed_notification_) {
1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    delayed_notification_.reset();
1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    PrefServiceSyncable::FromProfile(profile_)->RemoveObserver(this);
1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  } else {
1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    HideWelcomeNotification();
1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ExtensionWelcomeNotification::OnIsSyncingChanged() {
1815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(delayed_notification_);
1825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  PrefServiceSyncable* const pref_service_syncable =
1835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      PrefServiceSyncable::FromProfile(profile_);
1845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (pref_service_syncable->IsSyncing()) {
1855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    pref_service_syncable->RemoveObserver(this);
1865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    scoped_ptr<Notification> previous_notification(
1875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        delayed_notification_.release());
1885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ShowWelcomeNotificationIfNecessary(*(previous_notification.get()));
1895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ExtensionWelcomeNotification::ShowWelcomeNotificationIfNecessary(
1935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const Notification& notification) {
1945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if ((notification.notifier_id() == notifier_id_) && !delayed_notification_) {
1955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    PrefServiceSyncable* const pref_service_syncable =
1965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        PrefServiceSyncable::FromProfile(profile_);
1975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (pref_service_syncable->IsSyncing()) {
1985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      PrefService* const pref_service = profile_->GetPrefs();
1990529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      if (!UserHasDismissedWelcomeNotification()) {
2005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        const PopUpRequest pop_up_request =
2015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            pref_service->GetBoolean(
2025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                prefs::kWelcomeNotificationPreviouslyPoppedUp)
2035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                ? POP_UP_HIDDEN
2045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                : POP_UP_SHOWN;
2055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if (pop_up_request == POP_UP_SHOWN) {
2065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          pref_service->SetBoolean(
2075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)              prefs::kWelcomeNotificationPreviouslyPoppedUp, true);
2085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        }
2095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if (IsWelcomeNotificationExpired()) {
2115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          ExpireWelcomeNotification();
2125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        } else {
2135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          ShowWelcomeNotification(
2145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)              notification.display_source(), pop_up_request);
2155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        }
2165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      }
2175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    } else {
2185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      delayed_notification_.reset(new Notification(notification));
2195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      pref_service_syncable->AddObserver(this);
2205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
2215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
2225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// static
2255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ExtensionWelcomeNotification::RegisterProfilePrefs(
2265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    user_prefs::PrefRegistrySyncable* prefs) {
2275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  prefs->RegisterBooleanPref(prefs::kWelcomeNotificationDismissed,
2285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                             false,
2295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                             user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
2300529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  prefs->RegisterBooleanPref(prefs::kWelcomeNotificationDismissedLocal,
2310529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                             false,
2320529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                             user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
2335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  prefs->RegisterBooleanPref(prefs::kWelcomeNotificationPreviouslyPoppedUp,
2345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                             false,
2355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                             user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
2365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  prefs->RegisterInt64Pref(prefs::kWelcomeNotificationExpirationTimestamp,
2375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           0,
2385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
2395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)message_center::MessageCenter*
2425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)ExtensionWelcomeNotification::GetMessageCenter() const {
2435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return delegate_->GetMessageCenter();
2445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ExtensionWelcomeNotification::ShowWelcomeNotification(
2475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const base::string16& display_source,
2485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const PopUpRequest pop_up_request) {
2495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  message_center::ButtonInfo learn_more(
2505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      l10n_util::GetStringUTF16(IDS_NOTIFICATION_WELCOME_BUTTON_LEARN_MORE));
2515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  learn_more.icon = ui::ResourceBundle::GetSharedInstance().GetImageNamed(
2525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      IDR_NOTIFICATION_WELCOME_LEARN_MORE);
2530529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  message_center::ButtonInfo disable(
2540529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      l10n_util::GetStringUTF16(IDS_NOTIFIER_WELCOME_BUTTON));
2550529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  disable.icon = ui::ResourceBundle::GetSharedInstance().GetImageNamed(
2560529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      IDR_NOTIFIER_BLOCK_BUTTON);
2575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  message_center::RichNotificationData rich_notification_data;
2595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  rich_notification_data.priority = 2;
2605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  rich_notification_data.buttons.push_back(learn_more);
2610529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  rich_notification_data.buttons.push_back(disable);
2625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (welcome_notification_id_.empty())
2645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    welcome_notification_id_ = base::GenerateGUID();
2655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!welcome_notification_id_.empty()) {
2675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    scoped_ptr<message_center::Notification> message_center_notification(
2685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        new message_center::Notification(
2695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            message_center::NOTIFICATION_TYPE_BASE_FORMAT,
2705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            welcome_notification_id_,
2715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            l10n_util::GetStringUTF16(IDS_NOTIFICATION_WELCOME_TITLE),
2725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            l10n_util::GetStringUTF16(IDS_NOTIFICATION_WELCOME_BODY),
2735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            ui::ResourceBundle::GetSharedInstance().GetImageNamed(
2745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                IDR_NOTIFICATION_WELCOME_ICON),
2755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            display_source,
2765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            notifier_id_,
2775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            rich_notification_data,
2780529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch            new NotificationCallbacks(
2790529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                profile_, notifier_id_, welcome_notification_id_,
2800529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                delegate_.get())));
2815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (pop_up_request == POP_UP_HIDDEN)
2835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      message_center_notification->set_shown_as_popup(true);
2845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    GetMessageCenter()->AddNotification(message_center_notification.Pass());
2865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    StartExpirationTimer();
2875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
2885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ExtensionWelcomeNotification::HideWelcomeNotification() {
2915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!welcome_notification_id_.empty() &&
292f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      GetMessageCenter()->FindVisibleNotificationById(
293f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          welcome_notification_id_) != NULL) {
2945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    GetMessageCenter()->RemoveNotification(welcome_notification_id_, false);
2955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    StopExpirationTimer();
2965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
2975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2990529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochbool ExtensionWelcomeNotification::UserHasDismissedWelcomeNotification() const {
3000529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  // This was previously a syncable preference; now it's per-machine.
3010529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  // Only the local pref will be written moving forward, but check for both so
3020529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  // users won't be double-toasted.
3030529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  bool shown_synced = profile_->GetPrefs()->GetBoolean(
3040529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      prefs::kWelcomeNotificationDismissed);
3050529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  bool shown_local = profile_->GetPrefs()->GetBoolean(
3060529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      prefs::kWelcomeNotificationDismissedLocal);
3070529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  return (shown_synced || shown_local);
3080529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
3090529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
3105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ExtensionWelcomeNotification::OnWelcomeNotificationDismissedChanged() {
3110529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (UserHasDismissedWelcomeNotification()) {
3125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    HideWelcomeNotification();
3130529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  }
3145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
3155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ExtensionWelcomeNotification::StartExpirationTimer() {
3175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!expiration_timer_ && !IsWelcomeNotificationExpired()) {
3185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::Time expiration_timestamp = GetExpirationTimestamp();
3195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (expiration_timestamp.is_null()) {
3205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      SetExpirationTimestampFromNow();
3215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      expiration_timestamp = GetExpirationTimestamp();
3225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      DCHECK(!expiration_timestamp.is_null());
3235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
3245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    expiration_timer_.reset(
3255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        new base::OneShotTimer<ExtensionWelcomeNotification>());
3265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    expiration_timer_->Start(
3275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        FROM_HERE,
3285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        expiration_timestamp - delegate_->GetCurrentTime(),
3295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        this,
3305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        &ExtensionWelcomeNotification::ExpireWelcomeNotification);
3315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
3325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
3335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ExtensionWelcomeNotification::StopExpirationTimer() {
3355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (expiration_timer_) {
3365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    expiration_timer_->Stop();
3375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    expiration_timer_.reset();
3385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
3395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
3405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ExtensionWelcomeNotification::ExpireWelcomeNotification() {
3425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(IsWelcomeNotificationExpired());
3430529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  profile_->GetPrefs()->SetBoolean(
3440529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      prefs::kWelcomeNotificationDismissedLocal, true);
3455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  HideWelcomeNotification();
3465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
3475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)base::Time ExtensionWelcomeNotification::GetExpirationTimestamp() const {
3495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  PrefService* const pref_service = profile_->GetPrefs();
3505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const int64 expiration_timestamp =
3515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      pref_service->GetInt64(prefs::kWelcomeNotificationExpirationTimestamp);
3525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return (expiration_timestamp == 0)
3535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      ? base::Time()
3545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      : base::Time::FromInternalValue(expiration_timestamp);
3555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
3565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ExtensionWelcomeNotification::SetExpirationTimestampFromNow() {
3585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  PrefService* const pref_service = profile_->GetPrefs();
3595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  pref_service->SetInt64(
3605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      prefs::kWelcomeNotificationExpirationTimestamp,
3615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      (delegate_->GetCurrentTime() +
3625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          base::TimeDelta::FromDays(kRequestedShowTimeDays)).ToInternalValue());
3635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
3645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool ExtensionWelcomeNotification::IsWelcomeNotificationExpired() const {
3665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const base::Time expiration_timestamp = GetExpirationTimestamp();
3675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return !expiration_timestamp.is_null() &&
3685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)         (expiration_timestamp <= delegate_->GetCurrentTime());
3695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
370