1 /* |
|
2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0"" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * |
|
16 */ |
|
17 #include "cpwatchdog.h" |
|
18 #include <QCoreApplication> |
|
19 #include <QSettings> |
|
20 #include <QDebug> |
|
21 #include "cplogger.h" |
|
22 |
|
23 //const value definition |
|
24 const int DefaultMaxPluginBlackListedRuns = 5; |
|
25 const int DefaultWatchdogActivationLimit = 1; |
|
26 const int WatchdogActivationDisabled = -1; |
|
27 |
|
28 //Key definition for QSettings |
|
29 const QString KeyWatchDogStatus = "WatchDog"; |
|
30 const QString KeyWatchDogCpRunning = "cprunning"; |
|
31 const QString KeyWatchDogCrashCounter = "crashcounter"; |
|
32 const QString KeyWatchDogMaxPluginBlackListedRuns = "maxpluginblacklistedruns"; |
|
33 const QString KeyWatchDogActivationLimit = "activationlimit"; |
|
34 const QString KeyWatchDogQuarantine = "Quarantine"; |
|
35 const QString KeyWatchDogQuarantineUid = "uid"; |
|
36 const QString KeyWatchDogBlackList = "BlackList"; |
|
37 const QString KeyWatchDogBlackListUid = "uid"; |
|
38 const QString KeyWatchDogBlackListRunsAfterCrash = "runsaftercrash"; |
|
39 |
|
40 CpWatchDog *CpWatchDog::self = 0; |
|
41 |
|
42 CpWatchDog::PluginQuarantine::PluginQuarantine() |
|
43 : mUid(0), mRunsAfterCrash(0) |
|
44 { |
|
45 } |
|
46 |
|
47 void CpWatchDog::PluginQuarantine::read(QSettings &settings) |
|
48 { |
|
49 mUid = settings.value(KeyWatchDogBlackListUid,0).toInt(); |
|
50 mRunsAfterCrash = settings.value(KeyWatchDogBlackListRunsAfterCrash,0).toInt(); |
|
51 } |
|
52 |
|
53 void CpWatchDog::PluginQuarantine::store(QSettings &settings) |
|
54 { |
|
55 settings.setValue(KeyWatchDogBlackListUid,mUid); |
|
56 settings.setValue(KeyWatchDogBlackListRunsAfterCrash,mRunsAfterCrash); |
|
57 } |
|
58 |
|
59 CpWatchDog *CpWatchDog::instance() |
|
60 { |
|
61 if (!self) { |
|
62 self = new CpWatchDog; |
|
63 } |
|
64 return self; |
|
65 } |
|
66 |
|
67 CpWatchDog::CpWatchDog() |
|
68 : mActive(true), |
|
69 mCrashCounter(0), |
|
70 mAppRunning(true), |
|
71 mMaxPluginBlackListedRuns(DefaultMaxPluginBlackListedRuns), |
|
72 mWatchdogActivationLimit(DefaultWatchdogActivationLimit) |
|
73 { |
|
74 //delete watch dog when application is about to quit. |
|
75 connect(qApp,SIGNAL(aboutToQuit()),this,SLOT(destroy())); |
|
76 init(); |
|
77 } |
|
78 |
|
79 CpWatchDog::~CpWatchDog() |
|
80 { |
|
81 reportCleanExit(); |
|
82 updateBlackListedPluginRunCounters(); |
|
83 storeState(); |
|
84 } |
|
85 |
|
86 void CpWatchDog::destroy() |
|
87 { |
|
88 delete this; |
|
89 self = 0; |
|
90 } |
|
91 |
|
92 void CpWatchDog::quarantine(int uid) |
|
93 { |
|
94 if (isActive()) { |
|
95 mQuarantine.append(uid); |
|
96 storeQuarantine(); |
|
97 } |
|
98 } |
|
99 void CpWatchDog::removeFromQuarantine(int uid) |
|
100 { |
|
101 if (isActive()) { |
|
102 int index = mQuarantine.indexOf(uid); |
|
103 if (index >= 0) { |
|
104 mQuarantine.remove(index); |
|
105 storeQuarantine(); |
|
106 } |
|
107 } |
|
108 } |
|
109 |
|
110 bool CpWatchDog::isActive() const |
|
111 { |
|
112 return mActive; |
|
113 } |
|
114 |
|
115 bool CpWatchDog::wasCleanExit() const |
|
116 { |
|
117 return !mAppRunning; |
|
118 } |
|
119 |
|
120 void CpWatchDog::reportCleanExit() |
|
121 { |
|
122 mAppRunning = false; |
|
123 |
|
124 QSettings settings; |
|
125 settings.beginGroup(KeyWatchDogStatus); |
|
126 settings.setValue(KeyWatchDogCpRunning,mAppRunning); |
|
127 settings.endGroup(); |
|
128 } |
|
129 |
|
130 bool CpWatchDog::isInBlackList(int uid) |
|
131 { |
|
132 bool found = false; |
|
133 if (isActive()) { |
|
134 foreach(const PluginQuarantine &quarantine,mBlackList) { |
|
135 if (quarantine.mUid == uid) { |
|
136 found = true; |
|
137 break; |
|
138 } |
|
139 } |
|
140 } |
|
141 |
|
142 if (found) { |
|
143 CPFW_LOG( QLatin1String("Plugin ") + QString("0x%1").arg(uid,0,16) + QLatin1String(" is in black list.")); |
|
144 } |
|
145 |
|
146 return found; |
|
147 } |
|
148 |
|
149 void CpWatchDog::init() |
|
150 { |
|
151 readState(); |
|
152 |
|
153 if (!wasCleanExit() |
|
154 && mWatchdogActivationLimit != WatchdogActivationDisabled) { |
|
155 mCrashCounter++; |
|
156 mActive = true; |
|
157 |
|
158 for (int i(0); i < mQuarantine.size(); i++) { |
|
159 if (!isInBlackList(mQuarantine[i])) { |
|
160 PluginQuarantine quarantine; |
|
161 quarantine.mUid = mQuarantine[i]; |
|
162 quarantine.mRunsAfterCrash = 0; |
|
163 mBlackList.append(quarantine); |
|
164 mQuarantine.remove(i); |
|
165 i--; |
|
166 } |
|
167 } |
|
168 } |
|
169 else { |
|
170 mActive = false; |
|
171 mCrashCounter = 0; |
|
172 mQuarantine.clear(); |
|
173 } |
|
174 |
|
175 mAppRunning = true; |
|
176 storeState(); |
|
177 } |
|
178 |
|
179 void CpWatchDog::readState() |
|
180 { |
|
181 QSettings settings; |
|
182 settings.beginGroup(KeyWatchDogStatus); |
|
183 int appRunning = settings.value(KeyWatchDogCpRunning,0).toInt(); |
|
184 mAppRunning = (appRunning != 0); |
|
185 mCrashCounter = settings.value(KeyWatchDogCrashCounter,0).toInt(); |
|
186 mMaxPluginBlackListedRuns = settings.value( |
|
187 KeyWatchDogMaxPluginBlackListedRuns,DefaultMaxPluginBlackListedRuns).toInt(); |
|
188 mWatchdogActivationLimit = settings.value( |
|
189 KeyWatchDogActivationLimit,DefaultWatchdogActivationLimit).toInt(); |
|
190 settings.endGroup(); |
|
191 |
|
192 readQuarantine(); |
|
193 readBlackList(); |
|
194 } |
|
195 |
|
196 void CpWatchDog::storeState() |
|
197 { |
|
198 { |
|
199 QSettings settings; |
|
200 settings.beginGroup(KeyWatchDogStatus); |
|
201 settings.setValue(KeyWatchDogCpRunning, mAppRunning ? 1 : 0); |
|
202 settings.setValue(KeyWatchDogCrashCounter,mCrashCounter); |
|
203 settings.setValue(KeyWatchDogMaxPluginBlackListedRuns,mMaxPluginBlackListedRuns); |
|
204 settings.setValue(KeyWatchDogActivationLimit,mWatchdogActivationLimit); |
|
205 settings.endGroup(); |
|
206 } //Destructor of QSettings: writes any unsaved changes to permanent storage |
|
207 |
|
208 storeQuarantine(); |
|
209 storeBlackList(); |
|
210 } |
|
211 |
|
212 void CpWatchDog::readQuarantine() |
|
213 { |
|
214 QSettings settings; |
|
215 int size = settings.beginReadArray(KeyWatchDogQuarantine); |
|
216 for (int i(0); i < size; i++) { |
|
217 settings.setArrayIndex(i); |
|
218 int uid = settings.value(KeyWatchDogQuarantineUid,0).toInt(); |
|
219 if (uid != 0) { |
|
220 mQuarantine.append(uid); |
|
221 } |
|
222 } |
|
223 settings.endArray(); |
|
224 } |
|
225 |
|
226 void CpWatchDog::storeQuarantine() |
|
227 { |
|
228 QSettings settings; |
|
229 |
|
230 //remove old array data before updating |
|
231 settings.beginGroup(KeyWatchDogQuarantine); |
|
232 settings.remove(QString()); |
|
233 settings.endGroup(); |
|
234 |
|
235 settings.beginWriteArray(KeyWatchDogQuarantine); |
|
236 int size = mQuarantine.size(); |
|
237 for (int i(0); i < size; i++) { |
|
238 settings.setArrayIndex(i); |
|
239 settings.setValue(KeyWatchDogQuarantineUid,mQuarantine[i]); |
|
240 } |
|
241 settings.endArray(); |
|
242 } |
|
243 |
|
244 void CpWatchDog::readBlackList() |
|
245 { |
|
246 QSettings settings; |
|
247 int size = settings.beginReadArray(KeyWatchDogBlackList); |
|
248 for (int i(0); i < size; i++) { |
|
249 settings.setArrayIndex(i); |
|
250 PluginQuarantine quarantine; |
|
251 quarantine.read(settings); |
|
252 if (quarantine.mUid != 0) { |
|
253 mBlackList.append(quarantine); |
|
254 } |
|
255 } |
|
256 settings.endArray(); |
|
257 } |
|
258 |
|
259 void CpWatchDog::storeBlackList() |
|
260 { |
|
261 QSettings settings; |
|
262 |
|
263 //remove old array data before updating |
|
264 settings.beginGroup(KeyWatchDogBlackList); |
|
265 settings.remove(QString()); |
|
266 settings.endGroup(); |
|
267 |
|
268 settings.beginWriteArray(KeyWatchDogBlackList); |
|
269 int size = mBlackList.size(); |
|
270 for (int i(0); i < size; i++) { |
|
271 settings.setArrayIndex(i); |
|
272 mBlackList[i].store(settings); |
|
273 } |
|
274 settings.endArray(); |
|
275 } |
|
276 |
|
277 void CpWatchDog::updateBlackListedPluginRunCounters() |
|
278 { |
|
279 for (int i(0); i < mBlackList.size(); i++) { |
|
280 mBlackList[i].mRunsAfterCrash++; |
|
281 if (mBlackList[i].mRunsAfterCrash > mMaxPluginBlackListedRuns) { |
|
282 mBlackList.remove(i); |
|
283 i--; |
|
284 } |
|
285 } |
|
286 } |
|