- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / extensions / api / idle / idle_api_unittest.cc
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 #include "chrome/browser/extensions/api/idle/idle_api.h"
6
7 #include <limits.h>
8 #include <string>
9
10 #include "base/strings/string_number_conversions.h"
11 #include "chrome/browser/chrome_notification_types.h"
12 #include "chrome/browser/extensions/api/idle/idle_api_constants.h"
13 #include "chrome/browser/extensions/api/idle/idle_manager.h"
14 #include "chrome/browser/extensions/api/idle/idle_manager_factory.h"
15 #include "chrome/browser/extensions/event_router.h"
16 #include "chrome/browser/extensions/extension_function_test_utils.h"
17 #include "chrome/common/extensions/api/idle.h"
18 #include "chrome/common/extensions/extension.h"
19 #include "chrome/test/base/browser_with_test_window_test.h"
20 #include "content/public/browser/notification_details.h"
21 #include "content/public/browser/notification_source.h"
22 #include "testing/gmock/include/gmock/gmock.h"
23 #include "testing/gtest/include/gtest/gtest.h"
24
25 using ::testing::_;
26
27 namespace utils = extension_function_test_utils;
28 namespace idle = extensions::api::idle;
29
30 namespace extensions {
31
32 namespace {
33
34 class MockEventDelegate : public IdleManager::EventDelegate {
35  public:
36   MockEventDelegate() {}
37   virtual ~MockEventDelegate() {}
38   MOCK_METHOD2(OnStateChanged, void(const std::string&, IdleState));
39   virtual void RegisterObserver(EventRouter::Observer* observer) {}
40   virtual void UnregisterObserver(EventRouter::Observer* observer) {}
41 };
42
43 class TestIdleProvider : public IdleManager::IdleTimeProvider {
44  public:
45   TestIdleProvider();
46   virtual ~TestIdleProvider();
47   virtual void CalculateIdleState(int idle_threshold,
48                                   IdleCallback notify) OVERRIDE;
49   virtual void CalculateIdleTime(IdleTimeCallback notify) OVERRIDE;
50   virtual bool CheckIdleStateIsLocked() OVERRIDE;
51
52   void set_idle_time(int idle_time);
53   void set_locked(bool locked);
54
55  private:
56   int idle_time_;
57   bool locked_;
58 };
59
60 TestIdleProvider::TestIdleProvider()
61     : idle_time_(0),
62       locked_(false) {
63 }
64
65 TestIdleProvider::~TestIdleProvider() {
66 }
67
68 void TestIdleProvider::CalculateIdleState(int idle_threshold,
69                                           IdleCallback notify) {
70   if (locked_) {
71     notify.Run(IDLE_STATE_LOCKED);
72   } else {
73     if (idle_time_ >= idle_threshold) {
74       notify.Run(IDLE_STATE_IDLE);
75     } else {
76       notify.Run(IDLE_STATE_ACTIVE);
77     }
78   }
79 }
80
81 void TestIdleProvider::CalculateIdleTime(IdleTimeCallback notify) {
82   notify.Run(idle_time_);
83 }
84
85 bool TestIdleProvider::CheckIdleStateIsLocked() {
86   return locked_;
87 }
88
89 void TestIdleProvider::set_idle_time(int idle_time) {
90   idle_time_ = idle_time;
91 }
92
93 void TestIdleProvider::set_locked(bool locked) {
94   locked_ = locked;
95 }
96
97 class ScopedListen {
98  public:
99   ScopedListen(IdleManager* idle_manager, const std::string& extension_id);
100   ~ScopedListen();
101
102  private:
103   IdleManager* idle_manager_;
104   const std::string extension_id_;
105 };
106
107 ScopedListen::ScopedListen(IdleManager* idle_manager,
108                            const std::string& extension_id)
109     : idle_manager_(idle_manager),
110       extension_id_(extension_id) {
111   const EventListenerInfo details(idle::OnStateChanged::kEventName,
112                                   extension_id_);
113   idle_manager_->OnListenerAdded(details);
114 }
115
116 ScopedListen::~ScopedListen() {
117   const EventListenerInfo details(idle::OnStateChanged::kEventName,
118                                   extension_id_);
119   idle_manager_->OnListenerRemoved(details);
120 }
121
122 BrowserContextKeyedService* IdleManagerTestFactory(
123     content::BrowserContext* profile) {
124   return new IdleManager(static_cast<Profile*>(profile));
125 }
126
127 }  // namespace
128
129 class IdleTest : public BrowserWithTestWindowTest {
130  public:
131   virtual void SetUp() OVERRIDE;
132
133  protected:
134   base::Value* RunFunctionWithExtension(
135       UIThreadExtensionFunction* function, const std::string& args);
136
137   IdleManager* idle_manager_;
138   TestIdleProvider* idle_provider_;
139   testing::StrictMock<MockEventDelegate>* event_delegate_;
140   scoped_refptr<extensions::Extension> extension_;
141 };
142
143 void IdleTest::SetUp() {
144   BrowserWithTestWindowTest::SetUp();
145
146   IdleManagerFactory::GetInstance()->SetTestingFactory(browser()->profile(),
147                                                        &IdleManagerTestFactory);
148   idle_manager_ = IdleManagerFactory::GetForProfile(browser()->profile());
149
150   extension_ = utils::CreateEmptyExtensionWithLocation(
151       extensions::Manifest::UNPACKED);
152
153   idle_provider_ = new TestIdleProvider();
154   idle_manager_->SetIdleTimeProviderForTest(
155       scoped_ptr<IdleManager::IdleTimeProvider>(idle_provider_).Pass());
156   event_delegate_ = new testing::StrictMock<MockEventDelegate>();
157   idle_manager_->SetEventDelegateForTest(
158       scoped_ptr<IdleManager::EventDelegate>(event_delegate_).Pass());
159   idle_manager_->Init();
160 }
161
162 base::Value* IdleTest::RunFunctionWithExtension(
163     UIThreadExtensionFunction* function, const std::string& args) {
164   function->set_extension(extension_.get());
165   return utils::RunFunctionAndReturnSingleResult(function, args, browser());
166 }
167
168 // Verifies that "locked" takes priority over "active".
169 TEST_F(IdleTest, QueryLockedActive) {
170   idle_provider_->set_locked(true);
171   idle_provider_->set_idle_time(0);
172
173   scoped_ptr<base::Value> result(RunFunctionWithExtension(
174       new IdleQueryStateFunction(),
175       "[60]"));
176
177   std::string idle_state;
178   ASSERT_TRUE(result->GetAsString(&idle_state));
179   EXPECT_EQ("locked", idle_state);
180 }
181
182 // Verifies that "locked" takes priority over "idle".
183 TEST_F(IdleTest, QueryLockedIdle) {
184   idle_provider_->set_locked(true);
185   idle_provider_->set_idle_time(INT_MAX);
186
187   scoped_ptr<base::Value> result(RunFunctionWithExtension(
188       new IdleQueryStateFunction(),
189       "[60]"));
190
191   std::string idle_state;
192   ASSERT_TRUE(result->GetAsString(&idle_state));
193   EXPECT_EQ("locked", idle_state);
194 }
195
196 // Verifies that any amount of idle time less than the detection interval
197 // translates to a state of "active".
198 TEST_F(IdleTest, QueryActive) {
199   idle_provider_->set_locked(false);
200
201   for (int time = 0; time < 60; ++time) {
202     SCOPED_TRACE(time);
203     idle_provider_->set_idle_time(time);
204
205     scoped_ptr<base::Value> result(RunFunctionWithExtension(
206         new IdleQueryStateFunction(),
207         "[60]"));
208
209     std::string idle_state;
210     ASSERT_TRUE(result->GetAsString(&idle_state));
211     EXPECT_EQ("active", idle_state);
212   }
213 }
214
215 // Verifies that an idle time >= the detection interval returns the "idle"
216 // state.
217 TEST_F(IdleTest, QueryIdle) {
218   idle_provider_->set_locked(false);
219
220   for (int time = 80; time >= 60; --time) {
221     SCOPED_TRACE(time);
222     idle_provider_->set_idle_time(time);
223
224     scoped_ptr<base::Value> result(RunFunctionWithExtension(
225         new IdleQueryStateFunction(),
226         "[60]"));
227
228     std::string idle_state;
229     ASSERT_TRUE(result->GetAsString(&idle_state));
230     EXPECT_EQ("idle", idle_state);
231   }
232 }
233
234 // Verifies that requesting a detection interval < 15 has the same effect as
235 // passing in 15.
236 TEST_F(IdleTest, QueryMinThreshold) {
237   idle_provider_->set_locked(false);
238
239   for (int threshold = 0; threshold < 20; ++threshold) {
240     for (int time = 10; time < 60; ++time) {
241       SCOPED_TRACE(threshold);
242       SCOPED_TRACE(time);
243       idle_provider_->set_idle_time(time);
244
245       std::string args = "[" + base::IntToString(threshold) + "]";
246       scoped_ptr<base::Value> result(RunFunctionWithExtension(
247           new IdleQueryStateFunction(), args));
248
249       std::string idle_state;
250       ASSERT_TRUE(result->GetAsString(&idle_state));
251
252       int real_threshold = (threshold < 15) ? 15 : threshold;
253       const char* expected = (time < real_threshold) ? "active" : "idle";
254       EXPECT_EQ(expected, idle_state);
255     }
256   }
257 }
258
259 // Verifies that passing in a detection interval > 4 hours has the same effect
260 // as passing in 4 hours.
261 TEST_F(IdleTest, QueryMaxThreshold) {
262   idle_provider_->set_locked(false);
263
264   const int kFourHoursInSeconds = 4*60*60;
265
266   for (int threshold = kFourHoursInSeconds - 20;
267        threshold < (kFourHoursInSeconds + 20); ++threshold) {
268     for (int time = kFourHoursInSeconds - 30; time < kFourHoursInSeconds + 30;
269          ++time) {
270       SCOPED_TRACE(threshold);
271       SCOPED_TRACE(time);
272       idle_provider_->set_idle_time(time);
273
274       std::string args = "[" + base::IntToString(threshold) + "]";
275       scoped_ptr<base::Value> result(RunFunctionWithExtension(
276           new IdleQueryStateFunction(), args));
277
278       std::string idle_state;
279       ASSERT_TRUE(result->GetAsString(&idle_state));
280
281       int real_threshold = (threshold > kFourHoursInSeconds) ?
282           kFourHoursInSeconds : threshold;
283       const char* expected = (time < real_threshold) ? "active" : "idle";
284       EXPECT_EQ(expected, idle_state);
285     }
286   }
287 }
288
289 // Verifies that transitioning from an active to idle state fires an "idle"
290 // OnStateChanged event.
291 TEST_F(IdleTest, ActiveToIdle) {
292   ScopedListen listen_test(idle_manager_, "test");
293
294   idle_provider_->set_locked(false);
295
296   for (int time = 0; time < 60; ++time) {
297     SCOPED_TRACE(time);
298     idle_provider_->set_idle_time(time);
299
300     idle_manager_->UpdateIdleState();
301   }
302
303   idle_provider_->set_idle_time(60);
304
305   EXPECT_CALL(*event_delegate_, OnStateChanged("test", IDLE_STATE_IDLE));
306   idle_manager_->UpdateIdleState();
307   testing::Mock::VerifyAndClearExpectations(event_delegate_);
308
309   for (int time = 61; time < 75; ++time) {
310     SCOPED_TRACE(time);
311     idle_provider_->set_idle_time(time);
312     idle_manager_->UpdateIdleState();
313   }
314 }
315
316 // Verifies that locking an active system generates a "locked" event.
317 TEST_F(IdleTest, ActiveToLocked) {
318   ScopedListen listen_test(idle_manager_, "test");
319
320   idle_provider_->set_locked(true);
321   idle_provider_->set_idle_time(5);
322
323   EXPECT_CALL(*event_delegate_, OnStateChanged("test", IDLE_STATE_LOCKED));
324   idle_manager_->UpdateIdleState();
325 }
326
327 // Verifies that transitioning from an idle to active state generates an
328 // "active" event.
329 TEST_F(IdleTest, IdleToActive) {
330   ScopedListen listen_test(idle_manager_, "test");
331
332   idle_provider_->set_locked(false);
333   idle_provider_->set_idle_time(75);
334   EXPECT_CALL(*event_delegate_, OnStateChanged("test", IDLE_STATE_IDLE));
335   idle_manager_->UpdateIdleState();
336   testing::Mock::VerifyAndClearExpectations(event_delegate_);
337
338   idle_provider_->set_idle_time(0);
339   EXPECT_CALL(*event_delegate_, OnStateChanged("test", IDLE_STATE_ACTIVE));
340   idle_manager_->UpdateIdleState();
341 }
342
343 // Verifies that locking an idle system generates a "locked" event.
344 TEST_F(IdleTest, IdleToLocked) {
345   ScopedListen listen_test(idle_manager_, "test");
346
347   idle_provider_->set_locked(false);
348   idle_provider_->set_idle_time(75);
349
350   EXPECT_CALL(*event_delegate_, OnStateChanged("test", IDLE_STATE_IDLE));
351   idle_manager_->UpdateIdleState();
352   testing::Mock::VerifyAndClearExpectations(event_delegate_);
353
354   idle_provider_->set_locked(true);
355   EXPECT_CALL(*event_delegate_, OnStateChanged("test", IDLE_STATE_LOCKED));
356   idle_manager_->UpdateIdleState();
357 }
358
359 // Verifies that unlocking an active system generates an "active" event.
360 TEST_F(IdleTest, LockedToActive) {
361   ScopedListen listen_test(idle_manager_, "test");
362
363   idle_provider_->set_locked(true);
364   idle_provider_->set_idle_time(0);
365
366   EXPECT_CALL(*event_delegate_, OnStateChanged("test", IDLE_STATE_LOCKED));
367   idle_manager_->UpdateIdleState();
368
369   idle_provider_->set_locked(false);
370   idle_provider_->set_idle_time(5);
371   EXPECT_CALL(*event_delegate_, OnStateChanged("test", IDLE_STATE_ACTIVE));
372   idle_manager_->UpdateIdleState();
373 }
374
375 // Verifies that unlocking an inactive system generates an "idle" event.
376 TEST_F(IdleTest, LockedToIdle) {
377   ScopedListen listen_test(idle_manager_, "test");
378
379   idle_provider_->set_locked(true);
380   idle_provider_->set_idle_time(75);
381   EXPECT_CALL(*event_delegate_, OnStateChanged("test", IDLE_STATE_LOCKED));
382   idle_manager_->UpdateIdleState();
383   testing::Mock::VerifyAndClearExpectations(event_delegate_);
384
385   idle_provider_->set_locked(false);
386   EXPECT_CALL(*event_delegate_, OnStateChanged("test", IDLE_STATE_IDLE));
387   idle_manager_->UpdateIdleState();
388 }
389
390 // Verifies that events are routed to extensions that have one or more listeners
391 // in scope.
392 TEST_F(IdleTest, MultipleExtensions) {
393   ScopedListen listen_1(idle_manager_, "1");
394   ScopedListen listen_2(idle_manager_, "2");
395
396   idle_provider_->set_locked(true);
397   EXPECT_CALL(*event_delegate_, OnStateChanged("1", IDLE_STATE_LOCKED));
398   EXPECT_CALL(*event_delegate_, OnStateChanged("2", IDLE_STATE_LOCKED));
399   idle_manager_->UpdateIdleState();
400   testing::Mock::VerifyAndClearExpectations(event_delegate_);
401
402   {
403     ScopedListen listen_2prime(idle_manager_, "2");
404     ScopedListen listen_3(idle_manager_, "3");
405     idle_provider_->set_locked(false);
406     EXPECT_CALL(*event_delegate_, OnStateChanged("1", IDLE_STATE_ACTIVE));
407     EXPECT_CALL(*event_delegate_, OnStateChanged("2", IDLE_STATE_ACTIVE));
408     EXPECT_CALL(*event_delegate_, OnStateChanged("3", IDLE_STATE_ACTIVE));
409     idle_manager_->UpdateIdleState();
410     testing::Mock::VerifyAndClearExpectations(event_delegate_);
411   }
412
413   idle_provider_->set_locked(true);
414   EXPECT_CALL(*event_delegate_, OnStateChanged("1", IDLE_STATE_LOCKED));
415   EXPECT_CALL(*event_delegate_, OnStateChanged("2", IDLE_STATE_LOCKED));
416   idle_manager_->UpdateIdleState();
417 }
418
419 // Verifies that setDetectionInterval changes the detection interval from the
420 // default of 60 seconds, and that the call only affects a single extension's
421 // IdleMonitor.
422 TEST_F(IdleTest, SetDetectionInterval) {
423   ScopedListen listen_default(idle_manager_, "default");
424   ScopedListen listen_extension(idle_manager_, extension_->id());
425
426   scoped_ptr<base::Value> result45(RunFunctionWithExtension(
427       new IdleSetDetectionIntervalFunction(),
428       "[45]"));
429
430   idle_provider_->set_locked(false);
431   idle_provider_->set_idle_time(44);
432   idle_manager_->UpdateIdleState();
433
434   idle_provider_->set_idle_time(45);
435   EXPECT_CALL(*event_delegate_,
436               OnStateChanged(extension_->id(), IDLE_STATE_IDLE));
437   idle_manager_->UpdateIdleState();
438   // Verify that the expectation has been fulfilled before incrementing the
439   // time again.
440   testing::Mock::VerifyAndClearExpectations(event_delegate_);
441
442   idle_provider_->set_idle_time(60);
443   EXPECT_CALL(*event_delegate_, OnStateChanged("default", IDLE_STATE_IDLE));
444   idle_manager_->UpdateIdleState();
445 }
446
447 // Verifies that setting the detection interval before creating the listener
448 // works correctly.
449 TEST_F(IdleTest, SetDetectionIntervalBeforeListener) {
450   scoped_ptr<base::Value> result45(RunFunctionWithExtension(
451       new IdleSetDetectionIntervalFunction(),
452       "[45]"));
453
454   ScopedListen listen_extension(idle_manager_, extension_->id());
455
456   idle_provider_->set_locked(false);
457   idle_provider_->set_idle_time(44);
458   idle_manager_->UpdateIdleState();
459
460   idle_provider_->set_idle_time(45);
461   EXPECT_CALL(*event_delegate_,
462               OnStateChanged(extension_->id(), IDLE_STATE_IDLE));
463   idle_manager_->UpdateIdleState();
464 }
465
466 // Verifies that setting a detection interval above the maximum value results
467 // in an interval of 4 hours.
468 TEST_F(IdleTest, SetDetectionIntervalMaximum) {
469   ScopedListen listen_extension(idle_manager_, extension_->id());
470
471   scoped_ptr<base::Value> result(RunFunctionWithExtension(
472       new IdleSetDetectionIntervalFunction(),
473       "[18000]"));  // five hours in seconds
474
475   idle_provider_->set_locked(false);
476   idle_provider_->set_idle_time(4*60*60 - 1);
477   idle_manager_->UpdateIdleState();
478
479   idle_provider_->set_idle_time(4*60*60);
480   EXPECT_CALL(*event_delegate_,
481               OnStateChanged(extension_->id(), IDLE_STATE_IDLE));
482   idle_manager_->UpdateIdleState();
483 }
484
485 // Verifies that setting a detection interval below the minimum value results
486 // in an interval of 15 seconds.
487 TEST_F(IdleTest, SetDetectionIntervalMinimum) {
488   ScopedListen listen_extension(idle_manager_, extension_->id());
489
490   scoped_ptr<base::Value> result(RunFunctionWithExtension(
491       new IdleSetDetectionIntervalFunction(),
492       "[10]"));
493
494   idle_provider_->set_locked(false);
495   idle_provider_->set_idle_time(14);
496   idle_manager_->UpdateIdleState();
497
498   idle_provider_->set_idle_time(15);
499   EXPECT_CALL(*event_delegate_,
500               OnStateChanged(extension_->id(), IDLE_STATE_IDLE));
501   idle_manager_->UpdateIdleState();
502 }
503
504 // Verifies that an extension's detection interval is discarded when it unloads.
505 TEST_F(IdleTest, UnloadCleanup) {
506   {
507     ScopedListen listen(idle_manager_, extension_->id());
508
509     scoped_ptr<base::Value> result45(RunFunctionWithExtension(
510         new IdleSetDetectionIntervalFunction(),
511         "[15]"));
512   }
513
514   // Listener count dropping to zero does not reset threshold.
515
516   {
517     ScopedListen listen(idle_manager_, extension_->id());
518     idle_provider_->set_idle_time(16);
519     EXPECT_CALL(*event_delegate_,
520                 OnStateChanged(extension_->id(), IDLE_STATE_IDLE));
521     idle_manager_->UpdateIdleState();
522     testing::Mock::VerifyAndClearExpectations(event_delegate_);
523   }
524
525   // Threshold will reset after unload (and listen count == 0)
526   UnloadedExtensionInfo details(extension_.get(),
527                                 UnloadedExtensionInfo::REASON_UNINSTALL);
528   idle_manager_->Observe(
529       chrome::NOTIFICATION_EXTENSION_UNLOADED,
530       content::Source<Profile>(browser()->profile()),
531       content::Details<UnloadedExtensionInfo>(&details));
532
533   {
534     ScopedListen listen(idle_manager_, extension_->id());
535     idle_manager_->UpdateIdleState();
536     testing::Mock::VerifyAndClearExpectations(event_delegate_);
537
538     idle_provider_->set_idle_time(61);
539     EXPECT_CALL(*event_delegate_,
540                 OnStateChanged(extension_->id(), IDLE_STATE_IDLE));
541     idle_manager_->UpdateIdleState();
542   }
543 }
544
545 // Verifies that unloading an extension with no listeners or threshold works.
546 TEST_F(IdleTest, UnloadOnly) {
547   UnloadedExtensionInfo details(extension_.get(),
548                                 UnloadedExtensionInfo::REASON_UNINSTALL);
549   idle_manager_->Observe(
550       chrome::NOTIFICATION_EXTENSION_UNLOADED,
551       content::Source<Profile>(browser()->profile()),
552       content::Details<UnloadedExtensionInfo>(&details));
553 }
554
555 // Verifies that its ok for the unload notification to happen before all the
556 // listener removals.
557 TEST_F(IdleTest, UnloadWhileListening) {
558   ScopedListen listen(idle_manager_, extension_->id());
559   UnloadedExtensionInfo details(extension_.get(),
560                                 UnloadedExtensionInfo::REASON_UNINSTALL);
561   idle_manager_->Observe(
562       chrome::NOTIFICATION_EXTENSION_UNLOADED,
563       content::Source<Profile>(browser()->profile()),
564       content::Details<UnloadedExtensionInfo>(&details));
565 }
566
567 }  // namespace extensions