OLD | NEW |
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 "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/json/json_string_value_serializer.h" | 8 #include "base/json/json_string_value_serializer.h" |
9 #include "base/lazy_instance.h" | 9 #include "base/lazy_instance.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
(...skipping 28 matching lines...) Expand all Loading... |
39 #include "third_party/WebKit/Source/WebKit/chromium/public/WebSecurityOrigin.h" | 39 #include "third_party/WebKit/Source/WebKit/chromium/public/WebSecurityOrigin.h" |
40 #include "webkit/glue/resource_type.h" | 40 #include "webkit/glue/resource_type.h" |
41 | 41 |
42 using extensions::Extension; | 42 using extensions::Extension; |
43 using extensions::ExtensionAPI; | 43 using extensions::ExtensionAPI; |
44 using content::RenderViewHost; | 44 using content::RenderViewHost; |
45 using WebKit::WebSecurityOrigin; | 45 using WebKit::WebSecurityOrigin; |
46 | 46 |
47 namespace { | 47 namespace { |
48 | 48 |
49 void LogSuccess(const Extension* extension, | 49 void LogSuccess(const std::string& extension_id, |
50 const std::string& api_name, | 50 const std::string& api_name, |
51 scoped_ptr<ListValue> args, | 51 scoped_ptr<ListValue> args, |
52 Profile* profile) { | 52 Profile* profile) { |
53 // The ActivityLog can only be accessed from the main (UI) thread. If we're | 53 // The ActivityLog can only be accessed from the main (UI) thread. If we're |
54 // running on the wrong thread, re-dispatch from the main thread. | 54 // running on the wrong thread, re-dispatch from the main thread. |
55 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { | 55 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { |
56 BrowserThread::PostTask(BrowserThread::UI, | 56 BrowserThread::PostTask(BrowserThread::UI, |
57 FROM_HERE, | 57 FROM_HERE, |
58 base::Bind(&LogSuccess, | 58 base::Bind(&LogSuccess, |
59 extension, | 59 extension_id, |
60 api_name, | 60 api_name, |
61 base::Passed(&args), | 61 base::Passed(&args), |
62 profile)); | 62 profile)); |
63 } else { | 63 } else { |
64 extensions::ActivityLog* activity_log = | 64 extensions::ActivityLog* activity_log = |
65 extensions::ActivityLog::GetInstance(profile); | 65 extensions::ActivityLog::GetInstance(profile); |
66 activity_log->LogAPIAction(extension, api_name, args.get(), std::string()); | 66 activity_log->LogAPIAction( |
| 67 extension_id, api_name, args.get(), std::string()); |
67 } | 68 } |
68 } | 69 } |
69 | 70 |
70 void LogFailure(const Extension* extension, | 71 void LogFailure(const std::string& extension_id, |
71 const std::string& api_name, | 72 const std::string& api_name, |
72 scoped_ptr<ListValue> args, | 73 scoped_ptr<ListValue> args, |
73 extensions::BlockedAction::Reason reason, | 74 extensions::BlockedAction::Reason reason, |
74 Profile* profile) { | 75 Profile* profile) { |
75 // The ActivityLog can only be accessed from the main (UI) thread. If we're | 76 // The ActivityLog can only be accessed from the main (UI) thread. If we're |
76 // running on the wrong thread, re-dispatch from the main thread. | 77 // running on the wrong thread, re-dispatch from the main thread. |
77 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { | 78 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { |
78 BrowserThread::PostTask(BrowserThread::UI, | 79 BrowserThread::PostTask(BrowserThread::UI, |
79 FROM_HERE, | 80 FROM_HERE, |
80 base::Bind(&LogFailure, | 81 base::Bind(&LogFailure, |
81 extension, | 82 extension_id, |
82 api_name, | 83 api_name, |
83 base::Passed(&args), | 84 base::Passed(&args), |
84 reason, | 85 reason, |
85 profile)); | 86 profile)); |
86 } else { | 87 } else { |
87 extensions::ActivityLog* activity_log = | 88 extensions::ActivityLog* activity_log = |
88 extensions::ActivityLog::GetInstance(profile); | 89 extensions::ActivityLog::GetInstance(profile); |
89 activity_log->LogBlockedAction( | 90 activity_log->LogBlockedAction( |
90 extension, api_name, args.get(), reason, std::string()); | 91 extension_id, api_name, args.get(), reason, std::string()); |
91 } | 92 } |
92 } | 93 } |
93 | 94 |
94 | 95 |
95 // Separate copy of ExtensionAPI used for IO thread extension functions. We need | 96 // Separate copy of ExtensionAPI used for IO thread extension functions. We need |
96 // this because ExtensionAPI has mutable data. It should be possible to remove | 97 // this because ExtensionAPI has mutable data. It should be possible to remove |
97 // this once all the extension APIs are updated to the feature system. | 98 // this once all the extension APIs are updated to the feature system. |
98 struct Static { | 99 struct Static { |
99 Static() | 100 Static() |
100 : api(extensions::ExtensionAPI::CreateWithDefaultConfiguration()) { | 101 : api(extensions::ExtensionAPI::CreateWithDefaultConfiguration()) { |
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
252 params.request_id)); | 253 params.request_id)); |
253 | 254 |
254 scoped_refptr<ExtensionFunction> function( | 255 scoped_refptr<ExtensionFunction> function( |
255 CreateExtensionFunction(params, extension, render_process_id, | 256 CreateExtensionFunction(params, extension, render_process_id, |
256 extension_info_map->process_map(), | 257 extension_info_map->process_map(), |
257 g_global_io_data.Get().api.get(), | 258 g_global_io_data.Get().api.get(), |
258 profile, callback)); | 259 profile, callback)); |
259 scoped_ptr<ListValue> args(params.arguments.DeepCopy()); | 260 scoped_ptr<ListValue> args(params.arguments.DeepCopy()); |
260 | 261 |
261 if (!function.get()) { | 262 if (!function.get()) { |
262 LogFailure(extension, | 263 LogFailure(extension->id(), |
263 params.name, | 264 params.name, |
264 args.Pass(), | 265 args.Pass(), |
265 extensions::BlockedAction::ACCESS_DENIED, | 266 extensions::BlockedAction::ACCESS_DENIED, |
266 profile_cast); | 267 profile_cast); |
267 return; | 268 return; |
268 } | 269 } |
269 | 270 |
270 IOThreadExtensionFunction* function_io = | 271 IOThreadExtensionFunction* function_io = |
271 function->AsIOThreadExtensionFunction(); | 272 function->AsIOThreadExtensionFunction(); |
272 if (!function_io) { | 273 if (!function_io) { |
273 NOTREACHED(); | 274 NOTREACHED(); |
274 return; | 275 return; |
275 } | 276 } |
276 function_io->set_ipc_sender(ipc_sender); | 277 function_io->set_ipc_sender(ipc_sender); |
277 function_io->set_extension_info_map(extension_info_map); | 278 function_io->set_extension_info_map(extension_info_map); |
278 function->set_include_incognito( | 279 function->set_include_incognito( |
279 extension_info_map->IsIncognitoEnabled(extension->id())); | 280 extension_info_map->IsIncognitoEnabled(extension->id())); |
280 | 281 |
281 if (!CheckPermissions(function.get(), extension, params, callback)) { | 282 if (!CheckPermissions(function.get(), extension, params, callback)) { |
282 LogFailure(extension, | 283 LogFailure(extension->id(), |
283 params.name, | 284 params.name, |
284 args.Pass(), | 285 args.Pass(), |
285 extensions::BlockedAction::ACCESS_DENIED, | 286 extensions::BlockedAction::ACCESS_DENIED, |
286 profile_cast); | 287 profile_cast); |
287 return; | 288 return; |
288 } | 289 } |
289 | 290 |
290 ExtensionsQuotaService* quota = extension_info_map->GetQuotaService(); | 291 ExtensionsQuotaService* quota = extension_info_map->GetQuotaService(); |
291 std::string violation_error = quota->Assess(extension->id(), | 292 std::string violation_error = quota->Assess(extension->id(), |
292 function.get(), | 293 function.get(), |
293 ¶ms.arguments, | 294 ¶ms.arguments, |
294 base::TimeTicks::Now()); | 295 base::TimeTicks::Now()); |
295 if (violation_error.empty()) { | 296 if (violation_error.empty()) { |
296 LogSuccess(extension, | 297 LogSuccess(extension->id(), |
297 params.name, | 298 params.name, |
298 args.Pass(), | 299 args.Pass(), |
299 profile_cast); | 300 profile_cast); |
300 function->Run(); | 301 function->Run(); |
301 } else { | 302 } else { |
302 LogFailure(extension, | 303 LogFailure(extension->id(), |
303 params.name, | 304 params.name, |
304 args.Pass(), | 305 args.Pass(), |
305 extensions::BlockedAction::QUOTA_EXCEEDED, | 306 extensions::BlockedAction::QUOTA_EXCEEDED, |
306 profile_cast); | 307 profile_cast); |
307 function->OnQuotaExceeded(violation_error); | 308 function->OnQuotaExceeded(violation_error); |
308 } | 309 } |
309 } | 310 } |
310 | 311 |
311 ExtensionFunctionDispatcher::ExtensionFunctionDispatcher(Profile* profile, | 312 ExtensionFunctionDispatcher::ExtensionFunctionDispatcher(Profile* profile, |
312 Delegate* delegate) | 313 Delegate* delegate) |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
357 | 358 |
358 scoped_refptr<ExtensionFunction> function( | 359 scoped_refptr<ExtensionFunction> function( |
359 CreateExtensionFunction(params, extension, | 360 CreateExtensionFunction(params, extension, |
360 render_view_host->GetProcess()->GetID(), | 361 render_view_host->GetProcess()->GetID(), |
361 *(service->process_map()), | 362 *(service->process_map()), |
362 extensions::ExtensionAPI::GetSharedInstance(), | 363 extensions::ExtensionAPI::GetSharedInstance(), |
363 profile(), callback)); | 364 profile(), callback)); |
364 scoped_ptr<ListValue> args(params.arguments.DeepCopy()); | 365 scoped_ptr<ListValue> args(params.arguments.DeepCopy()); |
365 | 366 |
366 if (!function.get()) { | 367 if (!function.get()) { |
367 LogFailure(extension, | 368 LogFailure(extension->id(), |
368 params.name, | 369 params.name, |
369 args.Pass(), | 370 args.Pass(), |
370 extensions::BlockedAction::ACCESS_DENIED, | 371 extensions::BlockedAction::ACCESS_DENIED, |
371 profile()); | 372 profile()); |
372 return; | 373 return; |
373 } | 374 } |
374 | 375 |
375 UIThreadExtensionFunction* function_ui = | 376 UIThreadExtensionFunction* function_ui = |
376 function->AsUIThreadExtensionFunction(); | 377 function->AsUIThreadExtensionFunction(); |
377 if (!function_ui) { | 378 if (!function_ui) { |
378 NOTREACHED(); | 379 NOTREACHED(); |
379 return; | 380 return; |
380 } | 381 } |
381 function_ui->SetRenderViewHost(render_view_host); | 382 function_ui->SetRenderViewHost(render_view_host); |
382 function_ui->set_dispatcher(AsWeakPtr()); | 383 function_ui->set_dispatcher(AsWeakPtr()); |
383 function_ui->set_profile(profile_); | 384 function_ui->set_profile(profile_); |
384 function->set_include_incognito(service->CanCrossIncognito(extension)); | 385 function->set_include_incognito(service->CanCrossIncognito(extension)); |
385 | 386 |
386 if (!CheckPermissions(function.get(), extension, params, callback)) { | 387 if (!CheckPermissions(function.get(), extension, params, callback)) { |
387 LogFailure(extension, | 388 LogFailure(extension->id(), |
388 params.name, | 389 params.name, |
389 args.Pass(), | 390 args.Pass(), |
390 extensions::BlockedAction::ACCESS_DENIED, | 391 extensions::BlockedAction::ACCESS_DENIED, |
391 profile()); | 392 profile()); |
392 return; | 393 return; |
393 } | 394 } |
394 | 395 |
395 ExtensionsQuotaService* quota = service->quota_service(); | 396 ExtensionsQuotaService* quota = service->quota_service(); |
396 std::string violation_error = quota->Assess(extension->id(), | 397 std::string violation_error = quota->Assess(extension->id(), |
397 function.get(), | 398 function.get(), |
398 ¶ms.arguments, | 399 ¶ms.arguments, |
399 base::TimeTicks::Now()); | 400 base::TimeTicks::Now()); |
400 if (violation_error.empty()) { | 401 if (violation_error.empty()) { |
401 // See crbug.com/39178. | 402 // See crbug.com/39178. |
402 ExternalProtocolHandler::PermitLaunchUrl(); | 403 ExternalProtocolHandler::PermitLaunchUrl(); |
403 LogSuccess(extension, params.name, args.Pass(), profile()); | 404 LogSuccess(extension->id(), params.name, args.Pass(), profile()); |
404 function->Run(); | 405 function->Run(); |
405 } else { | 406 } else { |
406 LogFailure(extension, | 407 LogFailure(extension->id(), |
407 params.name, | 408 params.name, |
408 args.Pass(), | 409 args.Pass(), |
409 extensions::BlockedAction::QUOTA_EXCEEDED, | 410 extensions::BlockedAction::QUOTA_EXCEEDED, |
410 profile()); | 411 profile()); |
411 function->OnQuotaExceeded(violation_error); | 412 function->OnQuotaExceeded(violation_error); |
412 } | 413 } |
413 | 414 |
414 // Note: do not access |this| after this point. We may have been deleted | 415 // Note: do not access |this| after this point. We may have been deleted |
415 // if function->Run() ended up closing the tab that owns us. | 416 // if function->Run() ended up closing the tab that owns us. |
416 | 417 |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
526 return function; | 527 return function; |
527 } | 528 } |
528 | 529 |
529 // static | 530 // static |
530 void ExtensionFunctionDispatcher::SendAccessDenied( | 531 void ExtensionFunctionDispatcher::SendAccessDenied( |
531 const ExtensionFunction::ResponseCallback& callback) { | 532 const ExtensionFunction::ResponseCallback& callback) { |
532 ListValue empty_list; | 533 ListValue empty_list; |
533 callback.Run(ExtensionFunction::FAILED, empty_list, | 534 callback.Run(ExtensionFunction::FAILED, empty_list, |
534 "Access to extension API denied."); | 535 "Access to extension API denied."); |
535 } | 536 } |
OLD | NEW |