Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
michael@0 | 1 | // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
michael@0 | 2 | // Use of this source code is governed by a BSD-style license that can be |
michael@0 | 3 | // found in the LICENSE file. |
michael@0 | 4 | |
michael@0 | 5 | #include "base/idle_timer.h" |
michael@0 | 6 | |
michael@0 | 7 | // We may not want to port idle_timer to Linux, but we have implemented it |
michael@0 | 8 | // anyway. Define this to 1 to enable the Linux idle timer and then add the |
michael@0 | 9 | // libs that need to be linked (Xss). |
michael@0 | 10 | #define ENABLE_XSS_SUPPORT 0 |
michael@0 | 11 | |
michael@0 | 12 | #if defined(OS_MACOSX) |
michael@0 | 13 | #include <ApplicationServices/ApplicationServices.h> |
michael@0 | 14 | #endif |
michael@0 | 15 | |
michael@0 | 16 | #if defined(OS_LINUX) && ENABLE_XSS_SUPPORT |
michael@0 | 17 | // We may not want to port idle_timer to Linux, but we have implemented it |
michael@0 | 18 | // anyway. Remove the 0 above if we want it. |
michael@0 | 19 | #include <gdk/gdkx.h> |
michael@0 | 20 | #include <X11/extensions/scrnsaver.h> |
michael@0 | 21 | #include "base/lazy_instance.h" |
michael@0 | 22 | #include "base/thread_local.h" |
michael@0 | 23 | #endif |
michael@0 | 24 | |
michael@0 | 25 | #include "base/message_loop.h" |
michael@0 | 26 | #include "base/time.h" |
michael@0 | 27 | |
michael@0 | 28 | namespace base { |
michael@0 | 29 | |
michael@0 | 30 | #if defined(OS_WIN) |
michael@0 | 31 | bool OSIdleTimeSource(int32_t *milliseconds_interval_since_last_event) { |
michael@0 | 32 | LASTINPUTINFO lastInputInfo; |
michael@0 | 33 | lastInputInfo.cbSize = sizeof(lastInputInfo); |
michael@0 | 34 | if (GetLastInputInfo(&lastInputInfo) == 0) { |
michael@0 | 35 | return false; |
michael@0 | 36 | } |
michael@0 | 37 | int32_t last_input_time = lastInputInfo.dwTime; |
michael@0 | 38 | |
michael@0 | 39 | // Note: On Windows GetLastInputInfo returns a 32bit value which rolls over |
michael@0 | 40 | // ~49days. |
michael@0 | 41 | int32_t current_time = GetTickCount(); |
michael@0 | 42 | int32_t delta = current_time - last_input_time; |
michael@0 | 43 | // delta will go negative if we've been idle for 2GB of ticks. |
michael@0 | 44 | if (delta < 0) |
michael@0 | 45 | delta = -delta; |
michael@0 | 46 | *milliseconds_interval_since_last_event = delta; |
michael@0 | 47 | return true; |
michael@0 | 48 | } |
michael@0 | 49 | #elif defined(OS_MACOSX) |
michael@0 | 50 | bool OSIdleTimeSource(int32_t *milliseconds_interval_since_last_event) { |
michael@0 | 51 | *milliseconds_interval_since_last_event = |
michael@0 | 52 | CGEventSourceSecondsSinceLastEventType( |
michael@0 | 53 | kCGEventSourceStateCombinedSessionState, |
michael@0 | 54 | kCGAnyInputEventType) * 1000.0; |
michael@0 | 55 | return true; |
michael@0 | 56 | } |
michael@0 | 57 | #elif defined(OS_LINUX) && ENABLE_XSS_SUPPORT |
michael@0 | 58 | class IdleState { |
michael@0 | 59 | public: |
michael@0 | 60 | IdleState() { |
michael@0 | 61 | int event_base, error_base; |
michael@0 | 62 | have_idle_info_ = XScreenSaverQueryExtension(GDK_DISPLAY(), &event_base, |
michael@0 | 63 | &error_base); |
michael@0 | 64 | if (have_idle_info_) |
michael@0 | 65 | idle_info_.Set(XScreenSaverAllocInfo()); |
michael@0 | 66 | } |
michael@0 | 67 | |
michael@0 | 68 | ~IdleState() { |
michael@0 | 69 | if (idle_info_.Get()) { |
michael@0 | 70 | XFree(idle_info_.Get()); |
michael@0 | 71 | idle_info_.~ThreadLocalPointer(); |
michael@0 | 72 | } |
michael@0 | 73 | } |
michael@0 | 74 | |
michael@0 | 75 | int32_t IdleTime() { |
michael@0 | 76 | if (have_idle_info_ && idle_info_.Get()) { |
michael@0 | 77 | XScreenSaverQueryInfo(GDK_DISPLAY(), GDK_ROOT_WINDOW(), |
michael@0 | 78 | idle_info_.Get()); |
michael@0 | 79 | return idle_info_.Get()->idle; |
michael@0 | 80 | } |
michael@0 | 81 | return -1; |
michael@0 | 82 | } |
michael@0 | 83 | |
michael@0 | 84 | private: |
michael@0 | 85 | bool have_idle_info_; |
michael@0 | 86 | ThreadLocalPointer<XScreenSaverInfo> idle_info_; |
michael@0 | 87 | |
michael@0 | 88 | DISALLOW_COPY_AND_ASSIGN(IdleState); |
michael@0 | 89 | }; |
michael@0 | 90 | |
michael@0 | 91 | bool OSIdleTimeSource(int32_t* milliseconds_interval_since_last_event) { |
michael@0 | 92 | static LazyInstance<IdleState> state_instance(base::LINKER_INITIALIZED); |
michael@0 | 93 | IdleState* state = state_instance.Pointer(); |
michael@0 | 94 | int32_t idle_time = state->IdleTime(); |
michael@0 | 95 | if (0 < idle_time) { |
michael@0 | 96 | *milliseconds_interval_since_last_event = idle_time; |
michael@0 | 97 | return true; |
michael@0 | 98 | } |
michael@0 | 99 | return false; |
michael@0 | 100 | } |
michael@0 | 101 | #endif |
michael@0 | 102 | |
michael@0 | 103 | IdleTimer::IdleTimer(TimeDelta idle_time, bool repeat) |
michael@0 | 104 | : idle_interval_(idle_time), |
michael@0 | 105 | repeat_(repeat), |
michael@0 | 106 | idle_time_source_(OSIdleTimeSource) { |
michael@0 | 107 | DCHECK_EQ(MessageLoop::TYPE_UI, MessageLoop::current()->type()) << |
michael@0 | 108 | "Requires a thread that processes Windows UI events"; |
michael@0 | 109 | } |
michael@0 | 110 | |
michael@0 | 111 | IdleTimer::~IdleTimer() { |
michael@0 | 112 | Stop(); |
michael@0 | 113 | } |
michael@0 | 114 | |
michael@0 | 115 | void IdleTimer::Start() { |
michael@0 | 116 | StartTimer(); |
michael@0 | 117 | } |
michael@0 | 118 | |
michael@0 | 119 | void IdleTimer::Stop() { |
michael@0 | 120 | timer_.Stop(); |
michael@0 | 121 | } |
michael@0 | 122 | |
michael@0 | 123 | void IdleTimer::Run() { |
michael@0 | 124 | // Verify we can fire the idle timer. |
michael@0 | 125 | if (TimeUntilIdle().InMilliseconds() <= 0) { |
michael@0 | 126 | OnIdle(); |
michael@0 | 127 | last_time_fired_ = Time::Now(); |
michael@0 | 128 | } |
michael@0 | 129 | Stop(); |
michael@0 | 130 | StartTimer(); // Restart the timer for next run. |
michael@0 | 131 | } |
michael@0 | 132 | |
michael@0 | 133 | void IdleTimer::StartTimer() { |
michael@0 | 134 | DCHECK(!timer_.IsRunning()); |
michael@0 | 135 | TimeDelta delay = TimeUntilIdle(); |
michael@0 | 136 | if (delay.InMilliseconds() < 0) |
michael@0 | 137 | delay = TimeDelta(); |
michael@0 | 138 | timer_.Start(delay, this, &IdleTimer::Run); |
michael@0 | 139 | } |
michael@0 | 140 | |
michael@0 | 141 | TimeDelta IdleTimer::CurrentIdleTime() { |
michael@0 | 142 | int32_t interval = 0; |
michael@0 | 143 | if (idle_time_source_(&interval)) { |
michael@0 | 144 | return TimeDelta::FromMilliseconds(interval); |
michael@0 | 145 | } |
michael@0 | 146 | NOTREACHED(); |
michael@0 | 147 | return TimeDelta::FromMilliseconds(0); |
michael@0 | 148 | } |
michael@0 | 149 | |
michael@0 | 150 | TimeDelta IdleTimer::TimeUntilIdle() { |
michael@0 | 151 | TimeDelta time_since_last_fire = Time::Now() - last_time_fired_; |
michael@0 | 152 | TimeDelta current_idle_time = CurrentIdleTime(); |
michael@0 | 153 | if (current_idle_time > time_since_last_fire) { |
michael@0 | 154 | if (repeat_) |
michael@0 | 155 | return idle_interval_ - time_since_last_fire; |
michael@0 | 156 | return idle_interval_; |
michael@0 | 157 | } |
michael@0 | 158 | return idle_interval_ - current_idle_time; |
michael@0 | 159 | } |
michael@0 | 160 | |
michael@0 | 161 | } // namespace base |