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