Home | History | Annotate | Download | only in alarms
      1 // Copyright (c) 2012 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 // This file tests the chrome.alarms extension API.
      6 
      7 #include "base/test/simple_test_clock.h"
      8 #include "base/values.h"
      9 #include "chrome/browser/extensions/api/alarms/alarm_manager.h"
     10 #include "chrome/browser/extensions/api/alarms/alarms_api.h"
     11 #include "chrome/browser/extensions/extension_function_test_utils.h"
     12 #include "chrome/browser/profiles/profile_manager.h"
     13 #include "chrome/browser/ui/browser.h"
     14 #include "chrome/browser/ui/tabs/tab_strip_model.h"
     15 #include "chrome/common/extensions/background_info.h"
     16 #include "chrome/common/extensions/extension_messages.h"
     17 #include "chrome/test/base/browser_with_test_window_test.h"
     18 #include "content/public/browser/web_contents.h"
     19 #include "content/public/test/mock_render_process_host.h"
     20 #include "ipc/ipc_test_sink.h"
     21 #include "testing/gmock/include/gmock/gmock.h"
     22 #include "testing/gtest/include/gtest/gtest.h"
     23 
     24 typedef extensions::api::alarms::Alarm JsAlarm;
     25 
     26 namespace utils = extension_function_test_utils;
     27 
     28 namespace extensions {
     29 
     30 namespace {
     31 
     32 // Test delegate which quits the message loop when an alarm fires.
     33 class AlarmDelegate : public AlarmManager::Delegate {
     34  public:
     35   virtual ~AlarmDelegate() {}
     36   virtual void OnAlarm(const std::string& extension_id,
     37                        const Alarm& alarm) OVERRIDE {
     38     alarms_seen.push_back(alarm.js_alarm->name);
     39     base::MessageLoop::current()->Quit();
     40   }
     41 
     42   std::vector<std::string> alarms_seen;
     43 };
     44 
     45 }  // namespace
     46 
     47 class ExtensionAlarmsTest : public BrowserWithTestWindowTest {
     48  public:
     49   virtual void SetUp() {
     50     BrowserWithTestWindowTest::SetUp();
     51 
     52     test_clock_ = new base::SimpleTestClock();
     53     alarm_manager_ = AlarmManager::Get(browser()->profile());
     54     alarm_manager_->SetClockForTesting(test_clock_);
     55 
     56     alarm_delegate_ = new AlarmDelegate();
     57     alarm_manager_->set_delegate(alarm_delegate_);
     58 
     59     extension_ = utils::CreateEmptyExtensionWithLocation(
     60         extensions::Manifest::UNPACKED);
     61 
     62     // Make sure there's a RenderViewHost for alarms to warn into.
     63     AddTab(browser(), BackgroundInfo::GetBackgroundURL(extension_.get()));
     64     contents_ = browser()->tab_strip_model()->GetActiveWebContents();
     65 
     66     test_clock_->SetNow(base::Time::FromDoubleT(10));
     67   }
     68 
     69   base::Value* RunFunctionWithExtension(
     70       UIThreadExtensionFunction* function, const std::string& args) {
     71     scoped_refptr<UIThreadExtensionFunction> delete_function(function);
     72     function->set_extension(extension_.get());
     73     function->SetRenderViewHost(contents_->GetRenderViewHost());
     74     return utils::RunFunctionAndReturnSingleResult(function, args, browser());
     75   }
     76 
     77   base::DictionaryValue* RunFunctionAndReturnDict(
     78       UIThreadExtensionFunction* function, const std::string& args) {
     79     base::Value* result = RunFunctionWithExtension(function, args);
     80     return result ? utils::ToDictionary(result) : NULL;
     81   }
     82 
     83   base::ListValue* RunFunctionAndReturnList(
     84       UIThreadExtensionFunction* function, const std::string& args) {
     85     base::Value* result = RunFunctionWithExtension(function, args);
     86     return result ? utils::ToList(result) : NULL;
     87   }
     88 
     89   void RunFunction(UIThreadExtensionFunction* function,
     90                    const std::string& args) {
     91     scoped_ptr<base::Value> result(RunFunctionWithExtension(function, args));
     92   }
     93 
     94   std::string RunFunctionAndReturnError(UIThreadExtensionFunction* function,
     95                                         const std::string& args) {
     96     function->set_extension(extension_.get());
     97     function->SetRenderViewHost(contents_->GetRenderViewHost());
     98     return utils::RunFunctionAndReturnError(function, args, browser());
     99   }
    100 
    101   void CreateAlarm(const std::string& args) {
    102     RunFunction(new AlarmsCreateFunction(test_clock_), args);
    103   }
    104 
    105   // Takes a JSON result from a function and converts it to a vector of
    106   // JsAlarms.
    107   std::vector<linked_ptr<JsAlarm> > ToAlarmList(base::ListValue* value) {
    108     std::vector<linked_ptr<JsAlarm> > list;
    109     for (size_t i = 0; i < value->GetSize(); ++i) {
    110       linked_ptr<JsAlarm> alarm(new JsAlarm);
    111       base::DictionaryValue* alarm_value;
    112       if (!value->GetDictionary(i, &alarm_value)) {
    113         ADD_FAILURE() << "Expected a list of Alarm objects.";
    114         return list;
    115       }
    116       EXPECT_TRUE(JsAlarm::Populate(*alarm_value, alarm.get()));
    117       list.push_back(alarm);
    118     }
    119     return list;
    120   }
    121 
    122   // Creates up to 3 alarms using the extension API.
    123   void CreateAlarms(size_t num_alarms) {
    124     CHECK(num_alarms <= 3);
    125 
    126     const char* kCreateArgs[] = {
    127       "[null, {\"periodInMinutes\": 0.001}]",
    128       "[\"7\", {\"periodInMinutes\": 7}]",
    129       "[\"0\", {\"delayInMinutes\": 0}]",
    130     };
    131     for (size_t i = 0; i < num_alarms; ++i) {
    132       scoped_ptr<base::DictionaryValue> result(RunFunctionAndReturnDict(
    133           new AlarmsCreateFunction(test_clock_), kCreateArgs[i]));
    134       EXPECT_FALSE(result.get());
    135     }
    136   }
    137 
    138  protected:
    139   base::SimpleTestClock* test_clock_;
    140   AlarmManager* alarm_manager_;
    141   AlarmDelegate* alarm_delegate_;
    142   scoped_refptr<extensions::Extension> extension_;
    143   content::WebContents* contents_;
    144 };
    145 
    146 TEST_F(ExtensionAlarmsTest, Create) {
    147   test_clock_->SetNow(base::Time::FromDoubleT(10));
    148   // Create 1 non-repeating alarm.
    149   CreateAlarm("[null, {\"delayInMinutes\": 0}]");
    150 
    151   const Alarm* alarm =
    152       alarm_manager_->GetAlarm(extension_->id(), std::string());
    153   ASSERT_TRUE(alarm);
    154   EXPECT_EQ("", alarm->js_alarm->name);
    155   EXPECT_DOUBLE_EQ(10000, alarm->js_alarm->scheduled_time);
    156   EXPECT_FALSE(alarm->js_alarm->period_in_minutes.get());
    157 
    158   // Now wait for the alarm to fire. Our test delegate will quit the
    159   // MessageLoop when that happens.
    160   base::MessageLoop::current()->Run();
    161 
    162   ASSERT_EQ(1u, alarm_delegate_->alarms_seen.size());
    163   EXPECT_EQ("", alarm_delegate_->alarms_seen[0]);
    164 
    165   // Ensure the alarm is gone.
    166   {
    167     const AlarmManager::AlarmList* alarms =
    168         alarm_manager_->GetAllAlarms(extension_->id());
    169     ASSERT_FALSE(alarms);
    170   }
    171 }
    172 
    173 TEST_F(ExtensionAlarmsTest, CreateRepeating) {
    174   test_clock_->SetNow(base::Time::FromDoubleT(10));
    175 
    176   // Create 1 repeating alarm.
    177   CreateAlarm("[null, {\"periodInMinutes\": 0.001}]");
    178 
    179   const Alarm* alarm =
    180       alarm_manager_->GetAlarm(extension_->id(), std::string());
    181   ASSERT_TRUE(alarm);
    182   EXPECT_EQ("", alarm->js_alarm->name);
    183   EXPECT_DOUBLE_EQ(10060, alarm->js_alarm->scheduled_time);
    184   EXPECT_THAT(alarm->js_alarm->period_in_minutes,
    185               testing::Pointee(testing::DoubleEq(0.001)));
    186 
    187   test_clock_->Advance(base::TimeDelta::FromSeconds(1));
    188   // Now wait for the alarm to fire. Our test delegate will quit the
    189   // MessageLoop when that happens.
    190   base::MessageLoop::current()->Run();
    191 
    192   test_clock_->Advance(base::TimeDelta::FromSeconds(1));
    193   // Wait again, and ensure the alarm fires again.
    194   alarm_manager_->ScheduleNextPoll();
    195   base::MessageLoop::current()->Run();
    196 
    197   ASSERT_EQ(2u, alarm_delegate_->alarms_seen.size());
    198   EXPECT_EQ("", alarm_delegate_->alarms_seen[0]);
    199 }
    200 
    201 TEST_F(ExtensionAlarmsTest, CreateAbsolute) {
    202   test_clock_->SetNow(base::Time::FromDoubleT(9.99));
    203   CreateAlarm("[null, {\"when\": 10001}]");
    204 
    205   const Alarm* alarm =
    206       alarm_manager_->GetAlarm(extension_->id(), std::string());
    207   ASSERT_TRUE(alarm);
    208   EXPECT_EQ("", alarm->js_alarm->name);
    209   EXPECT_DOUBLE_EQ(10001, alarm->js_alarm->scheduled_time);
    210   EXPECT_THAT(alarm->js_alarm->period_in_minutes,
    211               testing::IsNull());
    212 
    213   test_clock_->SetNow(base::Time::FromDoubleT(10.1));
    214   // Now wait for the alarm to fire. Our test delegate will quit the
    215   // MessageLoop when that happens.
    216   base::MessageLoop::current()->Run();
    217 
    218   ASSERT_FALSE(alarm_manager_->GetAlarm(extension_->id(), std::string()));
    219 
    220   ASSERT_EQ(1u, alarm_delegate_->alarms_seen.size());
    221   EXPECT_EQ("", alarm_delegate_->alarms_seen[0]);
    222 }
    223 
    224 TEST_F(ExtensionAlarmsTest, CreateRepeatingWithQuickFirstCall) {
    225   test_clock_->SetNow(base::Time::FromDoubleT(9.99));
    226   CreateAlarm("[null, {\"when\": 10001, \"periodInMinutes\": 0.001}]");
    227 
    228   const Alarm* alarm =
    229       alarm_manager_->GetAlarm(extension_->id(), std::string());
    230   ASSERT_TRUE(alarm);
    231   EXPECT_EQ("", alarm->js_alarm->name);
    232   EXPECT_DOUBLE_EQ(10001, alarm->js_alarm->scheduled_time);
    233   EXPECT_THAT(alarm->js_alarm->period_in_minutes,
    234               testing::Pointee(testing::DoubleEq(0.001)));
    235 
    236   test_clock_->SetNow(base::Time::FromDoubleT(10.1));
    237   // Now wait for the alarm to fire. Our test delegate will quit the
    238   // MessageLoop when that happens.
    239   base::MessageLoop::current()->Run();
    240 
    241   ASSERT_TRUE(alarm_manager_->GetAlarm(extension_->id(), std::string()));
    242   EXPECT_THAT(alarm_delegate_->alarms_seen, testing::ElementsAre(""));
    243 
    244   test_clock_->SetNow(base::Time::FromDoubleT(10.7));
    245   base::MessageLoop::current()->Run();
    246 
    247   ASSERT_TRUE(alarm_manager_->GetAlarm(extension_->id(), std::string()));
    248   EXPECT_THAT(alarm_delegate_->alarms_seen, testing::ElementsAre("", ""));
    249 }
    250 
    251 TEST_F(ExtensionAlarmsTest, CreateDupe) {
    252   test_clock_->SetNow(base::Time::FromDoubleT(10));
    253 
    254   // Create 2 duplicate alarms. The first should be overridden.
    255   CreateAlarm("[\"dup\", {\"delayInMinutes\": 1}]");
    256   CreateAlarm("[\"dup\", {\"delayInMinutes\": 7}]");
    257 
    258   {
    259     const AlarmManager::AlarmList* alarms =
    260         alarm_manager_->GetAllAlarms(extension_->id());
    261     ASSERT_TRUE(alarms);
    262     EXPECT_EQ(1u, alarms->size());
    263     EXPECT_DOUBLE_EQ(430000, (*alarms)[0].js_alarm->scheduled_time);
    264   }
    265 }
    266 
    267 TEST_F(ExtensionAlarmsTest, CreateDelayBelowMinimum) {
    268   // Create an alarm with delay below the minimum accepted value.
    269   CreateAlarm("[\"negative\", {\"delayInMinutes\": -0.2}]");
    270   IPC::TestSink& sink = static_cast<content::MockRenderProcessHost*>(
    271       contents_->GetRenderViewHost()->GetProcess())->sink();
    272   const IPC::Message* warning = sink.GetUniqueMessageMatching(
    273       ExtensionMsg_AddMessageToConsole::ID);
    274   ASSERT_TRUE(warning);
    275   content::ConsoleMessageLevel level = content::CONSOLE_MESSAGE_LEVEL_DEBUG;
    276   std::string message;
    277   ExtensionMsg_AddMessageToConsole::Read(warning, &level, &message);
    278   EXPECT_EQ(content::CONSOLE_MESSAGE_LEVEL_WARNING, level);
    279   EXPECT_THAT(message, testing::HasSubstr("delay is less than minimum of 1"));
    280 }
    281 
    282 TEST_F(ExtensionAlarmsTest, Get) {
    283   test_clock_->SetNow(base::Time::FromDoubleT(4));
    284 
    285   // Create 2 alarms, and make sure we can query them.
    286   CreateAlarms(2);
    287 
    288   // Get the default one.
    289   {
    290     JsAlarm alarm;
    291     scoped_ptr<base::DictionaryValue> result(RunFunctionAndReturnDict(
    292         new AlarmsGetFunction(), "[null]"));
    293     ASSERT_TRUE(result.get());
    294     EXPECT_TRUE(JsAlarm::Populate(*result, &alarm));
    295     EXPECT_EQ("", alarm.name);
    296     EXPECT_DOUBLE_EQ(4060, alarm.scheduled_time);
    297     EXPECT_THAT(alarm.period_in_minutes,
    298                 testing::Pointee(testing::DoubleEq(0.001)));
    299   }
    300 
    301   // Get "7".
    302   {
    303     JsAlarm alarm;
    304     scoped_ptr<base::DictionaryValue> result(RunFunctionAndReturnDict(
    305         new AlarmsGetFunction(), "[\"7\"]"));
    306     ASSERT_TRUE(result.get());
    307     EXPECT_TRUE(JsAlarm::Populate(*result, &alarm));
    308     EXPECT_EQ("7", alarm.name);
    309     EXPECT_EQ(424000, alarm.scheduled_time);
    310     EXPECT_THAT(alarm.period_in_minutes, testing::Pointee(7));
    311   }
    312 
    313   // Get a non-existent one.
    314   {
    315     std::string error = RunFunctionAndReturnError(
    316         new AlarmsGetFunction(), "[\"nobody\"]");
    317     EXPECT_FALSE(error.empty());
    318   }
    319 }
    320 
    321 TEST_F(ExtensionAlarmsTest, GetAll) {
    322   // Test getAll with 0 alarms.
    323   {
    324     scoped_ptr<base::ListValue> result(RunFunctionAndReturnList(
    325         new AlarmsGetAllFunction(), "[]"));
    326     std::vector<linked_ptr<JsAlarm> > alarms = ToAlarmList(result.get());
    327     EXPECT_EQ(0u, alarms.size());
    328   }
    329 
    330   // Create 2 alarms, and make sure we can query them.
    331   CreateAlarms(2);
    332 
    333   {
    334     scoped_ptr<base::ListValue> result(RunFunctionAndReturnList(
    335         new AlarmsGetAllFunction(), "[null]"));
    336     std::vector<linked_ptr<JsAlarm> > alarms = ToAlarmList(result.get());
    337     EXPECT_EQ(2u, alarms.size());
    338 
    339     // Test the "7" alarm.
    340     JsAlarm* alarm = alarms[0].get();
    341     if (alarm->name != "7")
    342       alarm = alarms[1].get();
    343     EXPECT_EQ("7", alarm->name);
    344     EXPECT_THAT(alarm->period_in_minutes, testing::Pointee(7));
    345   }
    346 }
    347 
    348 TEST_F(ExtensionAlarmsTest, Clear) {
    349   // Clear a non-existent one.
    350   {
    351     std::string error = RunFunctionAndReturnError(
    352         new AlarmsClearFunction(), "[\"nobody\"]");
    353     EXPECT_FALSE(error.empty());
    354   }
    355 
    356   // Create 3 alarms.
    357   CreateAlarms(3);
    358 
    359   // Clear all but the 0.001-minute alarm.
    360   {
    361     RunFunction(new AlarmsClearFunction(), "[\"7\"]");
    362     RunFunction(new AlarmsClearFunction(), "[\"0\"]");
    363 
    364     const AlarmManager::AlarmList* alarms =
    365         alarm_manager_->GetAllAlarms(extension_->id());
    366     ASSERT_TRUE(alarms);
    367     EXPECT_EQ(1u, alarms->size());
    368     EXPECT_THAT((*alarms)[0].js_alarm->period_in_minutes,
    369                 testing::Pointee(0.001));
    370   }
    371 
    372   // Now wait for the alarms to fire, and ensure the cancelled alarms don't
    373   // fire.
    374   alarm_manager_->ScheduleNextPoll();
    375   base::MessageLoop::current()->Run();
    376 
    377   ASSERT_EQ(1u, alarm_delegate_->alarms_seen.size());
    378   EXPECT_EQ("", alarm_delegate_->alarms_seen[0]);
    379 
    380   // Ensure the 0.001-minute alarm is still there, since it's repeating.
    381   {
    382     const AlarmManager::AlarmList* alarms =
    383         alarm_manager_->GetAllAlarms(extension_->id());
    384     ASSERT_TRUE(alarms);
    385     EXPECT_EQ(1u, alarms->size());
    386     EXPECT_THAT((*alarms)[0].js_alarm->period_in_minutes,
    387                 testing::Pointee(0.001));
    388   }
    389 }
    390 
    391 TEST_F(ExtensionAlarmsTest, ClearAll) {
    392   // ClearAll with no alarms set.
    393   {
    394     scoped_ptr<base::Value> result(RunFunctionWithExtension(
    395         new AlarmsClearAllFunction(), "[]"));
    396     EXPECT_FALSE(result.get());
    397   }
    398 
    399   // Create 3 alarms.
    400   {
    401     CreateAlarms(3);
    402     const AlarmManager::AlarmList* alarms =
    403         alarm_manager_->GetAllAlarms(extension_->id());
    404     ASSERT_TRUE(alarms);
    405     EXPECT_EQ(3u, alarms->size());
    406   }
    407 
    408   // Clear them.
    409   {
    410     RunFunction(new AlarmsClearAllFunction(), "[]");
    411     const AlarmManager::AlarmList* alarms =
    412         alarm_manager_->GetAllAlarms(extension_->id());
    413     ASSERT_FALSE(alarms);
    414   }
    415 }
    416 
    417 class ExtensionAlarmsSchedulingTest : public ExtensionAlarmsTest {
    418  public:
    419   // Get the time that the alarm named is scheduled to run.
    420   base::Time GetScheduledTime(const std::string& alarm_name) {
    421     const extensions::Alarm* alarm =
    422         alarm_manager_->GetAlarm(extension_->id(), alarm_name);
    423     CHECK(alarm);
    424     return base::Time::FromJsTime(alarm->js_alarm->scheduled_time);
    425   }
    426 };
    427 
    428 TEST_F(ExtensionAlarmsSchedulingTest, PollScheduling) {
    429   {
    430     CreateAlarm("[\"a\", {\"periodInMinutes\": 6}]");
    431     CreateAlarm("[\"bb\", {\"periodInMinutes\": 8}]");
    432     EXPECT_EQ(GetScheduledTime("a"), alarm_manager_->next_poll_time_);
    433     alarm_manager_->RemoveAllAlarms(extension_->id());
    434   }
    435   {
    436     CreateAlarm("[\"a\", {\"delayInMinutes\": 10}]");
    437     CreateAlarm("[\"bb\", {\"delayInMinutes\": 21}]");
    438     EXPECT_EQ(GetScheduledTime("a"), alarm_manager_->next_poll_time_);
    439     alarm_manager_->RemoveAllAlarms(extension_->id());
    440   }
    441   {
    442     test_clock_->SetNow(base::Time::FromDoubleT(10));
    443     CreateAlarm("[\"a\", {\"periodInMinutes\": 10}]");
    444     Alarm alarm;
    445     alarm.js_alarm->name = "bb";
    446     alarm.js_alarm->scheduled_time = 30 * 60000;
    447     alarm.js_alarm->period_in_minutes.reset(new double(30));
    448     alarm_manager_->AddAlarmImpl(extension_->id(), alarm);
    449     EXPECT_DOUBLE_EQ(GetScheduledTime("a").ToDoubleT(),
    450                      alarm_manager_->next_poll_time_.ToDoubleT());
    451     alarm_manager_->RemoveAllAlarms(extension_->id());
    452   }
    453   {
    454     test_clock_->SetNow(base::Time::FromDoubleT(3 * 60 + 1));
    455     Alarm alarm;
    456     alarm.js_alarm->name = "bb";
    457     alarm.js_alarm->scheduled_time = 3 * 60000;
    458     alarm.js_alarm->period_in_minutes.reset(new double(3));
    459     alarm_manager_->AddAlarmImpl(extension_->id(), alarm);
    460     base::MessageLoop::current()->Run();
    461     EXPECT_EQ(alarm_manager_->last_poll_time_ + base::TimeDelta::FromMinutes(3),
    462               alarm_manager_->next_poll_time_);
    463     alarm_manager_->RemoveAllAlarms(extension_->id());
    464   }
    465   {
    466     test_clock_->SetNow(base::Time::FromDoubleT(4 * 60 + 1));
    467     CreateAlarm("[\"a\", {\"periodInMinutes\": 2}]");
    468     alarm_manager_->RemoveAlarm(extension_->id(), "a");
    469     Alarm alarm2;
    470     alarm2.js_alarm->name = "bb";
    471     alarm2.js_alarm->scheduled_time = 4 * 60000;
    472     alarm2.js_alarm->period_in_minutes.reset(new double(4));
    473     alarm_manager_->AddAlarmImpl(extension_->id(), alarm2);
    474     Alarm alarm3;
    475     alarm3.js_alarm->name = "ccc";
    476     alarm3.js_alarm->scheduled_time = 25 * 60000;
    477     alarm3.js_alarm->period_in_minutes.reset(new double(25));
    478     alarm_manager_->AddAlarmImpl(extension_->id(), alarm3);
    479     base::MessageLoop::current()->Run();
    480     EXPECT_EQ(alarm_manager_->last_poll_time_ + base::TimeDelta::FromMinutes(4),
    481               alarm_manager_->next_poll_time_);
    482     alarm_manager_->RemoveAllAlarms(extension_->id());
    483   }
    484 }
    485 
    486 TEST_F(ExtensionAlarmsSchedulingTest, ReleasedExtensionPollsInfrequently) {
    487   extension_ = utils::CreateEmptyExtensionWithLocation(
    488       extensions::Manifest::INTERNAL);
    489   test_clock_->SetNow(base::Time::FromJsTime(300000));
    490   CreateAlarm("[\"a\", {\"when\": 300010}]");
    491   CreateAlarm("[\"b\", {\"when\": 340000}]");
    492 
    493   // On startup (when there's no "last poll"), we let alarms fire as
    494   // soon as they're scheduled.
    495   EXPECT_DOUBLE_EQ(300010, alarm_manager_->next_poll_time_.ToJsTime());
    496 
    497   alarm_manager_->last_poll_time_ = base::Time::FromJsTime(290000);
    498   // In released extensions, we set the granularity to at least 5
    499   // minutes, which makes AddAlarm schedule the next poll after the
    500   // extension requested.
    501   alarm_manager_->ScheduleNextPoll();
    502   EXPECT_DOUBLE_EQ((alarm_manager_->last_poll_time_ +
    503                     base::TimeDelta::FromMinutes(1)).ToJsTime(),
    504                    alarm_manager_->next_poll_time_.ToJsTime());
    505 }
    506 
    507 TEST_F(ExtensionAlarmsSchedulingTest, TimerRunning) {
    508   EXPECT_FALSE(alarm_manager_->timer_.IsRunning());
    509   CreateAlarm("[\"a\", {\"delayInMinutes\": 0.001}]");
    510   EXPECT_TRUE(alarm_manager_->timer_.IsRunning());
    511   base::MessageLoop::current()->Run();
    512   EXPECT_FALSE(alarm_manager_->timer_.IsRunning());
    513   CreateAlarm("[\"bb\", {\"delayInMinutes\": 10}]");
    514   EXPECT_TRUE(alarm_manager_->timer_.IsRunning());
    515   alarm_manager_->RemoveAllAlarms(extension_->id());
    516   EXPECT_FALSE(alarm_manager_->timer_.IsRunning());
    517 }
    518 
    519 }  // namespace extensions
    520