| 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 "chrome/browser/extensions/activity_log/activity_log.h" | 5 #include "chrome/browser/extensions/activity_log/activity_log.h" |
| 6 | 6 |
| 7 #include <set> | 7 #include <set> |
| 8 #include <vector> | 8 #include <vector> |
| 9 | 9 |
| 10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
| 11 #include "base/json/json_string_value_serializer.h" | 11 #include "base/json/json_string_value_serializer.h" |
| 12 #include "base/logging.h" | 12 #include "base/logging.h" |
| 13 #include "base/strings/string_util.h" | 13 #include "base/strings/string_util.h" |
| 14 #include "base/strings/utf_string_conversions.h" | 14 #include "base/strings/utf_string_conversions.h" |
| 15 #include "base/threading/thread_checker.h" | 15 #include "base/threading/thread_checker.h" |
| 16 #include "chrome/browser/extensions/activity_log/activity_action_constants.h" | 16 #include "chrome/browser/extensions/activity_log/activity_action_constants.h" |
| 17 #include "chrome/browser/extensions/activity_log/counting_policy.h" | 17 #include "chrome/browser/extensions/activity_log/counting_policy.h" |
| 18 #include "chrome/browser/extensions/activity_log/fullstream_ui_policy.h" | 18 #include "chrome/browser/extensions/activity_log/fullstream_ui_policy.h" |
| 19 #include "chrome/browser/extensions/api/activity_log_private/activity_log_privat
e_api.h" | 19 #include "chrome/browser/extensions/api/activity_log_private/activity_log_privat
e_api.h" |
| 20 #include "chrome/browser/extensions/extension_service.h" | 20 #include "chrome/browser/extensions/extension_service.h" |
| 21 #include "chrome/browser/extensions/extension_system.h" | 21 #include "chrome/browser/extensions/extension_system.h" |
| 22 #include "chrome/browser/extensions/extension_system_factory.h" | 22 #include "chrome/browser/extensions/extension_system_factory.h" |
| 23 #include "chrome/browser/extensions/extension_tab_util.h" | 23 #include "chrome/browser/extensions/extension_tab_util.h" |
| 24 #include "chrome/browser/extensions/install_tracker_factory.h" | 24 #include "chrome/browser/extensions/install_tracker_factory.h" |
| 25 #include "chrome/browser/prefs/pref_service_syncable.h" |
| 25 #include "chrome/browser/prerender/prerender_manager.h" | 26 #include "chrome/browser/prerender/prerender_manager.h" |
| 26 #include "chrome/browser/prerender/prerender_manager_factory.h" | 27 #include "chrome/browser/prerender/prerender_manager_factory.h" |
| 27 #include "chrome/browser/profiles/incognito_helpers.h" | 28 #include "chrome/browser/profiles/incognito_helpers.h" |
| 28 #include "chrome/browser/ui/browser.h" | 29 #include "chrome/browser/ui/browser.h" |
| 29 #include "chrome/common/chrome_constants.h" | 30 #include "chrome/common/chrome_constants.h" |
| 30 #include "chrome/common/chrome_switches.h" | 31 #include "chrome/common/chrome_switches.h" |
| 31 #include "chrome/common/extensions/extension.h" | 32 #include "chrome/common/extensions/extension.h" |
| 33 #include "chrome/common/pref_names.h" |
| 32 #include "components/browser_context_keyed_service/browser_context_dependency_ma
nager.h" | 34 #include "components/browser_context_keyed_service/browser_context_dependency_ma
nager.h" |
| 33 #include "content/public/browser/web_contents.h" | 35 #include "content/public/browser/web_contents.h" |
| 34 #include "third_party/re2/re2/re2.h" | 36 #include "third_party/re2/re2/re2.h" |
| 35 #include "url/gurl.h" | 37 #include "url/gurl.h" |
| 36 | 38 |
| 37 namespace constants = activity_log_constants; | 39 namespace constants = activity_log_constants; |
| 38 | 40 |
| 39 namespace { | 41 namespace { |
| 40 | 42 |
| 41 // Concatenate arguments. | 43 // Concatenate arguments. |
| 42 std::string MakeArgList(const base::ListValue* args) { | 44 std::string MakeArgList(const base::ListValue* args) { |
| 43 std::string call_signature; | 45 std::string call_signature; |
| 44 base::ListValue::const_iterator it = args->begin(); | 46 base::ListValue::const_iterator it = args->begin(); |
| 45 for (; it != args->end(); ++it) { | 47 for (; it != args->end(); ++it) { |
| 46 std::string arg; | 48 std::string arg; |
| 47 JSONStringValueSerializer serializer(&arg); | 49 JSONStringValueSerializer serializer(&arg); |
| 48 if (serializer.SerializeAndOmitBinaryValues(**it)) { | 50 if (serializer.SerializeAndOmitBinaryValues(**it)) { |
| 49 if (it != args->begin()) | 51 if (it != args->begin()) |
| 50 call_signature += ", "; | 52 call_signature += ", "; |
| 51 call_signature += arg; | 53 call_signature += arg; |
| 52 } | 54 } |
| 53 } | 55 } |
| 54 return call_signature; | 56 return call_signature; |
| 55 } | 57 } |
| 56 | 58 |
| 57 // This is a hack for AL callers who don't have access to a profile object | |
| 58 // when deciding whether or not to do the work required for logging. The state | |
| 59 // is accessed through the static ActivityLog::IsLogEnabledOnAnyProfile() | |
| 60 // method. It returns true if --enable-extension-activity-logging is set on the | |
| 61 // command line OR *ANY* profile has the activity log whitelisted extension | |
| 62 // installed. | |
| 63 class LogIsEnabled { | |
| 64 public: | |
| 65 LogIsEnabled() : any_profile_enabled_(false) { | |
| 66 ComputeIsFlagEnabled(); | |
| 67 } | |
| 68 | |
| 69 void ComputeIsFlagEnabled() { | |
| 70 base::AutoLock auto_lock(lock_); | |
| 71 cmd_line_enabled_ = CommandLine::ForCurrentProcess()-> | |
| 72 HasSwitch(switches::kEnableExtensionActivityLogging); | |
| 73 } | |
| 74 | |
| 75 static LogIsEnabled* GetInstance() { | |
| 76 return Singleton<LogIsEnabled>::get(); | |
| 77 } | |
| 78 | |
| 79 bool IsEnabled() { | |
| 80 base::AutoLock auto_lock(lock_); | |
| 81 return cmd_line_enabled_ || any_profile_enabled_; | |
| 82 } | |
| 83 | |
| 84 void SetProfileEnabled(bool any_profile_enabled) { | |
| 85 base::AutoLock auto_lock(lock_); | |
| 86 any_profile_enabled_ = any_profile_enabled; | |
| 87 } | |
| 88 | |
| 89 private: | |
| 90 base::Lock lock_; | |
| 91 bool any_profile_enabled_; | |
| 92 bool cmd_line_enabled_; | |
| 93 }; | |
| 94 | |
| 95 // Gets the URL for a given tab ID. Helper method for LookupTabId. Returns | 59 // Gets the URL for a given tab ID. Helper method for LookupTabId. Returns |
| 96 // true if able to perform the lookup. The URL is stored to *url, and | 60 // true if able to perform the lookup. The URL is stored to *url, and |
| 97 // *is_incognito is set to indicate whether the URL is for an incognito tab. | 61 // *is_incognito is set to indicate whether the URL is for an incognito tab. |
| 98 bool GetUrlForTabId(int tab_id, | 62 bool GetUrlForTabId(int tab_id, |
| 99 Profile* profile, | 63 Profile* profile, |
| 100 GURL* url, | 64 GURL* url, |
| 101 bool* is_incognito) { | 65 bool* is_incognito) { |
| 102 content::WebContents* contents = NULL; | 66 content::WebContents* contents = NULL; |
| 103 Browser* browser = NULL; | 67 Browser* browser = NULL; |
| 104 bool found = ExtensionTabUtil::GetTabById(tab_id, | 68 bool found = ExtensionTabUtil::GetTabById(tab_id, |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 176 } | 140 } |
| 177 } | 141 } |
| 178 } | 142 } |
| 179 } | 143 } |
| 180 } | 144 } |
| 181 | 145 |
| 182 } // namespace | 146 } // namespace |
| 183 | 147 |
| 184 namespace extensions { | 148 namespace extensions { |
| 185 | 149 |
| 186 // static | |
| 187 bool ActivityLog::IsLogEnabledOnAnyProfile() { | |
| 188 return LogIsEnabled::GetInstance()->IsEnabled(); | |
| 189 } | |
| 190 | |
| 191 // static | |
| 192 void ActivityLog::RecomputeLoggingIsEnabled(bool profile_enabled) { | |
| 193 LogIsEnabled::GetInstance()->ComputeIsFlagEnabled(); | |
| 194 LogIsEnabled::GetInstance()->SetProfileEnabled(profile_enabled); | |
| 195 } | |
| 196 | |
| 197 // ActivityLogFactory | 150 // ActivityLogFactory |
| 198 | 151 |
| 199 ActivityLogFactory* ActivityLogFactory::GetInstance() { | 152 ActivityLogFactory* ActivityLogFactory::GetInstance() { |
| 200 return Singleton<ActivityLogFactory>::get(); | 153 return Singleton<ActivityLogFactory>::get(); |
| 201 } | 154 } |
| 202 | 155 |
| 203 BrowserContextKeyedService* ActivityLogFactory::BuildServiceInstanceFor( | 156 BrowserContextKeyedService* ActivityLogFactory::BuildServiceInstanceFor( |
| 204 content::BrowserContext* profile) const { | 157 content::BrowserContext* profile) const { |
| 205 return new ActivityLog(static_cast<Profile*>(profile)); | 158 return new ActivityLog(static_cast<Profile*>(profile)); |
| 206 } | 159 } |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 250 policy_type_ = policy_type; | 203 policy_type_ = policy_type; |
| 251 } | 204 } |
| 252 } | 205 } |
| 253 | 206 |
| 254 // Use GetInstance instead of directly creating an ActivityLog. | 207 // Use GetInstance instead of directly creating an ActivityLog. |
| 255 ActivityLog::ActivityLog(Profile* profile) | 208 ActivityLog::ActivityLog(Profile* profile) |
| 256 : policy_(NULL), | 209 : policy_(NULL), |
| 257 policy_type_(ActivityLogPolicy::POLICY_INVALID), | 210 policy_type_(ActivityLogPolicy::POLICY_INVALID), |
| 258 profile_(profile), | 211 profile_(profile), |
| 259 enabled_(false), | 212 enabled_(false), |
| 260 initialized_(false), | |
| 261 policy_chosen_(false), | 213 policy_chosen_(false), |
| 262 testing_mode_(false), | 214 testing_mode_(false), |
| 263 has_threads_(true), | 215 has_threads_(true), |
| 264 tracker_(NULL) { | 216 tracker_(NULL), |
| 217 watchdog_extension_active_(false) { |
| 265 // This controls whether logging statements are printed, which policy is set, | 218 // This controls whether logging statements are printed, which policy is set, |
| 266 // etc. | 219 // etc. |
| 267 testing_mode_ = CommandLine::ForCurrentProcess()->HasSwitch( | 220 testing_mode_ = CommandLine::ForCurrentProcess()->HasSwitch( |
| 268 switches::kEnableExtensionActivityLogTesting); | 221 switches::kEnableExtensionActivityLogTesting); |
| 269 | 222 |
| 223 // Check if the watchdog extension is previously installed and active. |
| 224 watchdog_extension_active_ = |
| 225 profile_->GetPrefs()->GetBoolean(prefs::kWatchdogExtensionActive); |
| 226 |
| 227 observers_ = new ObserverListThreadSafe<Observer>; |
| 228 |
| 270 // Check that the right threads exist. If not, we shouldn't try to do things | 229 // Check that the right threads exist. If not, we shouldn't try to do things |
| 271 // that require them. | 230 // that require them. |
| 272 if (!BrowserThread::IsMessageLoopValid(BrowserThread::DB) || | 231 if (!BrowserThread::IsMessageLoopValid(BrowserThread::DB) || |
| 273 !BrowserThread::IsMessageLoopValid(BrowserThread::FILE) || | 232 !BrowserThread::IsMessageLoopValid(BrowserThread::FILE) || |
| 274 !BrowserThread::IsMessageLoopValid(BrowserThread::IO)) { | 233 !BrowserThread::IsMessageLoopValid(BrowserThread::IO)) { |
| 275 LOG(ERROR) << "Missing threads, disabling Activity Logging!"; | 234 LOG(ERROR) << "Missing threads, disabling Activity Logging!"; |
| 276 has_threads_ = false; | 235 has_threads_ = false; |
| 277 } else { | |
| 278 enabled_ = IsLogEnabledOnAnyProfile(); | |
| 279 ExtensionSystem::Get(profile_)->ready().Post( | |
| 280 FROM_HERE, base::Bind(&ActivityLog::Init, base::Unretained(this))); | |
| 281 } | 236 } |
| 282 | 237 |
| 283 observers_ = new ObserverListThreadSafe<Observer>; | 238 enabled_ = has_threads_ |
| 239 && (CommandLine::ForCurrentProcess()-> |
| 240 HasSwitch(switches::kEnableExtensionActivityLogging) |
| 241 || watchdog_extension_active_); |
| 242 |
| 243 if (enabled_) enabled_on_any_profile_ = true; |
| 244 |
| 245 ExtensionSystem::Get(profile_)->ready().Post( |
| 246 FROM_HERE, |
| 247 base::Bind(&ActivityLog::InitInstallTracker, base::Unretained(this))); |
| 248 ChooseDefaultPolicy(); |
| 284 } | 249 } |
| 285 | 250 |
| 286 void ActivityLog::Init() { | 251 void ActivityLog::InitInstallTracker() { |
| 287 DCHECK(has_threads_); | |
| 288 DCHECK(!initialized_); | |
| 289 const Extension* whitelisted_extension = ExtensionSystem::Get(profile_)-> | |
| 290 extension_service()->GetExtensionById(kActivityLogExtensionId, false); | |
| 291 if (whitelisted_extension) { | |
| 292 enabled_ = true; | |
| 293 LogIsEnabled::GetInstance()->SetProfileEnabled(true); | |
| 294 } | |
| 295 tracker_ = InstallTrackerFactory::GetForProfile(profile_); | 252 tracker_ = InstallTrackerFactory::GetForProfile(profile_); |
| 296 tracker_->AddObserver(this); | 253 tracker_->AddObserver(this); |
| 297 ChooseDefaultPolicy(); | |
| 298 initialized_ = true; | |
| 299 } | 254 } |
| 300 | 255 |
| 301 void ActivityLog::ChooseDefaultPolicy() { | 256 void ActivityLog::ChooseDefaultPolicy() { |
| 302 if (policy_chosen_ || !enabled_) return; | 257 if (policy_chosen_ || !enabled_) return; |
| 303 if (testing_mode_) | 258 if (testing_mode_) |
| 304 SetDefaultPolicy(ActivityLogPolicy::POLICY_FULLSTREAM); | 259 SetDefaultPolicy(ActivityLogPolicy::POLICY_FULLSTREAM); |
| 305 else | 260 else |
| 306 SetDefaultPolicy(ActivityLogPolicy::POLICY_COUNTS); | 261 SetDefaultPolicy(ActivityLogPolicy::POLICY_COUNTS); |
| 307 } | 262 } |
| 308 | 263 |
| 309 void ActivityLog::Shutdown() { | 264 void ActivityLog::Shutdown() { |
| 310 if (tracker_) tracker_->RemoveObserver(this); | 265 if (tracker_) tracker_->RemoveObserver(this); |
| 311 } | 266 } |
| 312 | 267 |
| 313 ActivityLog::~ActivityLog() { | 268 ActivityLog::~ActivityLog() { |
| 314 if (policy_) | 269 if (policy_) |
| 315 policy_->Close(); | 270 policy_->Close(); |
| 316 } | 271 } |
| 317 | 272 |
| 273 // static |
| 274 bool ActivityLog::enabled_on_any_profile_ = false; |
| 275 |
| 276 // static |
| 277 bool ActivityLog::IsLogEnabledOnAnyProfile() { |
| 278 return enabled_on_any_profile_; |
| 279 } |
| 280 |
| 318 bool ActivityLog::IsLogEnabled() { | 281 bool ActivityLog::IsLogEnabled() { |
| 319 if (!has_threads_ || !initialized_) return false; | 282 // Make sure we are not enabled when there are no threads. |
| 283 DCHECK(has_threads_ || !enabled_); |
| 320 return enabled_; | 284 return enabled_; |
| 321 } | 285 } |
| 322 | 286 |
| 323 void ActivityLog::OnExtensionLoaded(const Extension* extension) { | 287 void ActivityLog::OnExtensionLoaded(const Extension* extension) { |
| 324 if (extension->id() != kActivityLogExtensionId) return; | 288 if (extension->id() != kActivityLogExtensionId) return; |
| 325 enabled_ = true; | 289 if (has_threads_) { |
| 326 LogIsEnabled::GetInstance()->SetProfileEnabled(true); | 290 enabled_ = true; |
| 291 enabled_on_any_profile_ = true; |
| 292 } |
| 293 if (!watchdog_extension_active_) { |
| 294 watchdog_extension_active_ = true; |
| 295 profile_->GetPrefs()->SetBoolean(prefs::kWatchdogExtensionActive, true); |
| 296 } |
| 327 ChooseDefaultPolicy(); | 297 ChooseDefaultPolicy(); |
| 328 } | 298 } |
| 329 | 299 |
| 330 void ActivityLog::OnExtensionUnloaded(const Extension* extension) { | 300 void ActivityLog::OnExtensionUnloaded(const Extension* extension) { |
| 331 if (extension->id() != kActivityLogExtensionId) return; | 301 if (extension->id() != kActivityLogExtensionId) return; |
| 302 // Make sure we are not enabled when there are no threads. |
| 303 DCHECK(has_threads_ || !enabled_); |
| 332 if (!CommandLine::ForCurrentProcess()->HasSwitch( | 304 if (!CommandLine::ForCurrentProcess()->HasSwitch( |
| 333 switches::kEnableExtensionActivityLogging)) | 305 switches::kEnableExtensionActivityLogging)) |
| 334 enabled_ = false; | 306 enabled_ = false; |
| 307 if (watchdog_extension_active_) { |
| 308 watchdog_extension_active_ = false; |
| 309 profile_->GetPrefs()->SetBoolean(prefs::kWatchdogExtensionActive, |
| 310 false); |
| 311 } |
| 335 } | 312 } |
| 336 | 313 |
| 337 // static | 314 // static |
| 338 ActivityLog* ActivityLog::GetInstance(Profile* profile) { | 315 ActivityLog* ActivityLog::GetInstance(Profile* profile) { |
| 339 return ActivityLogFactory::GetForProfile(profile); | 316 return ActivityLogFactory::GetForProfile(profile); |
| 340 } | 317 } |
| 341 | 318 |
| 342 void ActivityLog::AddObserver(ActivityLog::Observer* observer) { | 319 void ActivityLog::AddObserver(ActivityLog::Observer* observer) { |
| 343 observers_->AddObserver(observer); | 320 observers_->AddObserver(observer); |
| 344 } | 321 } |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 420 for (std::set<std::string>::const_iterator it2 = it->second.begin(); | 397 for (std::set<std::string>::const_iterator it2 = it->second.begin(); |
| 421 it2 != it->second.end(); | 398 it2 != it->second.end(); |
| 422 ++it2) { | 399 ++it2) { |
| 423 action->mutable_args()->AppendString(*it2); | 400 action->mutable_args()->AppendString(*it2); |
| 424 } | 401 } |
| 425 LogAction(action); | 402 LogAction(action); |
| 426 } | 403 } |
| 427 } | 404 } |
| 428 } | 405 } |
| 429 | 406 |
| 407 // static |
| 408 void ActivityLog::RegisterProfilePrefs( |
| 409 user_prefs::PrefRegistrySyncable* registry) { |
| 410 registry->RegisterBooleanPref( |
| 411 prefs::kWatchdogExtensionActive, |
| 412 false, |
| 413 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); |
| 414 } |
| 415 |
| 430 } // namespace extensions | 416 } // namespace extensions |
| OLD | NEW |