| 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 |