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