OLD | NEW |
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 #include "chrome/browser/sync/engine/syncer_thread.h" | 4 #include "chrome/browser/sync/engine/syncer_thread.h" |
5 | 5 |
6 #include "build/build_config.h" | 6 #include "build/build_config.h" |
7 | 7 |
8 #if defined(OS_MACOSX) | 8 #if defined(OS_MACOSX) |
9 #include <CoreFoundation/CFNumber.h> | 9 #include <CoreFoundation/CFNumber.h> |
10 #include <IOKit/IOTypes.h> | 10 #include <IOKit/IOTypes.h> |
(...skipping 13 matching lines...) Expand all Loading... |
24 #include "chrome/browser/sync/notifier/listener/talk_mediator_impl.h" | 24 #include "chrome/browser/sync/notifier/listener/talk_mediator_impl.h" |
25 #include "chrome/browser/sync/syncable/directory_manager.h" | 25 #include "chrome/browser/sync/syncable/directory_manager.h" |
26 #include "chrome/common/chrome_switches.h" | 26 #include "chrome/common/chrome_switches.h" |
27 | 27 |
28 using std::priority_queue; | 28 using std::priority_queue; |
29 using std::min; | 29 using std::min; |
30 using base::Time; | 30 using base::Time; |
31 using base::TimeDelta; | 31 using base::TimeDelta; |
32 using base::TimeTicks; | 32 using base::TimeTicks; |
33 | 33 |
34 namespace { | |
35 | |
36 // Returns the amount of time since the user last interacted with the computer, | |
37 // in milliseconds | |
38 int UserIdleTime() { | |
39 #if defined(OS_WIN) | |
40 LASTINPUTINFO last_input_info; | |
41 last_input_info.cbSize = sizeof(LASTINPUTINFO); | |
42 | |
43 // Get time in windows ticks since system start of last activity. | |
44 BOOL b = ::GetLastInputInfo(&last_input_info); | |
45 if (b == TRUE) | |
46 return ::GetTickCount() - last_input_info.dwTime; | |
47 #elif defined(OS_MACOSX) | |
48 // It would be great to do something like: | |
49 // | |
50 // return 1000 * | |
51 // CGEventSourceSecondsSinceLastEventType( | |
52 // kCGEventSourceStateCombinedSessionState, | |
53 // kCGAnyInputEventType); | |
54 // | |
55 // Unfortunately, CGEvent* lives in ApplicationServices, and we're a daemon | |
56 // and can't link that high up the food chain. Thus this mucking in IOKit. | |
57 | |
58 io_service_t hid_service = | |
59 IOServiceGetMatchingService(kIOMasterPortDefault, | |
60 IOServiceMatching("IOHIDSystem")); | |
61 if (!hid_service) { | |
62 LOG(WARNING) << "Could not obtain IOHIDSystem"; | |
63 return 0; | |
64 } | |
65 | |
66 CFTypeRef object = IORegistryEntryCreateCFProperty(hid_service, | |
67 CFSTR("HIDIdleTime"), | |
68 kCFAllocatorDefault, | |
69 0); | |
70 if (!object) { | |
71 LOG(WARNING) << "Could not get IOHIDSystem's HIDIdleTime property"; | |
72 IOObjectRelease(hid_service); | |
73 return 0; | |
74 } | |
75 | |
76 int64 idle_time; // in nanoseconds | |
77 Boolean success = false; | |
78 if (CFGetTypeID(object) == CFNumberGetTypeID()) { | |
79 success = CFNumberGetValue((CFNumberRef)object, | |
80 kCFNumberSInt64Type, | |
81 &idle_time); | |
82 } else { | |
83 LOG(WARNING) << "IOHIDSystem's HIDIdleTime property isn't a number!"; | |
84 } | |
85 | |
86 CFRelease(object); | |
87 IOObjectRelease(hid_service); | |
88 | |
89 if (!success) { | |
90 LOG(WARNING) << "Could not get IOHIDSystem's HIDIdleTime property's value"; | |
91 return 0; | |
92 } else { | |
93 return idle_time / 1000000; // nano to milli | |
94 } | |
95 #else | |
96 static bool was_logged = false; | |
97 if (!was_logged) { | |
98 was_logged = true; | |
99 LOG(INFO) << "UserIdleTime unimplemented on this platform, " | |
100 "synchronization will not throttle when user idle"; | |
101 } | |
102 #endif | |
103 | |
104 return 0; | |
105 } | |
106 | |
107 } // namespace | |
108 | 34 |
109 namespace browser_sync { | 35 namespace browser_sync { |
110 | 36 |
111 const int SyncerThread::kDefaultShortPollIntervalSeconds = 60; | 37 const int SyncerThread::kDefaultShortPollIntervalSeconds = 60; |
112 const int SyncerThread::kDefaultLongPollIntervalSeconds = 3600; | 38 const int SyncerThread::kDefaultLongPollIntervalSeconds = 3600; |
113 const int SyncerThread::kDefaultMaxPollIntervalMs = 30 * 60 * 1000; | 39 const int SyncerThread::kDefaultMaxPollIntervalMs = 30 * 60 * 1000; |
114 | 40 |
115 void SyncerThread::NudgeSyncer(int milliseconds_from_now, NudgeSource source) { | 41 void SyncerThread::NudgeSyncer(int milliseconds_from_now, NudgeSource source) { |
116 AutoLock lock(lock_); | 42 AutoLock lock(lock_); |
117 if (vault_.syncer_ == NULL) { | 43 if (vault_.syncer_ == NULL) { |
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
253 LOG(INFO) << "In thread main loop."; | 179 LOG(INFO) << "In thread main loop."; |
254 | 180 |
255 // Use the short poll value by default. | 181 // Use the short poll value by default. |
256 vault_.current_wait_interval_.poll_delta = | 182 vault_.current_wait_interval_.poll_delta = |
257 TimeDelta::FromSeconds(syncer_short_poll_interval_seconds_); | 183 TimeDelta::FromSeconds(syncer_short_poll_interval_seconds_); |
258 int user_idle_milliseconds = 0; | 184 int user_idle_milliseconds = 0; |
259 TimeTicks last_sync_time; | 185 TimeTicks last_sync_time; |
260 bool initial_sync_for_thread = true; | 186 bool initial_sync_for_thread = true; |
261 bool continue_sync_cycle = false; | 187 bool continue_sync_cycle = false; |
262 | 188 |
| 189 #if defined(OS_LINUX) |
| 190 idle_query_.reset(new IdleQueryLinux()); |
| 191 #endif |
| 192 |
263 while (!vault_.stop_syncer_thread_) { | 193 while (!vault_.stop_syncer_thread_) { |
264 // The Wait()s in these conditionals using |vault_| are not TimedWait()s (as | 194 // The Wait()s in these conditionals using |vault_| are not TimedWait()s (as |
265 // below) because we cannot poll until these conditions are met, so we wait | 195 // below) because we cannot poll until these conditions are met, so we wait |
266 // indefinitely. | 196 // indefinitely. |
267 if (!vault_.connected_) { | 197 if (!vault_.connected_) { |
268 LOG(INFO) << "Syncer thread waiting for connection."; | 198 LOG(INFO) << "Syncer thread waiting for connection."; |
269 while (!vault_.connected_ && !vault_.stop_syncer_thread_) | 199 while (!vault_.connected_ && !vault_.stop_syncer_thread_) |
270 vault_field_changed_.Wait(); | 200 vault_field_changed_.Wait(); |
271 LOG_IF(INFO, vault_.connected_) << "Syncer thread found connection."; | 201 LOG_IF(INFO, vault_.connected_) << "Syncer thread found connection."; |
272 continue; | 202 continue; |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
322 LOG(INFO) << "Calling Sync Main at time " << Time::Now().ToInternalValue(); | 252 LOG(INFO) << "Calling Sync Main at time " << Time::Now().ToInternalValue(); |
323 SyncMain(vault_.syncer_); | 253 SyncMain(vault_.syncer_); |
324 last_sync_time = TimeTicks::Now(); | 254 last_sync_time = TimeTicks::Now(); |
325 | 255 |
326 LOG(INFO) << "Updating the next polling time after SyncMain"; | 256 LOG(INFO) << "Updating the next polling time after SyncMain"; |
327 vault_.current_wait_interval_ = CalculatePollingWaitTime( | 257 vault_.current_wait_interval_ = CalculatePollingWaitTime( |
328 allstatus_->status(), | 258 allstatus_->status(), |
329 static_cast<int>(vault_.current_wait_interval_.poll_delta.InSeconds()), | 259 static_cast<int>(vault_.current_wait_interval_.poll_delta.InSeconds()), |
330 &user_idle_milliseconds, &continue_sync_cycle, nudged); | 260 &user_idle_milliseconds, &continue_sync_cycle, nudged); |
331 } | 261 } |
| 262 #if defined(OS_LINUX) |
| 263 idle_query_.reset(); |
| 264 #endif |
332 } | 265 } |
333 | 266 |
334 // We check how long the user's been idle and sync less often if the machine is | 267 // We check how long the user's been idle and sync less often if the machine is |
335 // not in use. The aim is to reduce server load. | 268 // not in use. The aim is to reduce server load. |
336 // TODO(timsteele): Should use Time(Delta). | 269 // TODO(timsteele): Should use Time(Delta). |
337 SyncerThread::WaitInterval SyncerThread::CalculatePollingWaitTime( | 270 SyncerThread::WaitInterval SyncerThread::CalculatePollingWaitTime( |
338 const AllStatus::Status& status, | 271 const AllStatus::Status& status, |
339 int last_poll_wait, // Time in seconds. | 272 int last_poll_wait, // Time in seconds. |
340 int* user_idle_milliseconds, | 273 int* user_idle_milliseconds, |
341 bool* continue_sync_cycle, | 274 bool* continue_sync_cycle, |
(...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
630 } | 563 } |
631 break; | 564 break; |
632 default: | 565 default: |
633 break; | 566 break; |
634 } | 567 } |
635 | 568 |
636 session_context_->set_notifications_enabled(p2p_authenticated_ && | 569 session_context_->set_notifications_enabled(p2p_authenticated_ && |
637 p2p_subscribed_); | 570 p2p_subscribed_); |
638 } | 571 } |
639 | 572 |
| 573 // Returns the amount of time since the user last interacted with the computer, |
| 574 // in milliseconds |
| 575 int SyncerThread::UserIdleTime() { |
| 576 #if defined(OS_WIN) |
| 577 LASTINPUTINFO last_input_info; |
| 578 last_input_info.cbSize = sizeof(LASTINPUTINFO); |
| 579 |
| 580 // Get time in windows ticks since system start of last activity. |
| 581 BOOL b = ::GetLastInputInfo(&last_input_info); |
| 582 if (b == TRUE) |
| 583 return ::GetTickCount() - last_input_info.dwTime; |
| 584 #elif defined(OS_MACOSX) |
| 585 // It would be great to do something like: |
| 586 // |
| 587 // return 1000 * |
| 588 // CGEventSourceSecondsSinceLastEventType( |
| 589 // kCGEventSourceStateCombinedSessionState, |
| 590 // kCGAnyInputEventType); |
| 591 // |
| 592 // Unfortunately, CGEvent* lives in ApplicationServices, and we're a daemon |
| 593 // and can't link that high up the food chain. Thus this mucking in IOKit. |
| 594 |
| 595 io_service_t hid_service = |
| 596 IOServiceGetMatchingService(kIOMasterPortDefault, |
| 597 IOServiceMatching("IOHIDSystem")); |
| 598 if (!hid_service) { |
| 599 LOG(WARNING) << "Could not obtain IOHIDSystem"; |
| 600 return 0; |
| 601 } |
| 602 |
| 603 CFTypeRef object = IORegistryEntryCreateCFProperty(hid_service, |
| 604 CFSTR("HIDIdleTime"), |
| 605 kCFAllocatorDefault, |
| 606 0); |
| 607 if (!object) { |
| 608 LOG(WARNING) << "Could not get IOHIDSystem's HIDIdleTime property"; |
| 609 IOObjectRelease(hid_service); |
| 610 return 0; |
| 611 } |
| 612 |
| 613 int64 idle_time; // in nanoseconds |
| 614 Boolean success = false; |
| 615 if (CFGetTypeID(object) == CFNumberGetTypeID()) { |
| 616 success = CFNumberGetValue((CFNumberRef)object, |
| 617 kCFNumberSInt64Type, |
| 618 &idle_time); |
| 619 } else { |
| 620 LOG(WARNING) << "IOHIDSystem's HIDIdleTime property isn't a number!"; |
| 621 } |
| 622 |
| 623 CFRelease(object); |
| 624 IOObjectRelease(hid_service); |
| 625 |
| 626 if (!success) { |
| 627 LOG(WARNING) << "Could not get IOHIDSystem's HIDIdleTime property's value"; |
| 628 return 0; |
| 629 } else { |
| 630 return idle_time / 1000000; // nano to milli |
| 631 } |
| 632 #elif defined(OS_LINUX) |
| 633 if (idle_query_.get()) { |
| 634 return idle_query_->IdleTime(); |
| 635 } else { |
| 636 return 0; |
| 637 } |
| 638 #else |
| 639 static bool was_logged = false; |
| 640 if (!was_logged) { |
| 641 was_logged = true; |
| 642 LOG(INFO) << "UserIdleTime unimplemented on this platform, " |
| 643 "synchronization will not throttle when user idle"; |
| 644 } |
| 645 #endif |
| 646 |
| 647 return 0; |
| 648 } |
| 649 |
| 650 |
640 } // namespace browser_sync | 651 } // namespace browser_sync |
OLD | NEW |