6fd707bf732ec10f3def493c694d889b00e0a7cc
[WebKit-https.git] / Source / WebCore / platform / cf / SharedTimerCF.cpp
1 /*
2  * Copyright (C) 2006, 2010, 2015 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #import "config.h"
27 #import "SharedTimer.h"
28
29 #include <wtf/AutodrainedPool.h>
30
31 #if PLATFORM(MAC)
32 #import "PowerObserverMac.h"
33 #elif PLATFORM(IOS)
34 #import "WebCoreThread.h"
35 #import "WebCoreThreadRun.h"
36 #endif
37
38 namespace WebCore {
39
40 static CFRunLoopTimerRef sharedTimer;
41 static void (*sharedTimerFiredFunction)();
42 static void timerFired(CFRunLoopTimerRef, void*);
43 static void restartSharedTimer();
44
45 static const CFTimeInterval kCFTimeIntervalDistantFuture = std::numeric_limits<CFTimeInterval>::max();
46
47 #if PLATFORM(IOS)
48 static void applicationDidBecomeActive(CFNotificationCenterRef, void*, CFStringRef, const void*, CFDictionaryRef)
49 {
50     WebThreadRun(^{
51         restartSharedTimer();
52     });
53 }
54 #endif
55
56 static void setupPowerObserver()
57 {
58 #if PLATFORM(MAC)
59     static PowerObserver* powerObserver;
60     if (!powerObserver)
61         powerObserver = std::make_unique<PowerObserver>(restartSharedTimer).release();
62 #elif PLATFORM(IOS)
63     static bool registeredForApplicationNotification = false;
64     if (!registeredForApplicationNotification) {
65         registeredForApplicationNotification = true;
66         CFNotificationCenterRef notificationCenter = CFNotificationCenterGetLocalCenter();
67         CFNotificationCenterAddObserver(notificationCenter, nullptr, applicationDidBecomeActive, CFSTR("UIApplicationDidBecomeActiveNotification"), nullptr, CFNotificationSuspensionBehaviorCoalesce);
68     }
69 #endif
70 }
71
72 void setSharedTimerFiredFunction(void (*f)())
73 {
74     ASSERT(!sharedTimerFiredFunction || sharedTimerFiredFunction == f);
75
76     sharedTimerFiredFunction = f;
77 }
78
79 static void timerFired(CFRunLoopTimerRef, void*)
80 {
81     AutodrainedPool pool;
82     sharedTimerFiredFunction();
83 }
84
85 static void restartSharedTimer()
86 {
87     if (!sharedTimer)
88         return;
89
90     stopSharedTimer();
91     timerFired(0, 0);
92 }
93
94 void invalidateSharedTimer()
95 {
96     if (!sharedTimer)
97         return;
98
99     CFRunLoopTimerInvalidate(sharedTimer);
100     CFRelease(sharedTimer);
101     sharedTimer = nullptr;
102 }
103
104 void setSharedTimerFireInterval(double interval)
105 {
106     ASSERT(sharedTimerFiredFunction);
107
108     CFAbsoluteTime fireDate = CFAbsoluteTimeGetCurrent() + interval;
109     if (!sharedTimer) {
110         sharedTimer = CFRunLoopTimerCreate(nullptr, fireDate, kCFTimeIntervalDistantFuture, 0, 0, timerFired, nullptr);
111 #if PLATFORM(IOS)
112         CFRunLoopAddTimer(WebThreadRunLoop(), sharedTimer, kCFRunLoopCommonModes);
113 #else
114         CFRunLoopAddTimer(CFRunLoopGetCurrent(), sharedTimer, kCFRunLoopCommonModes);
115 #endif
116
117         setupPowerObserver();
118
119         return;
120     }
121
122     CFRunLoopTimerSetNextFireDate(sharedTimer, fireDate);
123 }
124
125 void stopSharedTimer()
126 {
127     if (!sharedTimer)
128         return;
129
130     CFRunLoopTimerSetNextFireDate(sharedTimer, kCFTimeIntervalDistantFuture);
131 }
132
133 } // namespace WebCore