OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 | 4 |
5 #include <set> | 5 #include <set> |
6 #include <vector> | 6 #include <vector> |
7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
8 #include "base/json/json_string_value_serializer.h" | 8 #include "base/json/json_string_value_serializer.h" |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/string_util.h" | 10 #include "base/string_util.h" |
11 #include "base/threading/thread_checker.h" | 11 #include "base/threading/thread_checker.h" |
12 #include "chrome/browser/extensions/activity_log/activity_log.h" | 12 #include "chrome/browser/extensions/activity_log/activity_log.h" |
13 #include "chrome/browser/extensions/activity_log/api_actions.h" | 13 #include "chrome/browser/extensions/activity_log/api_actions.h" |
14 #include "chrome/browser/extensions/activity_log/blocked_actions.h" | 14 #include "chrome/browser/extensions/activity_log/blocked_actions.h" |
15 #include "chrome/browser/extensions/activity_log/stream_noargs_ui_policy.h" | |
15 #include "chrome/browser/extensions/extension_service.h" | 16 #include "chrome/browser/extensions/extension_service.h" |
16 #include "chrome/browser/extensions/extension_system.h" | 17 #include "chrome/browser/extensions/extension_system.h" |
17 #include "chrome/browser/profiles/incognito_helpers.h" | 18 #include "chrome/browser/profiles/incognito_helpers.h" |
18 #include "chrome/common/chrome_constants.h" | 19 #include "chrome/common/chrome_constants.h" |
19 #include "chrome/common/chrome_switches.h" | 20 #include "chrome/common/chrome_switches.h" |
20 #include "chrome/common/extensions/extension.h" | 21 #include "chrome/common/extensions/extension.h" |
21 #include "content/public/browser/web_contents.h" | 22 #include "content/public/browser/web_contents.h" |
22 #include "googleurl/src/gurl.h" | 23 #include "googleurl/src/gurl.h" |
23 #include "sql/error_delegate_util.h" | 24 #include "sql/error_delegate_util.h" |
24 #include "third_party/re2/re2/re2.h" | 25 #include "third_party/re2/re2/re2.h" |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
81 // static | 82 // static |
82 bool ActivityLog::IsLogEnabled() { | 83 bool ActivityLog::IsLogEnabled() { |
83 return LogIsEnabled::GetInstance()->enabled(); | 84 return LogIsEnabled::GetInstance()->enabled(); |
84 } | 85 } |
85 | 86 |
86 // static | 87 // static |
87 void ActivityLog::RecomputeLoggingIsEnabled() { | 88 void ActivityLog::RecomputeLoggingIsEnabled() { |
88 return LogIsEnabled::GetInstance()->ComputeIsEnabled(); | 89 return LogIsEnabled::GetInstance()->ComputeIsEnabled(); |
89 } | 90 } |
90 | 91 |
91 // This handles errors from the database. | |
92 class KillActivityDatabaseErrorDelegate : public sql::ErrorDelegate { | |
93 public: | |
94 explicit KillActivityDatabaseErrorDelegate(ActivityLog* backend) | |
95 : backend_(backend), | |
96 scheduled_death_(false) {} | |
97 | |
98 virtual int OnError(int error, | |
99 sql::Connection* connection, | |
100 sql::Statement* stmt) OVERRIDE { | |
101 if (!scheduled_death_ && sql::IsErrorCatastrophic(error)) { | |
102 ScheduleDeath(); | |
103 } | |
104 return error; | |
105 } | |
106 | |
107 // Schedules death if an error wasn't already reported. | |
108 void ScheduleDeath() { | |
109 if (!scheduled_death_) { | |
110 scheduled_death_ = true; | |
111 backend_->KillActivityLogDatabase(); | |
112 } | |
113 } | |
114 | |
115 bool scheduled_death() const { | |
116 return scheduled_death_; | |
117 } | |
118 | |
119 private: | |
120 ActivityLog* backend_; | |
121 bool scheduled_death_; | |
122 | |
123 DISALLOW_COPY_AND_ASSIGN(KillActivityDatabaseErrorDelegate); | |
124 }; | |
125 | |
126 // ActivityLogFactory | 92 // ActivityLogFactory |
127 | 93 |
128 ActivityLogFactory* ActivityLogFactory::GetInstance() { | 94 ActivityLogFactory* ActivityLogFactory::GetInstance() { |
129 return Singleton<ActivityLogFactory>::get(); | 95 return Singleton<ActivityLogFactory>::get(); |
130 } | 96 } |
131 | 97 |
132 ProfileKeyedService* ActivityLogFactory::BuildServiceInstanceFor( | 98 ProfileKeyedService* ActivityLogFactory::BuildServiceInstanceFor( |
133 content::BrowserContext* profile) const { | 99 content::BrowserContext* profile) const { |
134 return new ActivityLog(static_cast<Profile*>(profile)); | 100 return new ActivityLog(static_cast<Profile*>(profile)); |
135 } | 101 } |
136 | 102 |
137 content::BrowserContext* ActivityLogFactory::GetBrowserContextToUse( | 103 content::BrowserContext* ActivityLogFactory::GetBrowserContextToUse( |
138 content::BrowserContext* context) const { | 104 content::BrowserContext* context) const { |
139 return chrome::GetBrowserContextRedirectedInIncognito(context); | 105 return chrome::GetBrowserContextRedirectedInIncognito(context); |
140 } | 106 } |
141 | 107 |
142 // ActivityLog | 108 // ActivityLog |
143 | 109 |
144 // Use GetInstance instead of directly creating an ActivityLog. | 110 // Use GetInstance instead of directly creating an ActivityLog. |
145 ActivityLog::ActivityLog(Profile* profile) : profile_(profile) { | 111 ActivityLog::ActivityLog(Profile* profile) : policy_(NULL), profile_(profile) { |
146 // enable-extension-activity-logging and enable-extension-activity-ui | 112 // enable-extension-activity-logging and enable-extension-activity-ui |
147 log_activity_to_stdout_ = CommandLine::ForCurrentProcess()->HasSwitch( | 113 log_activity_to_stdout_ = CommandLine::ForCurrentProcess()->HasSwitch( |
148 switches::kEnableExtensionActivityLogging); | 114 switches::kEnableExtensionActivityLogging); |
149 log_activity_to_ui_ = CommandLine::ForCurrentProcess()->HasSwitch( | 115 log_activity_to_ui_ = CommandLine::ForCurrentProcess()->HasSwitch( |
150 switches::kEnableExtensionActivityUI); | 116 switches::kEnableExtensionActivityUI); |
151 | 117 |
152 // enable-extension-activity-log-testing | |
153 // This controls whether arguments are collected. | |
154 testing_mode_ = CommandLine::ForCurrentProcess()->HasSwitch( | |
155 switches::kEnableExtensionActivityLogTesting); | |
156 if (!testing_mode_) { | |
157 for (int i = 0; i < APIAction::kSizeAlwaysLog; i++) { | |
158 arg_whitelist_api_.insert(std::string(APIAction::kAlwaysLog[i])); | |
159 } | |
160 } | |
161 | |
162 // We normally dispatch DB requests to the DB thread, but the thread might | 118 // We normally dispatch DB requests to the DB thread, but the thread might |
163 // not exist if we are under test conditions. Substitute the UI thread for | 119 // not exist if we are under test conditions. Substitute the UI thread for |
164 // this case. | 120 // this case. |
121 content::BrowserThread::ID dispatch_thread; | |
165 if (BrowserThread::IsMessageLoopValid(BrowserThread::DB)) { | 122 if (BrowserThread::IsMessageLoopValid(BrowserThread::DB)) { |
166 dispatch_thread_ = BrowserThread::DB; | 123 dispatch_thread = BrowserThread::DB; |
167 } else { | 124 } else { |
168 LOG(ERROR) << "BrowserThread::DB does not exist, running on UI thread!"; | 125 LOG(ERROR) << "BrowserThread::DB does not exist, running on UI thread!"; |
169 dispatch_thread_ = BrowserThread::UI; | 126 dispatch_thread = BrowserThread::UI; |
170 } | 127 } |
171 | 128 |
172 // If the database cannot be initialized for some reason, we keep | 129 // TODO(dbabic) In the next iteration, we should support multiple policies, |
173 // chugging along but nothing will get recorded. If the UI is | 130 // which are then polled by the ActivityLog object |
174 // available, things will still get sent to the UI even if nothing | 131 if (IsLogEnabled()) { |
175 // is being written to the database. | 132 switch (policy_type_) { |
felt
2013/05/24 18:43:38
Where is policy_type_ set?
dbabic
2013/05/28 21:11:49
There's a static constructor at the end of this fi
felt
2013/05/29 03:41:15
Ah, didn't see it. Cool.
On 2013/05/28 21:11:49,
| |
176 db_ = new ActivityDatabase(); | 133 case ActivityLogPolicy::POLICY_FULLSTREAM: |
177 if (!IsLogEnabled()) return; | 134 policy_ = new FullStreamUIPolicy(profile, dispatch_thread); |
178 base::FilePath base_dir = profile->GetPath(); | 135 break; |
179 base::FilePath database_name = base_dir.Append( | 136 case ActivityLogPolicy::POLICY_NOARGS: |
180 chrome::kExtensionActivityLogFilename); | 137 policy_ = new StreamWithoutArgsUIPolicy(profile, dispatch_thread); |
181 KillActivityDatabaseErrorDelegate* error_delegate = | 138 break; |
182 new KillActivityDatabaseErrorDelegate(this); | 139 } |
183 db_->SetErrorDelegate(error_delegate); | 140 } |
184 ScheduleAndForget(&ActivityDatabase::Init, database_name); | |
185 } | 141 } |
186 | 142 |
187 ActivityLog::~ActivityLog() { | 143 ActivityLog::~ActivityLog() { |
188 ScheduleAndForget(&ActivityDatabase::Close); | 144 delete policy_; |
189 } | |
190 | |
191 void ActivityLog::SetArgumentLoggingForTesting(bool log_arguments) { | |
192 testing_mode_ = log_arguments; | |
193 } | 145 } |
194 | 146 |
195 // static | 147 // static |
196 ActivityLog* ActivityLog::GetInstance(Profile* profile) { | 148 ActivityLog* ActivityLog::GetInstance(Profile* profile) { |
197 return ActivityLogFactory::GetForProfile(profile); | 149 return ActivityLogFactory::GetForProfile(profile); |
198 } | 150 } |
199 | 151 |
200 void ActivityLog::AddObserver(const Extension* extension, | 152 void ActivityLog::AddObserver(const Extension* extension, |
201 ActivityLog::Observer* observer) { | 153 ActivityLog::Observer* observer) { |
202 if (!IsLogEnabled()) return; | 154 if (!IsLogEnabled()) return; |
203 if (observers_.count(extension) == 0) | 155 if (observers_.count(extension) == 0) |
204 observers_[extension] = new ObserverListThreadSafe<Observer>; | 156 observers_[extension] = new ObserverListThreadSafe<Observer>; |
205 observers_[extension]->AddObserver(observer); | 157 observers_[extension]->AddObserver(observer); |
206 } | 158 } |
207 | 159 |
208 void ActivityLog::RemoveObserver(const Extension* extension, | 160 void ActivityLog::RemoveObserver(const Extension* extension, |
209 ActivityLog::Observer* observer) { | 161 ActivityLog::Observer* observer) { |
210 if (observers_.count(extension) == 1) | 162 if (observers_.count(extension) == 1) |
211 observers_[extension]->RemoveObserver(observer); | 163 observers_[extension]->RemoveObserver(observer); |
212 } | 164 } |
213 | 165 |
214 void ActivityLog::LogAPIActionInternal(const Extension* extension, | 166 void ActivityLog::LogAPIActionInternal(const Extension* extension, |
215 const std::string& api_call, | 167 const std::string& api_call, |
216 ListValue* args, | 168 ListValue* args, |
217 const std::string& extra, | 169 const std::string& extra, |
218 const APIAction::Type type) { | 170 const APIAction::Type type) { |
171 if (!extension) | |
felt
2013/05/24 18:43:38
Note that these checks help with but still don't s
dbabic
2013/05/28 21:11:49
Sorry, I didn't understand why this doesn't fix th
felt
2013/05/29 03:41:15
Yup, if the extension is uninstalled, the extensio
| |
172 return; | |
173 | |
219 std::string verb, manager; | 174 std::string verb, manager; |
220 bool matches = RE2::FullMatch(api_call, "(.*?)\\.(.*)", &manager, &verb); | 175 bool matches = RE2::FullMatch(api_call, "(.*?)\\.(.*)", &manager, &verb); |
221 if (matches) { | 176 if (matches) { |
222 if (!args->empty() && manager == "tabs") { | 177 if (!args->empty() && manager == "tabs") { |
223 APIAction::LookupTabId(api_call, args, profile_); | 178 APIAction::LookupTabId(api_call, args, profile_); |
224 } | 179 } |
180 | |
181 if (policy_) { | |
182 DCHECK((type == APIAction::CALL || type == APIAction::EVENT_CALLBACK) && | |
183 "Unexpected APIAction call type."); | |
184 policy_->ProcessAction( | |
185 type == APIAction::CALL ? ActivityLogPolicy::ACTION_API : | |
186 ActivityLogPolicy::ACTION_EVENT, | |
187 *extension, | |
188 api_call, | |
189 NULL, | |
190 args, | |
191 NULL); | |
192 } | |
193 | |
194 // TODO(felt) Logging should be done more efficiently, so that it | |
195 // doesn't require construction of the action object. | |
225 scoped_refptr<APIAction> action = new APIAction( | 196 scoped_refptr<APIAction> action = new APIAction( |
226 extension->id(), | 197 extension->id(), |
227 base::Time::Now(), | 198 base::Time::Now(), |
228 type, | 199 type, |
229 api_call, | 200 api_call, |
230 MakeArgList(args), | 201 MakeArgList(args), |
231 extra); | 202 extra); |
232 ScheduleAndForget(&ActivityDatabase::RecordAction, action); | |
233 | 203 |
234 // Display the action. | 204 // Display the action. |
235 ObserverMap::const_iterator iter = observers_.find(extension); | 205 ObserverMap::const_iterator iter = observers_.find(extension); |
236 if (iter != observers_.end()) { | 206 if (iter != observers_.end()) { |
237 if (type == APIAction::CALL) { | 207 if (type == APIAction::CALL) { |
238 iter->second->Notify(&Observer::OnExtensionActivity, | 208 iter->second->Notify(&Observer::OnExtensionActivity, |
239 extension, | 209 extension, |
240 ActivityLog::ACTIVITY_EXTENSION_API_CALL, | 210 ActivityLog::ACTIVITY_EXTENSION_API_CALL, |
241 MakeCallSignature(api_call, args)); | 211 MakeCallSignature(api_call, args)); |
242 } else if (type == APIAction::EVENT_CALLBACK) { | 212 } else if (type == APIAction::EVENT_CALLBACK) { |
243 iter->second->Notify(&Observer::OnExtensionActivity, | 213 iter->second->Notify(&Observer::OnExtensionActivity, |
244 extension, | 214 extension, |
245 ActivityLog::ACTIVITY_EVENT_DISPATCH, | 215 ActivityLog::ACTIVITY_EVENT_DISPATCH, |
246 MakeCallSignature(api_call, args)); | 216 MakeCallSignature(api_call, args)); |
247 } | 217 } |
248 } | 218 } |
249 if (log_activity_to_stdout_) | 219 if (log_activity_to_stdout_) |
250 LOG(INFO) << action->PrintForDebug(); | 220 LOG(INFO) << action->PrintForDebug(); |
251 } else { | 221 } else { |
252 LOG(ERROR) << "Unknown API call! " << api_call; | 222 LOG(ERROR) << "Unknown API call! " << api_call; |
253 } | 223 } |
254 } | 224 } |
255 | 225 |
256 // A wrapper around LogAPIActionInternal, but we know it's an API call. | 226 // A wrapper around LogAPIActionInternal, but we know it's an API call. |
257 void ActivityLog::LogAPIAction(const Extension* extension, | 227 void ActivityLog::LogAPIAction(const Extension* extension, |
258 const std::string& api_call, | 228 const std::string& api_call, |
259 ListValue* args, | 229 ListValue* args, |
260 const std::string& extra) { | 230 const std::string& extra) { |
261 if (!IsLogEnabled()) return; | 231 if (!IsLogEnabled() || !extension) |
262 if (!testing_mode_ && | 232 return; |
263 arg_whitelist_api_.find(api_call) == arg_whitelist_api_.end()) | 233 |
264 args->Clear(); | |
265 LogAPIActionInternal(extension, | 234 LogAPIActionInternal(extension, |
266 api_call, | 235 api_call, |
267 args, | 236 args, |
268 extra, | 237 extra, |
269 APIAction::CALL); | 238 APIAction::CALL); |
270 } | 239 } |
271 | 240 |
272 // A wrapper around LogAPIActionInternal, but we know it's actually an event | 241 // A wrapper around LogAPIActionInternal, but we know it's actually an event |
273 // being fired and triggering extension code. Having the two separate methods | 242 // being fired and triggering extension code. Having the two separate methods |
274 // (LogAPIAction vs LogEventAction) lets us hide how we actually choose to | 243 // (LogAPIAction vs LogEventAction) lets us hide how we actually choose to |
275 // handle them. Right now they're being handled almost the same. | 244 // handle them. Right now they're being handled almost the same. |
276 void ActivityLog::LogEventAction(const Extension* extension, | 245 void ActivityLog::LogEventAction(const Extension* extension, |
277 const std::string& api_call, | 246 const std::string& api_call, |
278 ListValue* args, | 247 ListValue* args, |
279 const std::string& extra) { | 248 const std::string& extra) { |
280 if (!IsLogEnabled()) return; | 249 if (!IsLogEnabled() || !extension) |
281 if (!testing_mode_ && | 250 return; |
282 arg_whitelist_api_.find(api_call) == arg_whitelist_api_.end()) | 251 |
283 args->Clear(); | |
284 LogAPIActionInternal(extension, | 252 LogAPIActionInternal(extension, |
285 api_call, | 253 api_call, |
286 args, | 254 args, |
287 extra, | 255 extra, |
288 APIAction::EVENT_CALLBACK); | 256 APIAction::EVENT_CALLBACK); |
289 } | 257 } |
290 | 258 |
291 void ActivityLog::LogBlockedAction(const Extension* extension, | 259 void ActivityLog::LogBlockedAction(const Extension* extension, |
292 const std::string& blocked_call, | 260 const std::string& blocked_call, |
293 ListValue* args, | 261 ListValue* args, |
294 BlockedAction::Reason reason, | 262 BlockedAction::Reason reason, |
295 const std::string& extra) { | 263 const std::string& extra) { |
296 if (!IsLogEnabled()) return; | 264 if (!IsLogEnabled() || !extension) |
297 if (!testing_mode_ && | 265 return; |
298 arg_whitelist_api_.find(blocked_call) == arg_whitelist_api_.end()) | 266 |
299 args->Clear(); | 267 if (policy_) { |
268 scoped_ptr<base::DictionaryValue> details(new DictionaryValue()); | |
269 std::string key; | |
270 policy_->GetKey(ActivityLogPolicy::PARAM_KEY_REASON, key); | |
271 details->SetInteger(key, static_cast<int>(reason)); | |
272 policy_->ProcessAction( | |
273 ActivityLogPolicy::ACTION_BLOCKED, | |
274 *extension, | |
275 blocked_call, | |
276 NULL, | |
277 args, | |
278 details.get()); | |
279 } | |
280 | |
281 // TODO(felt) Logging should be done more efficiently, so that it | |
282 // doesn't require construction of the action object. | |
300 scoped_refptr<BlockedAction> action = new BlockedAction(extension->id(), | 283 scoped_refptr<BlockedAction> action = new BlockedAction(extension->id(), |
301 base::Time::Now(), | 284 base::Time::Now(), |
302 blocked_call, | 285 blocked_call, |
303 MakeArgList(args), | 286 MakeArgList(args), |
304 reason, | 287 reason, |
305 extra); | 288 extra); |
306 ScheduleAndForget(&ActivityDatabase::RecordAction, action); | |
307 // Display the action. | 289 // Display the action. |
308 ObserverMap::const_iterator iter = observers_.find(extension); | 290 ObserverMap::const_iterator iter = observers_.find(extension); |
309 if (iter != observers_.end()) { | 291 if (iter != observers_.end()) { |
310 std::string blocked_str = MakeCallSignature(blocked_call, args); | 292 std::string blocked_str = MakeCallSignature(blocked_call, args); |
311 iter->second->Notify(&Observer::OnExtensionActivity, | 293 iter->second->Notify(&Observer::OnExtensionActivity, |
312 extension, | 294 extension, |
313 ActivityLog::ACTIVITY_EXTENSION_API_BLOCK, | 295 ActivityLog::ACTIVITY_EXTENSION_API_BLOCK, |
314 blocked_str); | 296 blocked_str); |
315 } | 297 } |
316 if (log_activity_to_stdout_) | 298 if (log_activity_to_stdout_) |
317 LOG(INFO) << action->PrintForDebug(); | 299 LOG(INFO) << action->PrintForDebug(); |
318 } | 300 } |
319 | 301 |
320 void ActivityLog::LogDOMActionInternal(const Extension* extension, | 302 void ActivityLog::LogDOMActionInternal(const Extension* extension, |
321 const GURL& url, | 303 const GURL& url, |
322 const string16& url_title, | 304 const string16& url_title, |
323 const std::string& api_call, | 305 const std::string& api_call, |
324 const ListValue* args, | 306 const ListValue* args, |
325 const std::string& extra, | 307 const std::string& extra, |
326 DOMAction::DOMActionType verb) { | 308 DOMAction::DOMActionType verb) { |
309 | |
felt
2013/05/24 18:43:38
Delete the extra vertical spaces at the beginning
dbabic
2013/05/28 21:11:49
Done.
| |
310 if (!extension) | |
311 return; | |
312 | |
313 if (policy_) { | |
314 scoped_ptr<base::DictionaryValue> details(new DictionaryValue()); | |
315 std::string key; | |
316 policy_->GetKey(ActivityLogPolicy::PARAM_KEY_DOM_ACTION, key); | |
317 details->SetInteger(key, static_cast<int>(verb)); | |
318 policy_->GetKey(ActivityLogPolicy::PARAM_KEY_URL_TITLE, key); | |
319 details->SetString(key, url_title); | |
320 policy_->ProcessAction( | |
321 ActivityLogPolicy::ACTION_DOM, | |
322 *extension, | |
323 api_call, | |
324 &url, | |
325 args, | |
326 details.get()); | |
327 } | |
328 | |
329 | |
330 // TODO(felt) Logging should be done more efficiently, so that it | |
331 // doesn't require construction of the action object. | |
327 scoped_refptr<DOMAction> action = new DOMAction( | 332 scoped_refptr<DOMAction> action = new DOMAction( |
328 extension->id(), | 333 extension->id(), |
329 base::Time::Now(), | 334 base::Time::Now(), |
330 verb, | 335 verb, |
331 url, | 336 url, |
332 url_title, | 337 url_title, |
333 api_call, | 338 api_call, |
334 MakeArgList(args), | 339 MakeArgList(args), |
335 extra); | 340 extra); |
336 ScheduleAndForget(&ActivityDatabase::RecordAction, action); | |
337 | 341 |
338 // Display the action. | 342 // Display the action. |
339 ObserverMap::const_iterator iter = observers_.find(extension); | 343 ObserverMap::const_iterator iter = observers_.find(extension); |
340 if (iter != observers_.end()) { | 344 if (iter != observers_.end()) { |
341 // TODO(felt): This is a kludge, planning to update this when new | 345 // TODO(felt): This is a kludge, planning to update this when new |
342 // UI is in place. | 346 // UI is in place. |
343 if (verb == DOMAction::INSERTED) { | 347 if (verb == DOMAction::INSERTED) { |
344 iter->second->Notify(&Observer::OnExtensionActivity, | 348 iter->second->Notify(&Observer::OnExtensionActivity, |
345 extension, | 349 extension, |
346 ActivityLog::ACTIVITY_CONTENT_SCRIPT, | 350 ActivityLog::ACTIVITY_CONTENT_SCRIPT, |
347 action->PrintForDebug()); | 351 action->PrintForDebug()); |
348 } else { | 352 } else { |
349 iter->second->Notify(&Observer::OnExtensionActivity, | 353 iter->second->Notify(&Observer::OnExtensionActivity, |
350 extension, | 354 extension, |
351 ActivityLog::ACTIVITY_CONTENT_SCRIPT, | 355 ActivityLog::ACTIVITY_CONTENT_SCRIPT, |
352 MakeCallSignature(api_call, args)); | 356 MakeCallSignature(api_call, args)); |
353 } | 357 } |
354 } | 358 } |
355 if (log_activity_to_stdout_) | 359 if (log_activity_to_stdout_) |
356 LOG(INFO) << action->PrintForDebug(); | 360 LOG(INFO) << action->PrintForDebug(); |
357 } | 361 } |
358 | 362 |
359 void ActivityLog::LogDOMAction(const Extension* extension, | 363 void ActivityLog::LogDOMAction(const Extension* extension, |
360 const GURL& url, | 364 const GURL& url, |
361 const string16& url_title, | 365 const string16& url_title, |
362 const std::string& api_call, | 366 const std::string& api_call, |
363 const ListValue* args, | 367 const ListValue* args, |
364 const std::string& extra) { | 368 const std::string& extra) { |
365 if (!IsLogEnabled()) return; | 369 if (!IsLogEnabled() || !extension) |
370 return; | |
371 | |
366 DOMAction::DOMActionType action = DOMAction::MODIFIED; | 372 DOMAction::DOMActionType action = DOMAction::MODIFIED; |
367 if (extra == "Getter") { | 373 if (extra == "Getter") { |
368 action = DOMAction::GETTER; | 374 action = DOMAction::GETTER; |
369 } else if (extra == "Setter") { | 375 } else if (extra == "Setter") { |
370 action = DOMAction::SETTER; | 376 action = DOMAction::SETTER; |
371 } else if (api_call == "XMLHttpRequest.open") { | 377 } else if (api_call == "XMLHttpRequest.open") { |
372 // Has to come before the Method check because XHR is also a Method. | 378 // Has to come before the Method check because XHR is also a Method. |
373 action = DOMAction::XHR; | 379 action = DOMAction::XHR; |
374 } else if (extra == "Method") { | 380 } else if (extra == "Method") { |
375 action = DOMAction::METHOD; | 381 action = DOMAction::METHOD; |
376 } | 382 } |
383 | |
377 LogDOMActionInternal(extension, | 384 LogDOMActionInternal(extension, |
378 url, | 385 url, |
379 url_title, | 386 url_title, |
380 api_call, | 387 api_call, |
381 args, | 388 args, |
382 extra, | 389 extra, |
383 action); | 390 action); |
384 } | 391 } |
385 | 392 |
386 void ActivityLog::LogWebRequestAction(const Extension* extension, | 393 void ActivityLog::LogWebRequestAction(const Extension* extension, |
387 const GURL& url, | 394 const GURL& url, |
388 const std::string& api_call, | 395 const std::string& api_call, |
389 scoped_ptr<DictionaryValue> details, | 396 scoped_ptr<DictionaryValue> details, |
390 const std::string& extra) { | 397 const std::string& extra) { |
391 string16 null_title; | 398 string16 null_title; |
392 if (!IsLogEnabled()) return; | 399 if (!IsLogEnabled() || !extension) |
400 return; | |
393 | 401 |
394 // Strip details of the web request modifications (for privacy reasons), | 402 std::string details_string; |
395 // unless testing is enabled. | 403 if (policy_) { |
396 if (!testing_mode_) { | 404 scoped_ptr<base::DictionaryValue> details(new DictionaryValue()); |
397 DictionaryValue::Iterator details_iterator(*details); | 405 std::string key; |
398 while (!details_iterator.IsAtEnd()) { | 406 policy_->GetKey(ActivityLogPolicy::PARAM_KEY_DETAILS_STRING, key); |
399 details->SetBoolean(details_iterator.key(), true); | 407 details->SetString(key, details_string); |
400 details_iterator.Advance(); | 408 policy_->ProcessAction( |
401 } | 409 ActivityLogPolicy::ACTION_WEB_REQUEST, |
410 *extension, | |
411 api_call, | |
412 &url, | |
413 NULL, | |
414 details.get()); | |
402 } | 415 } |
403 std::string details_string; | 416 |
404 JSONStringValueSerializer serializer(&details_string); | 417 JSONStringValueSerializer serializer(&details_string); |
405 serializer.SerializeAndOmitBinaryValues(*details); | 418 serializer.SerializeAndOmitBinaryValues(*details); |
406 | 419 |
420 // TODO(felt) Logging should be done more efficiently, so that it | |
421 // doesn't require construction of the action object. | |
407 scoped_refptr<DOMAction> action = new DOMAction( | 422 scoped_refptr<DOMAction> action = new DOMAction( |
408 extension->id(), | 423 extension->id(), |
409 base::Time::Now(), | 424 base::Time::Now(), |
410 DOMAction::WEBREQUEST, | 425 DOMAction::WEBREQUEST, |
411 url, | 426 url, |
412 null_title, | 427 null_title, |
413 api_call, | 428 api_call, |
414 details_string, | 429 details_string, |
415 extra); | 430 extra); |
416 ScheduleAndForget(&ActivityDatabase::RecordAction, action); | |
417 | 431 |
418 // Display the action. | 432 // Display the action. |
419 ObserverMap::const_iterator iter = observers_.find(extension); | 433 ObserverMap::const_iterator iter = observers_.find(extension); |
420 if (iter != observers_.end()) { | 434 if (iter != observers_.end()) { |
421 iter->second->Notify(&Observer::OnExtensionActivity, | 435 iter->second->Notify(&Observer::OnExtensionActivity, |
422 extension, | 436 extension, |
423 ActivityLog::ACTIVITY_CONTENT_SCRIPT, | 437 ActivityLog::ACTIVITY_CONTENT_SCRIPT, |
424 action->PrintForDebug()); | 438 action->PrintForDebug()); |
425 } | 439 } |
426 if (log_activity_to_stdout_) | 440 if (log_activity_to_stdout_) |
427 LOG(INFO) << action->PrintForDebug(); | 441 LOG(INFO) << action->PrintForDebug(); |
428 } | 442 } |
429 | 443 |
430 void ActivityLog::GetActions( | 444 void ActivityLog::GetActions( |
431 const std::string& extension_id, | 445 const std::string& extension_id, |
432 const int day, | 446 const int day, |
433 const base::Callback | 447 const base::Callback |
434 <void(scoped_ptr<std::vector<scoped_refptr<Action> > >)>& callback) { | 448 <void(scoped_ptr<std::vector<scoped_refptr<Action> > >)>& callback) { |
435 BrowserThread::PostTaskAndReplyWithResult( | 449 if (policy_) { |
436 dispatch_thread_, | 450 policy_->ReadData(extension_id, day, callback); |
437 FROM_HERE, | 451 } |
438 base::Bind(&ActivityDatabase::GetActions, | |
439 base::Unretained(db_), | |
440 extension_id, | |
441 day), | |
442 callback); | |
443 } | 452 } |
444 | 453 |
445 void ActivityLog::OnScriptsExecuted( | 454 void ActivityLog::OnScriptsExecuted( |
446 const content::WebContents* web_contents, | 455 const content::WebContents* web_contents, |
447 const ExecutingScriptsMap& extension_ids, | 456 const ExecutingScriptsMap& extension_ids, |
448 int32 on_page_id, | 457 int32 on_page_id, |
449 const GURL& on_url) { | 458 const GURL& on_url) { |
450 if (!IsLogEnabled()) return; | 459 if (!IsLogEnabled()) return; |
451 Profile* profile = | 460 Profile* profile = |
452 Profile::FromBrowserContext(web_contents->GetBrowserContext()); | 461 Profile::FromBrowserContext(web_contents->GetBrowserContext()); |
(...skipping 18 matching lines...) Expand all Loading... | |
471 ext_scripts_str += *it2; | 480 ext_scripts_str += *it2; |
472 ext_scripts_str += " "; | 481 ext_scripts_str += " "; |
473 } | 482 } |
474 scoped_ptr<ListValue> script_names(new ListValue()); | 483 scoped_ptr<ListValue> script_names(new ListValue()); |
475 script_names->Set(0, new StringValue(ext_scripts_str)); | 484 script_names->Set(0, new StringValue(ext_scripts_str)); |
476 LogDOMActionInternal(extension, | 485 LogDOMActionInternal(extension, |
477 on_url, | 486 on_url, |
478 web_contents->GetTitle(), | 487 web_contents->GetTitle(), |
479 std::string(), // no api call here | 488 std::string(), // no api call here |
480 script_names.get(), | 489 script_names.get(), |
481 std::string(), // no extras either | 490 std::string(), |
482 DOMAction::INSERTED); | 491 DOMAction::INSERTED); // no extras either |
483 } | 492 } |
484 } | 493 } |
485 } | 494 } |
486 | 495 |
487 void ActivityLog::KillActivityLogDatabase() { | |
488 ScheduleAndForget(&ActivityDatabase::KillDatabase); | |
489 } | |
490 | |
491 // static | 496 // static |
492 const char* ActivityLog::ActivityToString(Activity activity) { | 497 const char* ActivityLog::ActivityToString(Activity activity) { |
493 switch (activity) { | 498 switch (activity) { |
494 case ActivityLog::ACTIVITY_EXTENSION_API_CALL: | 499 case ActivityLog::ACTIVITY_EXTENSION_API_CALL: |
495 return "api_call"; | 500 return "api_call"; |
496 case ActivityLog::ACTIVITY_EXTENSION_API_BLOCK: | 501 case ActivityLog::ACTIVITY_EXTENSION_API_BLOCK: |
497 return "api_block"; | 502 return "api_block"; |
498 case ActivityLog::ACTIVITY_CONTENT_SCRIPT: | 503 case ActivityLog::ACTIVITY_CONTENT_SCRIPT: |
499 return "content_script"; | 504 return "content_script"; |
500 case ActivityLog::ACTIVITY_EVENT_DISPATCH: | 505 case ActivityLog::ACTIVITY_EVENT_DISPATCH: |
501 return "event_dispatch"; | 506 return "event_dispatch"; |
502 default: | 507 default: |
503 NOTREACHED(); | 508 NOTREACHED(); |
504 return ""; | 509 return ""; |
505 } | 510 } |
506 } | 511 } |
507 | 512 |
513 ActivityLogPolicy::PolicyType ActivityLog::policy_type_( | |
514 ActivityLogPolicy::POLICY_NOARGS); | |
515 | |
508 } // namespace extensions | 516 } // namespace extensions |
OLD | NEW |