| 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) { | 262 if (!function) { |
| 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, extension, params, callback)) { | 282 if (!CheckPermissions(function, 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, | 293 function, |
| 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) { | 367 if (!function) { |
| 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, extension, params, callback)) { | 387 if (!CheckPermissions(function, 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, | 398 function, |
| 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 |