Chromium Code Reviews| 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/strings/string_util.h" | 10 #include "base/strings/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/activity_log/stream_noargs_ui_policy.h" |
| 16 #include "chrome/browser/extensions/api/activity_log_private/activity_log_privat e_api.h" | 16 #include "chrome/browser/extensions/api/activity_log_private/activity_log_privat e_api.h" |
| 17 #include "chrome/browser/extensions/extension_service.h" | 17 #include "chrome/browser/extensions/extension_service.h" |
| 18 #include "chrome/browser/extensions/extension_system.h" | 18 #include "chrome/browser/extensions/extension_system.h" |
| 19 #include "chrome/browser/extensions/extension_system_factory.h" | 19 #include "chrome/browser/extensions/extension_system_factory.h" |
| 20 #include "chrome/browser/extensions/install_tracker_factory.h" | 20 #include "chrome/browser/extensions/install_tracker_factory.h" |
| 21 #include "chrome/browser/prefs/pref_service_syncable.h" | |
| 21 #include "chrome/browser/prerender/prerender_manager.h" | 22 #include "chrome/browser/prerender/prerender_manager.h" |
| 22 #include "chrome/browser/prerender/prerender_manager_factory.h" | 23 #include "chrome/browser/prerender/prerender_manager_factory.h" |
| 23 #include "chrome/browser/profiles/incognito_helpers.h" | 24 #include "chrome/browser/profiles/incognito_helpers.h" |
| 24 #include "chrome/common/chrome_constants.h" | 25 #include "chrome/common/chrome_constants.h" |
| 25 #include "chrome/common/chrome_switches.h" | 26 #include "chrome/common/chrome_switches.h" |
| 26 #include "chrome/common/extensions/extension.h" | 27 #include "chrome/common/extensions/extension.h" |
| 28 #include "chrome/common/pref_names.h" | |
| 27 #include "components/browser_context_keyed_service/browser_context_dependency_ma nager.h" | 29 #include "components/browser_context_keyed_service/browser_context_dependency_ma nager.h" |
| 28 #include "content/public/browser/web_contents.h" | 30 #include "content/public/browser/web_contents.h" |
| 29 #include "third_party/re2/re2/re2.h" | 31 #include "third_party/re2/re2/re2.h" |
| 30 #include "url/gurl.h" | 32 #include "url/gurl.h" |
| 31 | 33 |
| 32 namespace { | 34 namespace { |
| 33 | 35 |
| 34 // Concatenate arguments. | 36 // Concatenate arguments. |
| 35 std::string MakeArgList(const base::ListValue* args) { | 37 std::string MakeArgList(const base::ListValue* args) { |
| 36 std::string call_signature; | 38 std::string call_signature; |
| 37 base::ListValue::const_iterator it = args->begin(); | 39 base::ListValue::const_iterator it = args->begin(); |
| 38 for (; it != args->end(); ++it) { | 40 for (; it != args->end(); ++it) { |
| 39 std::string arg; | 41 std::string arg; |
| 40 JSONStringValueSerializer serializer(&arg); | 42 JSONStringValueSerializer serializer(&arg); |
| 41 if (serializer.SerializeAndOmitBinaryValues(**it)) { | 43 if (serializer.SerializeAndOmitBinaryValues(**it)) { |
| 42 if (it != args->begin()) | 44 if (it != args->begin()) |
| 43 call_signature += ", "; | 45 call_signature += ", "; |
| 44 call_signature += arg; | 46 call_signature += arg; |
| 45 } | 47 } |
| 46 } | 48 } |
| 47 return call_signature; | 49 return call_signature; |
| 48 } | 50 } |
| 49 | 51 |
| 50 // This is a hack for AL callers who don't have access to a profile object | |
| 51 // when deciding whether or not to do the work required for logging. The state | |
| 52 // is accessed through the static ActivityLog::IsLogEnabledOnAnyProfile() | |
| 53 // method. It returns true if --enable-extension-activity-logging is set on the | |
| 54 // command line OR *ANY* profile has the activity log whitelisted extension | |
| 55 // installed. | |
| 56 class LogIsEnabled { | |
| 57 public: | |
| 58 LogIsEnabled() : any_profile_enabled_(false) { | |
| 59 ComputeIsFlagEnabled(); | |
| 60 } | |
| 61 | |
| 62 void ComputeIsFlagEnabled() { | |
| 63 base::AutoLock auto_lock(lock_); | |
| 64 cmd_line_enabled_ = CommandLine::ForCurrentProcess()-> | |
| 65 HasSwitch(switches::kEnableExtensionActivityLogging); | |
| 66 } | |
| 67 | |
| 68 static LogIsEnabled* GetInstance() { | |
| 69 return Singleton<LogIsEnabled>::get(); | |
| 70 } | |
| 71 | |
| 72 bool IsEnabled() { | |
| 73 base::AutoLock auto_lock(lock_); | |
| 74 return cmd_line_enabled_ || any_profile_enabled_; | |
| 75 } | |
| 76 | |
| 77 void SetProfileEnabled(bool any_profile_enabled) { | |
| 78 base::AutoLock auto_lock(lock_); | |
| 79 any_profile_enabled_ = any_profile_enabled; | |
| 80 } | |
| 81 | |
| 82 private: | |
| 83 base::Lock lock_; | |
| 84 bool any_profile_enabled_; | |
| 85 bool cmd_line_enabled_; | |
| 86 }; | |
| 87 | |
| 88 } // namespace | 52 } // namespace |
| 89 | 53 |
| 90 namespace extensions { | 54 namespace extensions { |
| 91 | 55 |
| 92 // static | |
| 93 bool ActivityLog::IsLogEnabledOnAnyProfile() { | |
| 94 return LogIsEnabled::GetInstance()->IsEnabled(); | |
| 95 } | |
| 96 | |
| 97 // static | |
| 98 void ActivityLog::RecomputeLoggingIsEnabled(bool profile_enabled) { | |
| 99 LogIsEnabled::GetInstance()->ComputeIsFlagEnabled(); | |
| 100 LogIsEnabled::GetInstance()->SetProfileEnabled(profile_enabled); | |
| 101 } | |
| 102 | |
| 103 // ActivityLogFactory | 56 // ActivityLogFactory |
| 104 | 57 |
| 105 ActivityLogFactory* ActivityLogFactory::GetInstance() { | 58 ActivityLogFactory* ActivityLogFactory::GetInstance() { |
| 106 return Singleton<ActivityLogFactory>::get(); | 59 return Singleton<ActivityLogFactory>::get(); |
| 107 } | 60 } |
| 108 | 61 |
| 109 BrowserContextKeyedService* ActivityLogFactory::BuildServiceInstanceFor( | 62 BrowserContextKeyedService* ActivityLogFactory::BuildServiceInstanceFor( |
| 110 content::BrowserContext* profile) const { | 63 content::BrowserContext* profile) const { |
| 111 return new ActivityLog(static_cast<Profile*>(profile)); | 64 return new ActivityLog(static_cast<Profile*>(profile)); |
| 112 } | 65 } |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 156 policy_type_ = policy_type; | 109 policy_type_ = policy_type; |
| 157 } | 110 } |
| 158 } | 111 } |
| 159 | 112 |
| 160 // Use GetInstance instead of directly creating an ActivityLog. | 113 // Use GetInstance instead of directly creating an ActivityLog. |
| 161 ActivityLog::ActivityLog(Profile* profile) | 114 ActivityLog::ActivityLog(Profile* profile) |
| 162 : policy_(NULL), | 115 : policy_(NULL), |
| 163 policy_type_(ActivityLogPolicy::POLICY_INVALID), | 116 policy_type_(ActivityLogPolicy::POLICY_INVALID), |
| 164 profile_(profile), | 117 profile_(profile), |
| 165 enabled_(false), | 118 enabled_(false), |
| 166 initialized_(false), | |
| 167 policy_chosen_(false), | 119 policy_chosen_(false), |
| 168 testing_mode_(false), | 120 testing_mode_(false), |
| 169 has_threads_(true), | 121 has_threads_(true), |
| 170 tracker_(NULL) { | 122 tracker_(NULL), |
| 123 watchdog_extension_active_(false) { | |
| 171 // This controls whether logging statements are printed, which policy is set, | 124 // This controls whether logging statements are printed, which policy is set, |
| 172 // etc. | 125 // etc. |
| 173 testing_mode_ = CommandLine::ForCurrentProcess()->HasSwitch( | 126 testing_mode_ = CommandLine::ForCurrentProcess()->HasSwitch( |
| 174 switches::kEnableExtensionActivityLogTesting); | 127 switches::kEnableExtensionActivityLogTesting); |
| 175 | 128 |
| 129 // Check if the watchdog extension is previously installed and active. | |
| 130 watchdog_extension_active_ = | |
| 131 profile_->GetPrefs()->GetBoolean(prefs::kWatchdogExtensionActive); | |
| 132 | |
| 176 // Check that the right threads exist. If not, we shouldn't try to do things | 133 // Check that the right threads exist. If not, we shouldn't try to do things |
| 177 // that require them. | 134 // that require them. |
| 178 if (!BrowserThread::IsMessageLoopValid(BrowserThread::DB) || | 135 if (!BrowserThread::IsMessageLoopValid(BrowserThread::DB) || |
| 179 !BrowserThread::IsMessageLoopValid(BrowserThread::FILE) || | 136 !BrowserThread::IsMessageLoopValid(BrowserThread::FILE) || |
| 180 !BrowserThread::IsMessageLoopValid(BrowserThread::IO)) { | 137 !BrowserThread::IsMessageLoopValid(BrowserThread::IO)) { |
| 181 LOG(ERROR) << "Missing threads, disabling Activity Logging!"; | 138 LOG(ERROR) << "Missing threads, disabling Activity Logging!"; |
| 182 has_threads_ = false; | 139 has_threads_ = false; |
| 183 } else { | 140 return; |
|
felt
2013/07/23 06:37:34
If we return here, observers is never set to anyth
pmarch
2013/07/29 17:36:47
I think you are right, we should not return here.
| |
| 184 enabled_ = IsLogEnabledOnAnyProfile(); | |
| 185 ExtensionSystem::Get(profile_)->ready().Post( | |
| 186 FROM_HERE, base::Bind(&ActivityLog::Init, base::Unretained(this))); | |
| 187 } | 141 } |
| 188 | 142 |
| 143 enabled_ = CommandLine::ForCurrentProcess()-> | |
| 144 HasSwitch(switches::kEnableExtensionActivityLogging) | |
| 145 || watchdog_extension_active_; | |
| 189 observers_ = new ObserverListThreadSafe<Observer>; | 146 observers_ = new ObserverListThreadSafe<Observer>; |
| 147 | |
| 148 ExtensionSystem::Get(profile_)->ready().Post( | |
| 149 FROM_HERE, | |
| 150 base::Bind(&ActivityLog::InitInstallTracker, base::Unretained(this))); | |
| 151 ChooseDefaultPolicy(); | |
| 190 } | 152 } |
| 191 | 153 |
| 192 void ActivityLog::Init() { | 154 void ActivityLog::InitInstallTracker() { |
| 193 DCHECK(has_threads_); | |
| 194 DCHECK(!initialized_); | |
| 195 const Extension* whitelisted_extension = ExtensionSystem::Get(profile_)-> | |
| 196 extension_service()->GetExtensionById(kActivityLogExtensionId, false); | |
| 197 if (whitelisted_extension) { | |
| 198 enabled_ = true; | |
| 199 LogIsEnabled::GetInstance()->SetProfileEnabled(true); | |
| 200 } | |
| 201 tracker_ = InstallTrackerFactory::GetForProfile(profile_); | 155 tracker_ = InstallTrackerFactory::GetForProfile(profile_); |
| 202 tracker_->AddObserver(this); | 156 tracker_->AddObserver(this); |
| 203 ChooseDefaultPolicy(); | |
| 204 initialized_ = true; | |
| 205 } | 157 } |
| 206 | 158 |
| 207 void ActivityLog::ChooseDefaultPolicy() { | 159 void ActivityLog::ChooseDefaultPolicy() { |
| 208 if (policy_chosen_ || !enabled_) return; | 160 if (policy_chosen_ || !enabled_) return; |
| 209 if (testing_mode_) | 161 if (testing_mode_) |
| 210 SetDefaultPolicy(ActivityLogPolicy::POLICY_FULLSTREAM); | 162 SetDefaultPolicy(ActivityLogPolicy::POLICY_FULLSTREAM); |
| 211 else | 163 else |
| 212 SetDefaultPolicy(ActivityLogPolicy::POLICY_NOARGS); | 164 SetDefaultPolicy(ActivityLogPolicy::POLICY_NOARGS); |
| 213 } | 165 } |
| 214 | 166 |
| 215 void ActivityLog::Shutdown() { | 167 void ActivityLog::Shutdown() { |
| 216 if (tracker_) tracker_->RemoveObserver(this); | 168 if (tracker_) tracker_->RemoveObserver(this); |
| 217 } | 169 } |
| 218 | 170 |
| 219 ActivityLog::~ActivityLog() { | 171 ActivityLog::~ActivityLog() { |
| 220 if (policy_) | 172 if (policy_) |
| 221 policy_->Close(); | 173 policy_->Close(); |
| 222 } | 174 } |
| 223 | 175 |
| 224 bool ActivityLog::IsLogEnabled() { | 176 bool ActivityLog::IsLogEnabled() { |
| 225 if (!has_threads_ || !initialized_) return false; | 177 // Make sure we are not enabled when there are no threads. |
| 178 DCHECK(has_threads_ || !enabled_); | |
| 226 return enabled_; | 179 return enabled_; |
| 227 } | 180 } |
| 228 | 181 |
| 229 void ActivityLog::OnExtensionLoaded(const Extension* extension) { | 182 void ActivityLog::OnExtensionLoaded(const Extension* extension) { |
| 230 if (extension->id() != kActivityLogExtensionId) return; | 183 if (extension->id() != kActivityLogExtensionId) return; |
| 231 enabled_ = true; | 184 if (has_threads_) |
| 232 LogIsEnabled::GetInstance()->SetProfileEnabled(true); | 185 enabled_ = true; |
|
felt
2013/07/23 06:37:34
Can you switch this to:
if (!has_threads_) return;
pmarch
2013/07/29 17:36:47
I do not think it is the right thing to do. If has
felt
2013/07/29 19:29:42
Ah, OK, you're right -- the semantics have changed
| |
| 186 if (!watchdog_extension_active_) { | |
| 187 watchdog_extension_active_ = true; | |
| 188 profile_->GetPrefs()->SetBoolean(prefs::kWatchdogExtensionActive, true); | |
| 189 } | |
| 233 ChooseDefaultPolicy(); | 190 ChooseDefaultPolicy(); |
| 234 } | 191 } |
| 235 | 192 |
| 236 void ActivityLog::OnExtensionUnloaded(const Extension* extension) { | 193 void ActivityLog::OnExtensionUnloaded(const Extension* extension) { |
| 237 if (extension->id() != kActivityLogExtensionId) return; | 194 if (extension->id() != kActivityLogExtensionId) return; |
| 195 // Make sure we are not enabled when there are no threads. | |
| 196 DCHECK(has_threads_ || !enabled_); | |
| 238 if (!CommandLine::ForCurrentProcess()->HasSwitch( | 197 if (!CommandLine::ForCurrentProcess()->HasSwitch( |
| 239 switches::kEnableExtensionActivityLogging)) | 198 switches::kEnableExtensionActivityLogging)) |
| 240 enabled_ = false; | 199 enabled_ = false; |
| 200 if (watchdog_extension_active_) { | |
| 201 watchdog_extension_active_ = false; | |
| 202 profile_->GetPrefs()->SetBoolean(prefs::kWatchdogExtensionActive, | |
| 203 false); | |
| 204 } | |
| 241 } | 205 } |
| 242 | 206 |
| 243 // static | 207 // static |
| 244 ActivityLog* ActivityLog::GetInstance(Profile* profile) { | 208 ActivityLog* ActivityLog::GetInstance(Profile* profile) { |
| 245 return ActivityLogFactory::GetForProfile(profile); | 209 return ActivityLogFactory::GetForProfile(profile); |
| 246 } | 210 } |
| 247 | 211 |
| 248 void ActivityLog::AddObserver(ActivityLog::Observer* observer) { | 212 void ActivityLog::AddObserver(ActivityLog::Observer* observer) { |
| 249 observers_->AddObserver(observer); | 213 observers_->AddObserver(observer); |
| 250 } | 214 } |
| (...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 505 on_url, | 469 on_url, |
| 506 web_contents->GetTitle(), | 470 web_contents->GetTitle(), |
| 507 std::string(), // no api call here | 471 std::string(), // no api call here |
| 508 script_names.get(), | 472 script_names.get(), |
| 509 DomActionType::INSERTED, | 473 DomActionType::INSERTED, |
| 510 extra); | 474 extra); |
| 511 } | 475 } |
| 512 } | 476 } |
| 513 } | 477 } |
| 514 | 478 |
| 479 // static | |
| 480 void ActivityLog::RegisterProfilePrefs( | |
| 481 user_prefs::PrefRegistrySyncable* registry) { | |
| 482 registry->RegisterBooleanPref( | |
| 483 prefs::kWatchdogExtensionActive, | |
| 484 false, | |
| 485 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); | |
|
felt
2013/07/23 06:37:34
Does this mean it will sync across browsers? Since
pmarch
2013/07/29 17:36:47
I will make it Non-syncable.
| |
| 486 } | |
| 487 | |
| 515 } // namespace extensions | 488 } // namespace extensions |
| OLD | NEW |