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" |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
150 | 150 |
151 void ActivityLog::SetArgumentLoggingForTesting(bool log_arguments) { | 151 void ActivityLog::SetArgumentLoggingForTesting(bool log_arguments) { |
152 testing_mode_ = log_arguments; | 152 testing_mode_ = log_arguments; |
153 } | 153 } |
154 | 154 |
155 // static | 155 // static |
156 ActivityLog* ActivityLog::GetInstance(Profile* profile) { | 156 ActivityLog* ActivityLog::GetInstance(Profile* profile) { |
157 return ActivityLogFactory::GetForProfile(profile); | 157 return ActivityLogFactory::GetForProfile(profile); |
158 } | 158 } |
159 | 159 |
160 void ActivityLog::AddObserver(ActivityLog::Observer* observer) { | 160 void ActivityLog::AddObserver(const Extension* extension, |
| 161 ActivityLog::Observer* observer) { |
161 if (!IsLogEnabled()) return; | 162 if (!IsLogEnabled()) return; |
162 // TODO(felt) Re-implement Observer notification HERE for the API. | 163 if (observers_.count(extension) == 0) |
| 164 observers_[extension] = new ObserverListThreadSafe<Observer>; |
| 165 observers_[extension]->AddObserver(observer); |
163 } | 166 } |
164 | 167 |
165 void ActivityLog::RemoveObserver(ActivityLog::Observer* observer) { | 168 void ActivityLog::RemoveObserver(const Extension* extension, |
166 // TODO(felt) Re-implement Observer notification HERE for the API. | 169 ActivityLog::Observer* observer) { |
| 170 if (observers_.count(extension) == 1) |
| 171 observers_[extension]->RemoveObserver(observer); |
167 } | 172 } |
168 | 173 |
169 void ActivityLog::LogAPIActionInternal(const std::string& extension_id, | 174 void ActivityLog::LogAPIActionInternal(const Extension* extension, |
170 const std::string& api_call, | 175 const std::string& api_call, |
171 ListValue* args, | 176 ListValue* args, |
172 const std::string& extra, | 177 const std::string& extra, |
173 const APIAction::Type type) { | 178 const APIAction::Type type) { |
174 std::string verb, manager; | 179 std::string verb, manager; |
175 bool matches = RE2::FullMatch(api_call, "(.*?)\\.(.*)", &manager, &verb); | 180 bool matches = RE2::FullMatch(api_call, "(.*?)\\.(.*)", &manager, &verb); |
176 if (matches) { | 181 if (matches) { |
177 if (!args->empty() && manager == "tabs") { | 182 if (!args->empty() && manager == "tabs") { |
178 APIAction::LookupTabId(api_call, args, profile_); | 183 APIAction::LookupTabId(api_call, args, profile_); |
179 } | 184 } |
180 scoped_refptr<APIAction> action = new APIAction( | 185 scoped_refptr<APIAction> action = new APIAction( |
181 extension_id, | 186 extension->id(), |
182 base::Time::Now(), | 187 base::Time::Now(), |
183 type, | 188 type, |
184 api_call, | 189 api_call, |
185 MakeArgList(args), | 190 MakeArgList(args), |
186 extra); | 191 extra); |
187 ScheduleAndForget(&ActivityDatabase::RecordAction, action); | 192 ScheduleAndForget(&ActivityDatabase::RecordAction, action); |
188 // TODO(felt) Re-implement Observer notification HERE for the API. | 193 |
| 194 // Display the action. |
| 195 ObserverMap::const_iterator iter = observers_.find(extension); |
| 196 if (iter != observers_.end()) { |
| 197 if (type == APIAction::CALL) { |
| 198 iter->second->Notify(&Observer::OnExtensionActivity, |
| 199 extension, |
| 200 ActivityLog::ACTIVITY_EXTENSION_API_CALL, |
| 201 MakeCallSignature(api_call, args)); |
| 202 } else if (type == APIAction::EVENT_CALLBACK) { |
| 203 iter->second->Notify(&Observer::OnExtensionActivity, |
| 204 extension, |
| 205 ActivityLog::ACTIVITY_EVENT_DISPATCH, |
| 206 MakeCallSignature(api_call, args)); |
| 207 } |
| 208 } |
189 if (log_activity_to_stdout_) | 209 if (log_activity_to_stdout_) |
190 LOG(INFO) << action->PrintForDebug(); | 210 LOG(INFO) << action->PrintForDebug(); |
191 } else { | 211 } else { |
192 LOG(ERROR) << "Unknown API call! " << api_call; | 212 LOG(ERROR) << "Unknown API call! " << api_call; |
193 } | 213 } |
194 } | 214 } |
195 | 215 |
196 // A wrapper around LogAPIActionInternal, but we know it's an API call. | 216 // A wrapper around LogAPIActionInternal, but we know it's an API call. |
197 void ActivityLog::LogAPIAction(const std::string& extension_id, | 217 void ActivityLog::LogAPIAction(const Extension* extension, |
198 const std::string& api_call, | 218 const std::string& api_call, |
199 ListValue* args, | 219 ListValue* args, |
200 const std::string& extra) { | 220 const std::string& extra) { |
201 if (!IsLogEnabled()) return; | 221 if (!IsLogEnabled()) return; |
202 if (!testing_mode_ && | 222 if (!testing_mode_ && |
203 arg_whitelist_api_.find(api_call) == arg_whitelist_api_.end()) | 223 arg_whitelist_api_.find(api_call) == arg_whitelist_api_.end()) |
204 args->Clear(); | 224 args->Clear(); |
205 LogAPIActionInternal(extension_id, | 225 LogAPIActionInternal(extension, |
206 api_call, | 226 api_call, |
207 args, | 227 args, |
208 extra, | 228 extra, |
209 APIAction::CALL); | 229 APIAction::CALL); |
210 } | 230 } |
211 | 231 |
212 // A wrapper around LogAPIActionInternal, but we know it's actually an event | 232 // A wrapper around LogAPIActionInternal, but we know it's actually an event |
213 // being fired and triggering extension code. Having the two separate methods | 233 // being fired and triggering extension code. Having the two separate methods |
214 // (LogAPIAction vs LogEventAction) lets us hide how we actually choose to | 234 // (LogAPIAction vs LogEventAction) lets us hide how we actually choose to |
215 // handle them. Right now they're being handled almost the same. | 235 // handle them. Right now they're being handled almost the same. |
216 void ActivityLog::LogEventAction(const std::string& extension_id, | 236 void ActivityLog::LogEventAction(const Extension* extension, |
217 const std::string& api_call, | 237 const std::string& api_call, |
218 ListValue* args, | 238 ListValue* args, |
219 const std::string& extra) { | 239 const std::string& extra) { |
220 if (!IsLogEnabled()) return; | 240 if (!IsLogEnabled()) return; |
221 if (!testing_mode_ && | 241 if (!testing_mode_ && |
222 arg_whitelist_api_.find(api_call) == arg_whitelist_api_.end()) | 242 arg_whitelist_api_.find(api_call) == arg_whitelist_api_.end()) |
223 args->Clear(); | 243 args->Clear(); |
224 LogAPIActionInternal(extension_id, | 244 LogAPIActionInternal(extension, |
225 api_call, | 245 api_call, |
226 args, | 246 args, |
227 extra, | 247 extra, |
228 APIAction::EVENT_CALLBACK); | 248 APIAction::EVENT_CALLBACK); |
229 } | 249 } |
230 | 250 |
231 void ActivityLog::LogBlockedAction(const std::string& extension_id, | 251 void ActivityLog::LogBlockedAction(const Extension* extension, |
232 const std::string& blocked_call, | 252 const std::string& blocked_call, |
233 ListValue* args, | 253 ListValue* args, |
234 BlockedAction::Reason reason, | 254 BlockedAction::Reason reason, |
235 const std::string& extra) { | 255 const std::string& extra) { |
236 if (!IsLogEnabled()) return; | 256 if (!IsLogEnabled()) return; |
237 if (!testing_mode_ && | 257 if (!testing_mode_ && |
238 arg_whitelist_api_.find(blocked_call) == arg_whitelist_api_.end()) | 258 arg_whitelist_api_.find(blocked_call) == arg_whitelist_api_.end()) |
239 args->Clear(); | 259 args->Clear(); |
240 scoped_refptr<BlockedAction> action = new BlockedAction(extension_id, | 260 scoped_refptr<BlockedAction> action = new BlockedAction(extension->id(), |
241 base::Time::Now(), | 261 base::Time::Now(), |
242 blocked_call, | 262 blocked_call, |
243 MakeArgList(args), | 263 MakeArgList(args), |
244 reason, | 264 reason, |
245 extra); | 265 extra); |
246 ScheduleAndForget(&ActivityDatabase::RecordAction, action); | 266 ScheduleAndForget(&ActivityDatabase::RecordAction, action); |
247 // TODO(felt) Re-implement Observer notification HERE for the API. | 267 // Display the action. |
| 268 ObserverMap::const_iterator iter = observers_.find(extension); |
| 269 if (iter != observers_.end()) { |
| 270 std::string blocked_str = MakeCallSignature(blocked_call, args); |
| 271 iter->second->Notify(&Observer::OnExtensionActivity, |
| 272 extension, |
| 273 ActivityLog::ACTIVITY_EXTENSION_API_BLOCK, |
| 274 blocked_str); |
| 275 } |
248 if (log_activity_to_stdout_) | 276 if (log_activity_to_stdout_) |
249 LOG(INFO) << action->PrintForDebug(); | 277 LOG(INFO) << action->PrintForDebug(); |
250 } | 278 } |
251 | 279 |
252 void ActivityLog::LogDOMAction(const std::string& extension_id, | 280 void ActivityLog::LogDOMAction(const Extension* extension, |
253 const GURL& url, | 281 const GURL& url, |
254 const string16& url_title, | 282 const string16& url_title, |
255 const std::string& api_call, | 283 const std::string& api_call, |
256 const ListValue* args, | 284 const ListValue* args, |
257 DomActionType::Type call_type, | 285 DomActionType::Type call_type, |
258 const std::string& extra) { | 286 const std::string& extra) { |
259 if (!IsLogEnabled()) return; | 287 if (!IsLogEnabled()) return; |
260 if (call_type == DomActionType::METHOD && api_call == "XMLHttpRequest.open") | 288 if (call_type == DomActionType::METHOD && api_call == "XMLHttpRequest.open") |
261 call_type = DomActionType::XHR; | 289 call_type = DomActionType::XHR; |
262 scoped_refptr<DOMAction> action = new DOMAction( | 290 scoped_refptr<DOMAction> action = new DOMAction( |
263 extension_id, | 291 extension->id(), |
264 base::Time::Now(), | 292 base::Time::Now(), |
265 call_type, | 293 call_type, |
266 url, | 294 url, |
267 url_title, | 295 url_title, |
268 api_call, | 296 api_call, |
269 MakeArgList(args), | 297 MakeArgList(args), |
270 extra); | 298 extra); |
271 ScheduleAndForget(&ActivityDatabase::RecordAction, action); | 299 ScheduleAndForget(&ActivityDatabase::RecordAction, action); |
272 // TODO(felt) Re-implement Observer notification HERE for the API. | 300 |
| 301 // Display the action. |
| 302 ObserverMap::const_iterator iter = observers_.find(extension); |
| 303 if (iter != observers_.end()) { |
| 304 // TODO(felt): This is a kludge, planning to update this when new |
| 305 // UI is in place. |
| 306 if (call_type == DomActionType::INSERTED) { |
| 307 iter->second->Notify(&Observer::OnExtensionActivity, |
| 308 extension, |
| 309 ActivityLog::ACTIVITY_CONTENT_SCRIPT, |
| 310 action->PrintForDebug()); |
| 311 } else { |
| 312 iter->second->Notify(&Observer::OnExtensionActivity, |
| 313 extension, |
| 314 ActivityLog::ACTIVITY_CONTENT_SCRIPT, |
| 315 MakeCallSignature(api_call, args)); |
| 316 } |
| 317 } |
273 if (log_activity_to_stdout_) | 318 if (log_activity_to_stdout_) |
274 LOG(INFO) << action->PrintForDebug(); | 319 LOG(INFO) << action->PrintForDebug(); |
275 } | 320 } |
276 | 321 |
277 void ActivityLog::LogWebRequestAction(const std::string& extension_id, | 322 void ActivityLog::LogWebRequestAction(const Extension* extension, |
278 const GURL& url, | 323 const GURL& url, |
279 const std::string& api_call, | 324 const std::string& api_call, |
280 scoped_ptr<DictionaryValue> details, | 325 scoped_ptr<DictionaryValue> details, |
281 const std::string& extra) { | 326 const std::string& extra) { |
282 string16 null_title; | 327 string16 null_title; |
283 if (!IsLogEnabled()) return; | 328 if (!IsLogEnabled()) return; |
284 | 329 |
285 // Strip details of the web request modifications (for privacy reasons), | 330 // Strip details of the web request modifications (for privacy reasons), |
286 // unless testing is enabled. | 331 // unless testing is enabled. |
287 if (!testing_mode_) { | 332 if (!testing_mode_) { |
288 DictionaryValue::Iterator details_iterator(*details); | 333 DictionaryValue::Iterator details_iterator(*details); |
289 while (!details_iterator.IsAtEnd()) { | 334 while (!details_iterator.IsAtEnd()) { |
290 details->SetBoolean(details_iterator.key(), true); | 335 details->SetBoolean(details_iterator.key(), true); |
291 details_iterator.Advance(); | 336 details_iterator.Advance(); |
292 } | 337 } |
293 } | 338 } |
294 std::string details_string; | 339 std::string details_string; |
295 JSONStringValueSerializer serializer(&details_string); | 340 JSONStringValueSerializer serializer(&details_string); |
296 serializer.SerializeAndOmitBinaryValues(*details); | 341 serializer.SerializeAndOmitBinaryValues(*details); |
297 | 342 |
298 scoped_refptr<DOMAction> action = new DOMAction( | 343 scoped_refptr<DOMAction> action = new DOMAction( |
299 extension_id, | 344 extension->id(), |
300 base::Time::Now(), | 345 base::Time::Now(), |
301 DomActionType::WEBREQUEST, | 346 DomActionType::WEBREQUEST, |
302 url, | 347 url, |
303 null_title, | 348 null_title, |
304 api_call, | 349 api_call, |
305 details_string, | 350 details_string, |
306 extra); | 351 extra); |
307 ScheduleAndForget(&ActivityDatabase::RecordAction, action); | 352 ScheduleAndForget(&ActivityDatabase::RecordAction, action); |
308 // TODO(felt) Re-implement Observer notification HERE for the API. | 353 |
| 354 // Display the action. |
| 355 ObserverMap::const_iterator iter = observers_.find(extension); |
| 356 if (iter != observers_.end()) { |
| 357 iter->second->Notify(&Observer::OnExtensionActivity, |
| 358 extension, |
| 359 ActivityLog::ACTIVITY_CONTENT_SCRIPT, |
| 360 action->PrintForDebug()); |
| 361 } |
309 if (log_activity_to_stdout_) | 362 if (log_activity_to_stdout_) |
310 LOG(INFO) << action->PrintForDebug(); | 363 LOG(INFO) << action->PrintForDebug(); |
311 } | 364 } |
312 | 365 |
313 void ActivityLog::GetActions( | 366 void ActivityLog::GetActions( |
314 const std::string& extension_id, | 367 const std::string& extension_id, |
315 const int day, | 368 const int day, |
316 const base::Callback | 369 const base::Callback |
317 <void(scoped_ptr<std::vector<scoped_refptr<Action> > >)>& callback) { | 370 <void(scoped_ptr<std::vector<scoped_refptr<Action> > >)>& callback) { |
318 BrowserThread::PostTaskAndReplyWithResult( | 371 BrowserThread::PostTaskAndReplyWithResult( |
(...skipping 30 matching lines...) Expand all Loading... |
349 if (!it->second.empty()) { | 402 if (!it->second.empty()) { |
350 std::string ext_scripts_str; | 403 std::string ext_scripts_str; |
351 for (std::set<std::string>::const_iterator it2 = it->second.begin(); | 404 for (std::set<std::string>::const_iterator it2 = it->second.begin(); |
352 it2 != it->second.end(); | 405 it2 != it->second.end(); |
353 ++it2) { | 406 ++it2) { |
354 ext_scripts_str += *it2; | 407 ext_scripts_str += *it2; |
355 ext_scripts_str += " "; | 408 ext_scripts_str += " "; |
356 } | 409 } |
357 scoped_ptr<ListValue> script_names(new ListValue()); | 410 scoped_ptr<ListValue> script_names(new ListValue()); |
358 script_names->Set(0, new StringValue(ext_scripts_str)); | 411 script_names->Set(0, new StringValue(ext_scripts_str)); |
359 LogDOMAction(extension->id(), | 412 LogDOMAction(extension, |
360 on_url, | 413 on_url, |
361 web_contents->GetTitle(), | 414 web_contents->GetTitle(), |
362 std::string(), // no api call here | 415 std::string(), // no api call here |
363 script_names.get(), | 416 script_names.get(), |
364 DomActionType::INSERTED, | 417 DomActionType::INSERTED, |
365 std::string()); // no extras either | 418 std::string()); // no extras either |
366 } | 419 } |
367 } | 420 } |
368 } | 421 } |
369 | 422 |
370 void ActivityLog::DatabaseErrorCallback(int error, sql::Statement* stmt) { | 423 void ActivityLog::DatabaseErrorCallback(int error, sql::Statement* stmt) { |
371 if (sql::IsErrorCatastrophic(error)) | 424 if (sql::IsErrorCatastrophic(error)) |
372 ScheduleAndForget(&ActivityDatabase::KillDatabase); | 425 ScheduleAndForget(&ActivityDatabase::KillDatabase); |
373 } | 426 } |
374 | 427 |
| 428 // static |
| 429 const char* ActivityLog::ActivityToString(Activity activity) { |
| 430 switch (activity) { |
| 431 case ActivityLog::ACTIVITY_EXTENSION_API_CALL: |
| 432 return "api_call"; |
| 433 case ActivityLog::ACTIVITY_EXTENSION_API_BLOCK: |
| 434 return "api_block"; |
| 435 case ActivityLog::ACTIVITY_CONTENT_SCRIPT: |
| 436 return "content_script"; |
| 437 case ActivityLog::ACTIVITY_EVENT_DISPATCH: |
| 438 return "event_dispatch"; |
| 439 default: |
| 440 NOTREACHED(); |
| 441 return ""; |
| 442 } |
| 443 } |
| 444 |
375 } // namespace extensions | 445 } // namespace extensions |
OLD | NEW |