Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(947)

Side by Side Diff: chrome/browser/extensions/activity_log.cc

Issue 11886084: Revert 177235 (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 7 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
Property Changes:
Added: svn:mergeinfo
OLDNEW
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.h" 5 #include "chrome/browser/extensions/activity_log.h"
6 6
7 #include <set>
8 #include "base/command_line.h" 7 #include "base/command_line.h"
9 #include "base/json/json_string_value_serializer.h"
10 #include "base/logging.h" 8 #include "base/logging.h"
11 #include "base/string_util.h" 9 #include "base/string_util.h"
12 #include "base/threading/thread_checker.h"
13 #include "chrome/browser/extensions/api_actions.h"
14 #include "chrome/browser/extensions/blocked_actions.h"
15 #include "chrome/browser/extensions/extension_service.h" 10 #include "chrome/browser/extensions/extension_service.h"
16 #include "chrome/browser/extensions/extension_system.h" 11 #include "chrome/browser/extensions/extension_system.h"
17 #include "chrome/common/chrome_constants.h" 12 #include "chrome/browser/profiles/profile.h"
18 #include "chrome/common/chrome_switches.h" 13 #include "chrome/common/chrome_switches.h"
19 #include "chrome/common/extensions/extension.h" 14 #include "chrome/common/extensions/extension.h"
20 #include "content/public/browser/web_contents.h" 15 #include "content/public/browser/web_contents.h"
21 #include "googleurl/src/gurl.h" 16 #include "googleurl/src/gurl.h"
22 #include "sql/error_delegate_util.h"
23 #include "third_party/re2/re2/re2.h"
24
25 namespace {
26
27 // Concatenate an API call with its arguments.
28 std::string MakeCallSignature(const std::string& name, const ListValue* args) {
29 std::string call_signature = name + "(";
30 ListValue::const_iterator it = args->begin();
31 for (; it != args->end(); ++it) {
32 std::string arg;
33 JSONStringValueSerializer serializer(&arg);
34 if (serializer.SerializeAndOmitBinaryValues(**it)) {
35 if (it != args->begin())
36 call_signature += ", ";
37 call_signature += arg;
38 }
39 }
40 call_signature += ")";
41 return call_signature;
42 }
43
44 } // namespace
45 17
46 namespace extensions { 18 namespace extensions {
47 19
48 // This handles errors from the database. 20 ActivityLog::ActivityLog() {
49 class KillActivityDatabaseErrorDelegate : public sql::ErrorDelegate {
50 public:
51 explicit KillActivityDatabaseErrorDelegate(ActivityLog* backend)
52 : backend_(backend),
53 scheduled_death_(false) {}
54
55 virtual int OnError(int error,
56 sql::Connection* connection,
57 sql::Statement* stmt) OVERRIDE {
58 if (!scheduled_death_ && sql::IsErrorCatastrophic(error)) {
59 ScheduleDeath();
60 }
61 return error;
62 }
63
64 // Schedules death if an error wasn't already reported.
65 void ScheduleDeath() {
66 if (!scheduled_death_) {
67 scheduled_death_ = true;
68 backend_->KillActivityLogDatabase();
69 }
70 }
71
72 bool scheduled_death() const {
73 return scheduled_death_;
74 }
75
76 private:
77 ActivityLog* backend_;
78 bool scheduled_death_;
79
80 DISALLOW_COPY_AND_ASSIGN(KillActivityDatabaseErrorDelegate);
81 };
82
83 // ActivityLogFactory
84
85 ActivityLogFactory* ActivityLogFactory::GetInstance() {
86 return Singleton<ActivityLogFactory>::get();
87 }
88
89 ProfileKeyedService* ActivityLogFactory::BuildServiceInstanceFor(
90 Profile* profile) const {
91 return new ActivityLog(profile);
92 }
93
94 bool ActivityLogFactory::ServiceRedirectedInIncognito() const {
95 return true;
96 }
97
98 // ActivityLog
99
100 // Use GetInstance instead of directly creating an ActivityLog.
101 ActivityLog::ActivityLog(Profile* profile) {
102 log_activity_to_stdout_ = CommandLine::ForCurrentProcess()-> 21 log_activity_to_stdout_ = CommandLine::ForCurrentProcess()->
103 HasSwitch(switches::kEnableExtensionActivityLogging); 22 HasSwitch(switches::kEnableExtensionActivityLogging);
104
105 // If the database cannot be initialized for some reason, we keep
106 // chugging along but nothing will get recorded. If the UI is
107 // available, things will still get sent to the UI even if nothing
108 // is being written to the database.
109 db_ = new ActivityDatabase();
110 #if defined(ENABLE_EXTENSIONS) && !defined(OS_ANDROID)
111 FilePath base_dir = profile->GetPath();
112 FilePath database_name = base_dir.Append(
113 chrome::kExtensionActivityLogFilename);
114 KillActivityDatabaseErrorDelegate* error_delegate =
115 new KillActivityDatabaseErrorDelegate(this);
116 ScheduleAndForget(&ActivityDatabase::Init,
117 database_name,
118 error_delegate);
119 #endif
120 } 23 }
121 24
122 ActivityLog::~ActivityLog() { 25 ActivityLog::~ActivityLog() {
123 } 26 }
124 27
125 // static 28 // static
126 ActivityLog* ActivityLog::GetInstance(Profile* profile) { 29 ActivityLog* ActivityLog::GetInstance() {
127 return ActivityLogFactory::GetForProfile(profile); 30 return Singleton<ActivityLog>::get();
128 } 31 }
129 32
130 void ActivityLog::AddObserver(const Extension* extension, 33 void ActivityLog::AddObserver(const Extension* extension,
131 ActivityLog::Observer* observer) { 34 ActivityLog::Observer* observer) {
35 base::AutoLock scoped_lock(lock_);
36
132 if (observers_.count(extension) == 0) { 37 if (observers_.count(extension) == 0) {
133 observers_[extension] = new ObserverListThreadSafe<Observer>; 38 observers_[extension] = new ObserverListThreadSafe<Observer>;
134 } 39 }
135 40
136 observers_[extension]->AddObserver(observer); 41 observers_[extension]->AddObserver(observer);
137 } 42 }
138 43
139 void ActivityLog::RemoveObserver(const Extension* extension, 44 void ActivityLog::RemoveObserver(const Extension* extension,
140 ActivityLog::Observer* observer) { 45 ActivityLog::Observer* observer) {
46 base::AutoLock scoped_lock(lock_);
47
141 if (observers_.count(extension) == 1) { 48 if (observers_.count(extension) == 1) {
142 observers_[extension]->RemoveObserver(observer); 49 observers_[extension]->RemoveObserver(observer);
143 } 50 }
144 } 51 }
145 52
53 // Extension*
146 bool ActivityLog::HasObservers(const Extension* extension) const { 54 bool ActivityLog::HasObservers(const Extension* extension) const {
55 base::AutoLock scoped_lock(lock_);
56
147 // We also return true if extension activity logging is enabled since in that 57 // We also return true if extension activity logging is enabled since in that
148 // case this class is observing all extensions. 58 // case this class is observing all extensions.
149 return observers_.count(extension) > 0 || log_activity_to_stdout_; 59 return observers_.count(extension) > 0 || log_activity_to_stdout_;
150 } 60 }
151 61
152 void ActivityLog::LogAPIAction(const Extension* extension, 62 void ActivityLog::Log(const Extension* extension,
153 const std::string& name, 63 Activity activity,
154 const ListValue* args, 64 const std::string& message) const {
155 const std::string& extra) { 65 std::vector<std::string> messages(1, message);
156 std::string verb, manager; 66 Log(extension, activity, messages);
157 bool matches = RE2::FullMatch(name, "(.*?)\\.(.*)", &manager, &verb); 67 }
158 if (matches) {
159 std::string call_signature = MakeCallSignature(name, args);
160 scoped_refptr<APIAction> action = new APIAction(
161 extension->id(),
162 base::Time::Now(),
163 APIAction::StringAsActionType(verb),
164 APIAction::StringAsTargetType(manager),
165 call_signature,
166 extra);
167 ScheduleAndForget(&ActivityDatabase::RecordAction, action);
168 68
169 // Display the action. 69 void ActivityLog::Log(const Extension* extension,
170 ObserverMap::const_iterator iter = observers_.find(extension); 70 Activity activity,
171 if (iter != observers_.end()) { 71 const std::vector<std::string>& messages) const {
172 iter->second->Notify(&Observer::OnExtensionActivity, 72 base::AutoLock scoped_lock(lock_);
173 extension, 73
174 ActivityLog::ACTIVITY_EXTENSION_API_CALL, 74 ObserverMap::const_iterator iter = observers_.find(extension);
175 call_signature); 75 if (iter != observers_.end()) {
176 } 76 iter->second->Notify(&Observer::OnExtensionActivity, extension, activity,
177 if (log_activity_to_stdout_) { 77 messages);
178 LOG(INFO) << action->PrettyPrintForDebug(); 78 }
179 } 79
180 } else { 80 if (log_activity_to_stdout_) {
181 LOG(ERROR) << "Unknown API call! " << name; 81 LOG(INFO) << extension->id() << ":" << ActivityToString(activity) << ":" <<
82 JoinString(messages, ' ');
182 } 83 }
183 } 84 }
184 85
185 void ActivityLog::LogBlockedAction(const Extension* extension,
186 const std::string& blocked_name,
187 const ListValue* args,
188 const char* reason,
189 const std::string& extra) {
190 std::string blocked_call = MakeCallSignature(blocked_name, args);
191 scoped_refptr<BlockedAction> action = new BlockedAction(extension->id(),
192 base::Time::Now(),
193 blocked_call,
194 std::string(reason),
195 extra);
196 ScheduleAndForget(&ActivityDatabase::RecordAction, action);
197 // Display the action.
198 ObserverMap::const_iterator iter = observers_.find(extension);
199 if (iter != observers_.end()) {
200 iter->second->Notify(&Observer::OnExtensionActivity,
201 extension,
202 ActivityLog::ACTIVITY_EXTENSION_API_BLOCK,
203 blocked_call);
204 }
205 if (log_activity_to_stdout_) {
206 LOG(INFO) << action->PrettyPrintForDebug();
207 }
208 }
209
210 void ActivityLog::LogUrlAction(const Extension* extension,
211 const UrlAction::UrlActionType verb,
212 const GURL& url,
213 const string16& url_title,
214 const std::string& technical_message,
215 const std::string& extra) {
216 scoped_refptr<UrlAction> action = new UrlAction(
217 extension->id(),
218 base::Time::Now(),
219 verb,
220 url,
221 url_title,
222 technical_message,
223 extra);
224 ScheduleAndForget(&ActivityDatabase::RecordAction, action);
225
226 // Display the action.
227 ObserverMap::const_iterator iter = observers_.find(extension);
228 if (iter != observers_.end()) {
229 iter->second->Notify(&Observer::OnExtensionActivity,
230 extension,
231 ActivityLog::ACTIVITY_CONTENT_SCRIPT,
232 action->PrettyPrintForDebug());
233 }
234 if (log_activity_to_stdout_) {
235 LOG(INFO) << action->PrettyPrintForDebug();
236 }
237 }
238
239 void ActivityLog::OnScriptsExecuted( 86 void ActivityLog::OnScriptsExecuted(
240 const content::WebContents* web_contents, 87 const content::WebContents* web_contents,
241 const ExecutingScriptsMap& extension_ids, 88 const ExecutingScriptsMap& extension_ids,
242 int32 on_page_id, 89 int32 on_page_id,
243 const GURL& on_url) { 90 const GURL& on_url) {
244 Profile* profile = 91 Profile* profile =
245 Profile::FromBrowserContext(web_contents->GetBrowserContext()); 92 Profile::FromBrowserContext(web_contents->GetBrowserContext());
246 const ExtensionService* extension_service = 93 const ExtensionService* extension_service =
247 ExtensionSystem::Get(profile)->extension_service(); 94 ExtensionSystem::Get(profile)->extension_service();
248 const ExtensionSet* extensions = extension_service->extensions(); 95 const ExtensionSet* extensions = extension_service->extensions();
249 96
250 for (ExecutingScriptsMap::const_iterator it = extension_ids.begin(); 97 for (ExecutingScriptsMap::const_iterator it = extension_ids.begin();
251 it != extension_ids.end(); ++it) { 98 it != extension_ids.end(); ++it) {
252 const Extension* extension = extensions->GetByID(it->first); 99 const Extension* extension = extensions->GetByID(it->first);
253 if (!extension || !HasObservers(extension)) 100 if (!extension || !HasObservers(extension))
254 continue; 101 continue;
255 102
256 // If OnScriptsExecuted is fired because of tabs.executeScript, the list 103 for (std::set<std::string>::const_iterator it2 = it->second.begin();
257 // of content scripts will be empty. We don't want to log it because 104 it2 != it->second.end(); ++it2) {
258 // the call to tabs.executeScript will have already been logged anyway. 105 std::vector<std::string> messages;
259 if (!it->second.empty()) { 106 messages.push_back(on_url.spec());
260 std::string ext_scripts_str = ""; 107 messages.push_back(*it2);
261 for (std::set<std::string>::const_iterator it2 = it->second.begin(); 108 Log(extension, ActivityLog::ACTIVITY_CONTENT_SCRIPT, messages);
262 it2 != it->second.end(); ++it2) {
263 ext_scripts_str += *it2;
264 ext_scripts_str += " ";
265 }
266 LogUrlAction(extension,
267 UrlAction::INSERTED,
268 on_url,
269 web_contents->GetTitle(),
270 ext_scripts_str,
271 "");
272 } 109 }
273 } 110 }
274 } 111 }
275 112
276 void ActivityLog::KillActivityLogDatabase() {
277 if (db_.get()) {
278 ScheduleAndForget(&ActivityDatabase::KillDatabase);
279 }
280 }
281
282 // static 113 // static
283 const char* ActivityLog::ActivityToString(Activity activity) { 114 const char* ActivityLog::ActivityToString(Activity activity) {
284 switch (activity) { 115 switch (activity) {
285 case ActivityLog::ACTIVITY_EXTENSION_API_CALL: 116 case ActivityLog::ACTIVITY_EXTENSION_API_CALL:
286 return "api_call"; 117 return "api_call";
287 case ActivityLog::ACTIVITY_EXTENSION_API_BLOCK: 118 case ActivityLog::ACTIVITY_EXTENSION_API_BLOCK:
288 return "api_block"; 119 return "api_block";
289 case ActivityLog::ACTIVITY_CONTENT_SCRIPT: 120 case ActivityLog::ACTIVITY_CONTENT_SCRIPT:
290 return "content_script"; 121 return "content_script";
291 default: 122 default:
292 NOTREACHED(); 123 NOTREACHED();
293 return ""; 124 return "";
294 } 125 }
295 } 126 }
296 127
297 } // namespace extensions 128 } // namespace extensions
OLDNEW
« no previous file with comments | « chrome/browser/extensions/activity_log.h ('k') | chrome/browser/extensions/activity_log_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698