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

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

Issue 11421192: Save extension activity log to a file. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Another small fix Created 8 years 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
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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/extension_function_dispatcher.h" 5 #include "chrome/browser/extensions/extension_function_dispatcher.h"
6 6
7 #include <map> 7 #include <map>
8 8
9 #include "base/bind.h"
9 #include "base/json/json_string_value_serializer.h" 10 #include "base/json/json_string_value_serializer.h"
10 #include "base/lazy_instance.h" 11 #include "base/lazy_instance.h"
11 #include "base/memory/ref_counted.h" 12 #include "base/memory/ref_counted.h"
12 #include "base/process_util.h" 13 #include "base/process_util.h"
13 #include "base/values.h" 14 #include "base/values.h"
14 #include "build/build_config.h" 15 #include "build/build_config.h"
15 #include "chrome/browser/extensions/activity_log.h" 16 #include "chrome/browser/extensions/activity_log.h"
16 #include "chrome/browser/extensions/extension_function.h" 17 #include "chrome/browser/extensions/extension_function.h"
17 #include "chrome/browser/extensions/extension_function_registry.h" 18 #include "chrome/browser/extensions/extension_function_registry.h"
18 #include "chrome/browser/extensions/extension_service.h" 19 #include "chrome/browser/extensions/extension_service.h"
19 #include "chrome/browser/extensions/extension_system.h" 20 #include "chrome/browser/extensions/extension_system.h"
20 #include "chrome/browser/extensions/extension_web_ui.h" 21 #include "chrome/browser/extensions/extension_web_ui.h"
21 #include "chrome/browser/extensions/extensions_quota_service.h" 22 #include "chrome/browser/extensions/extensions_quota_service.h"
22 #include "chrome/browser/extensions/process_map.h" 23 #include "chrome/browser/extensions/process_map.h"
23 #include "chrome/browser/external_protocol/external_protocol_handler.h" 24 #include "chrome/browser/external_protocol/external_protocol_handler.h"
24 #include "chrome/browser/profiles/profile.h" 25 #include "chrome/browser/profiles/profile.h"
25 #include "chrome/browser/renderer_host/chrome_render_message_filter.h" 26 #include "chrome/browser/renderer_host/chrome_render_message_filter.h"
26 #include "chrome/common/extensions/api/extension_api.h" 27 #include "chrome/common/extensions/api/extension_api.h"
27 #include "chrome/common/extensions/extension_messages.h" 28 #include "chrome/common/extensions/extension_messages.h"
28 #include "chrome/common/extensions/extension_set.h" 29 #include "chrome/common/extensions/extension_set.h"
29 #include "chrome/common/url_constants.h" 30 #include "chrome/common/url_constants.h"
31 #include "content/public/browser/browser_thread.h"
30 #include "content/public/browser/render_process_host.h" 32 #include "content/public/browser/render_process_host.h"
31 #include "content/public/browser/render_view_host.h" 33 #include "content/public/browser/render_view_host.h"
32 #include "ipc/ipc_message.h" 34 #include "ipc/ipc_message.h"
33 #include "ipc/ipc_message_macros.h" 35 #include "ipc/ipc_message_macros.h"
34 #include "third_party/WebKit/Source/WebKit/chromium/public/WebSecurityOrigin.h" 36 #include "third_party/WebKit/Source/WebKit/chromium/public/WebSecurityOrigin.h"
35 #include "webkit/glue/resource_type.h" 37 #include "webkit/glue/resource_type.h"
36 38
37 using extensions::Extension; 39 using extensions::Extension;
38 using extensions::ExtensionAPI; 40 using extensions::ExtensionAPI;
39 using content::RenderViewHost; 41 using content::RenderViewHost;
40 using WebKit::WebSecurityOrigin; 42 using WebKit::WebSecurityOrigin;
41 43
42 namespace { 44 namespace {
43 45
44 const char kAccessDenied[] = "access denied"; 46 const char kAccessDenied[] = "access denied";
45 const char kQuotaExceeded[] = "quota exceeded"; 47 const char kQuotaExceeded[] = "quota exceeded";
46 48
47 void LogSuccess(const Extension* extension, 49 void LogSuccess(const Extension* extension,
48 const ExtensionHostMsg_Request_Params& params) { 50 const std::string& api_name,
49 extensions::ActivityLog* activity_log = 51 const ListValue* args,
Matt Perry 2013/01/03 20:53:35 This leaks |args|. Pass as a scoped_ptr to fix.
felt 2013/01/07 23:44:22 I think I've done this correctly, assuming you don
Matt Perry 2013/01/08 00:02:01 Correct. (Only use scoped_ptr when passing ownersh
50 extensions::ActivityLog::GetInstance(); 52 Profile* profile) {
51 if (activity_log->HasObservers(extension)) { 53 // The ActivityLog can only be accessed from the main (UI) thread. If we're
52 std::string call_signature = params.name + "("; 54 // running on the wrong thread, re-dispatch from the main thread.
53 ListValue::const_iterator it = params.arguments.begin(); 55 BrowserThread::ID thread_id;
54 for (; it != params.arguments.end(); ++it) { 56 bool known = BrowserThread::GetCurrentThreadIdentifier(&thread_id);
Matt Perry 2013/01/03 20:53:35 Use BrowserThread::CurrentlyOn
felt 2013/01/07 23:44:22 Done.
55 std::string arg; 57 if (!known || thread_id != BrowserThread::UI) {
56 JSONStringValueSerializer serializer(&arg); 58 BrowserThread::PostTask(BrowserThread::UI,
57 if (serializer.SerializeAndOmitBinaryValues(**it)) { 59 FROM_HERE,
58 if (it != params.arguments.begin()) 60 base::Bind(&LogSuccess,
59 call_signature += ", "; 61 extension,
60 call_signature += arg; 62 api_name,
61 } 63 args,
62 } 64 profile));
63 call_signature += ")"; 65 } else {
64 66 extensions::ActivityLog* activity_log =
65 activity_log->Log(extension, 67 extensions::ActivityLog::GetInstance(profile);
66 extensions::ActivityLog::ACTIVITY_EXTENSION_API_CALL, 68 if (activity_log->HasObservers(extension))
67 call_signature); 69 activity_log->LogAPIAction(extension, api_name, args);
68 } 70 }
69 } 71 }
70 72
71 void LogFailure(const Extension* extension, 73 void LogFailure(const Extension* extension,
72 const std::string& func_name, 74 const std::string& api_name,
73 const char* reason) { 75 const ListValue* args,
74 extensions::ActivityLog* activity_log = 76 const char* reason,
75 extensions::ActivityLog::GetInstance(); 77 Profile* profile) {
76 if (activity_log->HasObservers(extension)) { 78 // The ActivityLog can only be accessed from the main (UI) thread. If we're
77 activity_log->Log(extension, 79 // running on the wrong thread, re-dispatch from the main thread.
78 extensions::ActivityLog::ACTIVITY_EXTENSION_API_BLOCK, 80 BrowserThread::ID thread_id;
79 func_name + ": " + reason); 81 bool known = BrowserThread::GetCurrentThreadIdentifier(&thread_id);
82 if (!known || thread_id != BrowserThread::UI) {
83 BrowserThread::PostTask(BrowserThread::UI,
84 FROM_HERE,
85 base::Bind(&LogFailure,
86 extension,
87 api_name,
88 args,
89 reason,
90 profile));
91 } else {
92 extensions::ActivityLog* activity_log =
93 extensions::ActivityLog::GetInstance(profile);
94 if (activity_log->HasObservers(extension))
95 activity_log->LogBlockedAction(extension,
96 api_name,
97 args,
98 reason);
80 } 99 }
81 } 100 }
82 101
102
83 // Separate copy of ExtensionAPI used for IO thread extension functions. We need 103 // Separate copy of ExtensionAPI used for IO thread extension functions. We need
84 // this because ExtensionAPI has mutable data. It should be possible to remove 104 // this because ExtensionAPI has mutable data. It should be possible to remove
85 // this once all the extension APIs are updated to the feature system. 105 // this once all the extension APIs are updated to the feature system.
86 struct Static { 106 struct Static {
87 Static() 107 Static()
88 : api(extensions::ExtensionAPI::CreateWithDefaultConfiguration()) { 108 : api(extensions::ExtensionAPI::CreateWithDefaultConfiguration()) {
89 } 109 }
90 scoped_ptr<extensions::ExtensionAPI> api; 110 scoped_ptr<extensions::ExtensionAPI> api;
91 }; 111 };
92 base::LazyInstance<Static> g_global_io_data = LAZY_INSTANCE_INITIALIZER; 112 base::LazyInstance<Static> g_global_io_data = LAZY_INSTANCE_INITIALIZER;
(...skipping 29 matching lines...) Expand all
122 // static 142 // static
123 void ExtensionFunctionDispatcher::DispatchOnIOThread( 143 void ExtensionFunctionDispatcher::DispatchOnIOThread(
124 ExtensionInfoMap* extension_info_map, 144 ExtensionInfoMap* extension_info_map,
125 void* profile, 145 void* profile,
126 int render_process_id, 146 int render_process_id,
127 base::WeakPtr<ChromeRenderMessageFilter> ipc_sender, 147 base::WeakPtr<ChromeRenderMessageFilter> ipc_sender,
128 int routing_id, 148 int routing_id,
129 const ExtensionHostMsg_Request_Params& params) { 149 const ExtensionHostMsg_Request_Params& params) {
130 const Extension* extension = 150 const Extension* extension =
131 extension_info_map->extensions().GetByID(params.extension_id); 151 extension_info_map->extensions().GetByID(params.extension_id);
132 152 Profile* profile_cast = static_cast<Profile*>(profile);
133 scoped_refptr<ExtensionFunction> function( 153 scoped_refptr<ExtensionFunction> function(
134 CreateExtensionFunction(params, extension, render_process_id, 154 CreateExtensionFunction(params, extension, render_process_id,
135 extension_info_map->process_map(), 155 extension_info_map->process_map(),
136 g_global_io_data.Get().api.get(), 156 g_global_io_data.Get().api.get(),
137 profile, 157 profile,
138 ipc_sender, NULL, routing_id)); 158 ipc_sender, NULL, routing_id));
139 if (!function) { 159 if (!function) {
140 LogFailure(extension, params.name, kAccessDenied); 160 LogFailure(extension,
161 params.name,
162 params.arguments.DeepCopy(),
163 kAccessDenied,
164 profile_cast);
141 return; 165 return;
142 } 166 }
143 167
144 IOThreadExtensionFunction* function_io = 168 IOThreadExtensionFunction* function_io =
145 function->AsIOThreadExtensionFunction(); 169 function->AsIOThreadExtensionFunction();
146 if (!function_io) { 170 if (!function_io) {
147 NOTREACHED(); 171 NOTREACHED();
148 return; 172 return;
149 } 173 }
150 function_io->set_ipc_sender(ipc_sender, routing_id); 174 function_io->set_ipc_sender(ipc_sender, routing_id);
151 function_io->set_extension_info_map(extension_info_map); 175 function_io->set_extension_info_map(extension_info_map);
152 function->set_include_incognito( 176 function->set_include_incognito(
153 extension_info_map->IsIncognitoEnabled(extension->id())); 177 extension_info_map->IsIncognitoEnabled(extension->id()));
154 178
155 if (!CheckPermissions(function, extension, params, ipc_sender, routing_id)) { 179 if (!CheckPermissions(function, extension, params, ipc_sender, routing_id)) {
156 LogFailure(extension, params.name, kAccessDenied); 180 LogFailure(extension,
181 params.name,
182 params.arguments.DeepCopy(),
183 kAccessDenied,
184 profile_cast);
157 return; 185 return;
158 } 186 }
159 187
160 ExtensionsQuotaService* quota = extension_info_map->GetQuotaService(); 188 ExtensionsQuotaService* quota = extension_info_map->GetQuotaService();
161 std::string violation_error = quota->Assess(extension->id(), 189 std::string violation_error = quota->Assess(extension->id(),
162 function, 190 function,
163 &params.arguments, 191 &params.arguments,
164 base::TimeTicks::Now()); 192 base::TimeTicks::Now());
165 if (violation_error.empty()) { 193 if (violation_error.empty()) {
194 LogSuccess(extension,
195 params.name,
196 params.arguments.DeepCopy(),
197 profile_cast);
166 function->Run(); 198 function->Run();
167 LogSuccess(extension, params);
168 } else { 199 } else {
200 LogFailure(extension,
201 params.name,
202 params.arguments.DeepCopy(),
203 kQuotaExceeded,
204 profile_cast);
169 function->OnQuotaExceeded(violation_error); 205 function->OnQuotaExceeded(violation_error);
170 LogFailure(extension, params.name, kQuotaExceeded);
171 } 206 }
172 } 207 }
173 208
174 ExtensionFunctionDispatcher::ExtensionFunctionDispatcher(Profile* profile, 209 ExtensionFunctionDispatcher::ExtensionFunctionDispatcher(Profile* profile,
175 Delegate* delegate) 210 Delegate* delegate)
176 : profile_(profile), 211 : profile_(profile),
177 delegate_(delegate) { 212 delegate_(delegate) {
178 } 213 }
179 214
180 ExtensionFunctionDispatcher::~ExtensionFunctionDispatcher() { 215 ExtensionFunctionDispatcher::~ExtensionFunctionDispatcher() {
(...skipping 17 matching lines...) Expand all
198 params.source_url)); 233 params.source_url));
199 234
200 scoped_refptr<ExtensionFunction> function( 235 scoped_refptr<ExtensionFunction> function(
201 CreateExtensionFunction(params, extension, 236 CreateExtensionFunction(params, extension,
202 render_view_host->GetProcess()->GetID(), 237 render_view_host->GetProcess()->GetID(),
203 *(service->process_map()), 238 *(service->process_map()),
204 extensions::ExtensionAPI::GetSharedInstance(), 239 extensions::ExtensionAPI::GetSharedInstance(),
205 profile(), render_view_host, render_view_host, 240 profile(), render_view_host, render_view_host,
206 render_view_host->GetRoutingID())); 241 render_view_host->GetRoutingID()));
207 if (!function) { 242 if (!function) {
208 LogFailure(extension, params.name, kAccessDenied); 243 LogFailure(extension,
244 params.name,
245 params.arguments.DeepCopy(),
246 kAccessDenied,
247 profile());
209 return; 248 return;
210 } 249 }
211 250
212 UIThreadExtensionFunction* function_ui = 251 UIThreadExtensionFunction* function_ui =
213 function->AsUIThreadExtensionFunction(); 252 function->AsUIThreadExtensionFunction();
214 if (!function_ui) { 253 if (!function_ui) {
215 NOTREACHED(); 254 NOTREACHED();
216 return; 255 return;
217 } 256 }
218 function_ui->set_dispatcher(AsWeakPtr()); 257 function_ui->set_dispatcher(AsWeakPtr());
219 function_ui->set_profile(profile_); 258 function_ui->set_profile(profile_);
220 function->set_include_incognito(service->CanCrossIncognito(extension)); 259 function->set_include_incognito(service->CanCrossIncognito(extension));
221 260
222 if (!CheckPermissions(function, extension, params, render_view_host, 261 if (!CheckPermissions(function, extension, params, render_view_host,
223 render_view_host->GetRoutingID())) { 262 render_view_host->GetRoutingID())) {
224 LogFailure(extension, params.name, kAccessDenied); 263 LogFailure(extension,
264 params.name,
265 params.arguments.DeepCopy(),
266 kAccessDenied,
267 profile());
225 return; 268 return;
226 } 269 }
227 270
228 ExtensionsQuotaService* quota = service->quota_service(); 271 ExtensionsQuotaService* quota = service->quota_service();
229 std::string violation_error = quota->Assess(extension->id(), 272 std::string violation_error = quota->Assess(extension->id(),
230 function, 273 function,
231 &params.arguments, 274 &params.arguments,
232 base::TimeTicks::Now()); 275 base::TimeTicks::Now());
233 if (violation_error.empty()) { 276 if (violation_error.empty()) {
234 // See crbug.com/39178. 277 // See crbug.com/39178.
235 ExternalProtocolHandler::PermitLaunchUrl(); 278 ExternalProtocolHandler::PermitLaunchUrl();
236 279 LogSuccess(extension, params.name, params.arguments.DeepCopy(), profile());
237 function->Run(); 280 function->Run();
238 LogSuccess(extension, params);
239 } else { 281 } else {
282 LogFailure(extension,
283 params.name,
284 params.arguments.DeepCopy(),
285 kQuotaExceeded,
286 profile());
240 function->OnQuotaExceeded(violation_error); 287 function->OnQuotaExceeded(violation_error);
241 LogFailure(extension, params.name, kQuotaExceeded);
242 } 288 }
243 289
244 // Note: do not access |this| after this point. We may have been deleted 290 // Note: do not access |this| after this point. We may have been deleted
245 // if function->Run() ended up closing the tab that owns us. 291 // if function->Run() ended up closing the tab that owns us.
246 292
247 // Check if extension was uninstalled by management.uninstall. 293 // Check if extension was uninstalled by management.uninstall.
248 if (!service->extensions()->GetByID(params.extension_id)) 294 if (!service->extensions()->GetByID(params.extension_id))
249 return; 295 return;
250 296
251 // We only adjust the keepalive count for UIThreadExtensionFunction for 297 // We only adjust the keepalive count for UIThreadExtensionFunction for
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
323 } 369 }
324 370
325 // static 371 // static
326 void ExtensionFunctionDispatcher::SendAccessDenied( 372 void ExtensionFunctionDispatcher::SendAccessDenied(
327 IPC::Sender* ipc_sender, int routing_id, int request_id) { 373 IPC::Sender* ipc_sender, int routing_id, int request_id) {
328 ListValue empty_list; 374 ListValue empty_list;
329 ipc_sender->Send(new ExtensionMsg_Response( 375 ipc_sender->Send(new ExtensionMsg_Response(
330 routing_id, request_id, false, empty_list, 376 routing_id, request_id, false, empty_list,
331 "Access to extension API denied.")); 377 "Access to extension API denied."));
332 } 378 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698