[iOS] DataTransfer.getData always returns the empty string when dropping text
[WebKit-https.git] / Source / WebKit / UIProcess / BackgroundProcessResponsivenessTimer.cpp
1 /*
2  * Copyright (C) 2017 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. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "BackgroundProcessResponsivenessTimer.h"
28
29 #include "Logging.h"
30 #include "WebProcessMessages.h"
31 #include "WebProcessProxy.h"
32
33 namespace WebKit {
34
35 static const Seconds initialCheckingInterval { 20_s };
36 static const Seconds maximumCheckingInterval { 8_h };
37 static const Seconds responsivenessTimeout { 90_s };
38
39 BackgroundProcessResponsivenessTimer::BackgroundProcessResponsivenessTimer(WebProcessProxy& webProcessProxy)
40     : m_webProcessProxy(webProcessProxy)
41     , m_checkingInterval(initialCheckingInterval)
42     , m_responsivenessCheckTimer(RunLoop::main(), this, &BackgroundProcessResponsivenessTimer::responsivenessCheckTimerFired)
43     , m_timeoutTimer(RunLoop::main(), this, &BackgroundProcessResponsivenessTimer::timeoutTimerFired)
44 {
45 }
46
47 BackgroundProcessResponsivenessTimer::~BackgroundProcessResponsivenessTimer()
48 {
49 }
50
51 void BackgroundProcessResponsivenessTimer::updateState()
52 {
53     if (!shouldBeActive()) {
54         if (m_responsivenessCheckTimer.isActive()) {
55             m_checkingInterval = initialCheckingInterval;
56             m_responsivenessCheckTimer.stop();
57         }
58         m_timeoutTimer.stop();
59         m_isResponsive = true;
60         return;
61     }
62
63     if (!isActive())
64         m_responsivenessCheckTimer.startOneShot(m_checkingInterval);
65 }
66
67 void BackgroundProcessResponsivenessTimer::didReceiveBackgroundResponsivenessPong()
68 {
69     if (!m_timeoutTimer.isActive())
70         return;
71
72     m_timeoutTimer.stop();
73     scheduleNextResponsivenessCheck();
74
75     setResponsive(true);
76 }
77
78 void BackgroundProcessResponsivenessTimer::invalidate()
79 {
80     m_timeoutTimer.stop();
81     m_responsivenessCheckTimer.stop();
82 }
83
84 void BackgroundProcessResponsivenessTimer::processTerminated()
85 {
86     invalidate();
87     setResponsive(true);
88 }
89
90 void BackgroundProcessResponsivenessTimer::responsivenessCheckTimerFired()
91 {
92     ASSERT(shouldBeActive());
93     ASSERT(!m_timeoutTimer.isActive());
94
95     m_timeoutTimer.startOneShot(responsivenessTimeout);
96     m_webProcessProxy.send(Messages::WebProcess::BackgroundResponsivenessPing(), 0);
97 }
98
99 void BackgroundProcessResponsivenessTimer::timeoutTimerFired()
100 {
101     ASSERT(shouldBeActive());
102
103     scheduleNextResponsivenessCheck();
104
105     if (!m_isResponsive)
106         return;
107
108     if (!client().mayBecomeUnresponsive())
109         return;
110
111     setResponsive(false);
112 }
113
114 void BackgroundProcessResponsivenessTimer::setResponsive(bool isResponsive)
115 {
116     if (m_isResponsive == isResponsive)
117         return;
118
119     client().willChangeIsResponsive();
120     m_isResponsive = isResponsive;
121     client().didChangeIsResponsive();
122
123     if (m_isResponsive) {
124         RELEASE_LOG_ERROR(PerformanceLogging, "Notifying the client that background WebProcess with pid %d has become responsive again", m_webProcessProxy.processIdentifier());
125         client().didBecomeResponsive();
126     } else {
127         RELEASE_LOG_ERROR(PerformanceLogging, "Notifying the client that background WebProcess with pid %d has become unresponsive", m_webProcessProxy.processIdentifier());
128         client().didBecomeUnresponsive();
129     }
130 }
131
132 bool BackgroundProcessResponsivenessTimer::shouldBeActive() const
133 {
134 #if !PLATFORM(IOS)
135     return !m_webProcessProxy.visiblePageCount() && m_webProcessProxy.pageCount();
136 #else
137     // Disable background process responsiveness checking on iOS since such processes usually get suspended.
138     return false;
139 #endif
140 }
141
142 bool BackgroundProcessResponsivenessTimer::isActive() const
143 {
144     return m_responsivenessCheckTimer.isActive() || m_timeoutTimer.isActive();
145 }
146
147 void BackgroundProcessResponsivenessTimer::scheduleNextResponsivenessCheck()
148 {
149     // Exponential backoff to avoid waking up the process too often.
150     ASSERT(!m_responsivenessCheckTimer.isActive());
151     m_checkingInterval = std::min(m_checkingInterval * 2, maximumCheckingInterval);
152     m_responsivenessCheckTimer.startOneShot(m_checkingInterval);
153 }
154
155 ResponsivenessTimer::Client& BackgroundProcessResponsivenessTimer::client() const
156 {
157     return m_webProcessProxy;
158 }
159
160 } // namespace WebKit