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

Side by Side Diff: components/nacl/renderer/ppb_nacl_private_impl.cc

Issue 276423003: Pepper: Nexe downloading out of the trusted plugin. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebased Created 6 years, 7 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
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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 "components/nacl/renderer/ppb_nacl_private_impl.h" 5 #include "components/nacl/renderer/ppb_nacl_private_impl.h"
6 6
7 #include <numeric> 7 #include <numeric>
8 #include <string> 8 #include <string>
9 #include <vector> 9 #include <vector>
10 10
11 #include "base/bind.h" 11 #include "base/bind.h"
12 #include "base/bind_helpers.h" 12 #include "base/bind_helpers.h"
13 #include "base/command_line.h" 13 #include "base/command_line.h"
14 #include "base/containers/scoped_ptr_hash_map.h" 14 #include "base/containers/scoped_ptr_hash_map.h"
15 #include "base/cpu.h" 15 #include "base/cpu.h"
16 #include "base/lazy_instance.h" 16 #include "base/lazy_instance.h"
17 #include "base/logging.h" 17 #include "base/logging.h"
18 #include "base/rand_util.h" 18 #include "base/rand_util.h"
19 #include "components/nacl/common/nacl_host_messages.h" 19 #include "components/nacl/common/nacl_host_messages.h"
20 #include "components/nacl/common/nacl_messages.h" 20 #include "components/nacl/common/nacl_messages.h"
21 #include "components/nacl/common/nacl_nonsfi_util.h" 21 #include "components/nacl/common/nacl_nonsfi_util.h"
22 #include "components/nacl/common/nacl_switches.h" 22 #include "components/nacl/common/nacl_switches.h"
23 #include "components/nacl/common/nacl_types.h" 23 #include "components/nacl/common/nacl_types.h"
24 #include "components/nacl/renderer/file_downloader.h"
24 #include "components/nacl/renderer/histogram.h" 25 #include "components/nacl/renderer/histogram.h"
25 #include "components/nacl/renderer/json_manifest.h" 26 #include "components/nacl/renderer/json_manifest.h"
26 #include "components/nacl/renderer/manifest_downloader.h" 27 #include "components/nacl/renderer/manifest_downloader.h"
27 #include "components/nacl/renderer/manifest_service_channel.h" 28 #include "components/nacl/renderer/manifest_service_channel.h"
28 #include "components/nacl/renderer/nexe_load_manager.h" 29 #include "components/nacl/renderer/nexe_load_manager.h"
29 #include "components/nacl/renderer/pnacl_translation_resource_host.h" 30 #include "components/nacl/renderer/pnacl_translation_resource_host.h"
30 #include "components/nacl/renderer/progress_event.h" 31 #include "components/nacl/renderer/progress_event.h"
31 #include "components/nacl/renderer/sandbox_arch.h" 32 #include "components/nacl/renderer/sandbox_arch.h"
32 #include "components/nacl/renderer/trusted_plugin_channel.h" 33 #include "components/nacl/renderer/trusted_plugin_channel.h"
33 #include "content/public/common/content_client.h" 34 #include "content/public/common/content_client.h"
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after
248 bool result = PP_ToBool(manifest_service_.Quit(user_data_)); 249 bool result = PP_ToBool(manifest_service_.Quit(user_data_));
249 DCHECK(!result); 250 DCHECK(!result);
250 user_data_ = NULL; 251 user_data_ = NULL;
251 } 252 }
252 253
253 PPP_ManifestService manifest_service_; 254 PPP_ManifestService manifest_service_;
254 void* user_data_; 255 void* user_data_;
255 DISALLOW_COPY_AND_ASSIGN(ManifestServiceProxy); 256 DISALLOW_COPY_AND_ASSIGN(ManifestServiceProxy);
256 }; 257 };
257 258
259 blink::WebURLLoader* CreateWebURLLoader(const blink::WebDocument& document,
260 const GURL& gurl) {
261 blink::WebURLLoaderOptions options;
262 options.untrustedHTTP = true;
263
264 // Options settings here follow the original behavior in the trusted
265 // plugin and PepperURLLoaderHost.
266 if (document.securityOrigin().canRequest(gurl)) {
267 options.allowCredentials = true;
268 } else {
269 // Allow CORS.
270 options.crossOriginRequestPolicy =
271 blink::WebURLLoaderOptions::CrossOriginRequestPolicyUseAccessControl;
272 }
273 return document.frame()->createAssociatedURLLoader(options);
274 }
275
276 blink::WebURLRequest CreateWebURLRequest(const blink::WebDocument& document,
277 const GURL& gurl) {
278 blink::WebURLRequest request;
279 request.initialize();
280 request.setURL(gurl);
281 request.setFirstPartyForCookies(document.firstPartyForCookies());
282 return request;
283 }
284
258 // Launch NaCl's sel_ldr process. 285 // Launch NaCl's sel_ldr process.
259 void LaunchSelLdr(PP_Instance instance, 286 void LaunchSelLdr(PP_Instance instance,
260 PP_Bool main_service_runtime, 287 PP_Bool main_service_runtime,
261 const char* alleged_url, 288 const char* alleged_url,
262 PP_Bool uses_irt, 289 PP_Bool uses_irt,
263 PP_Bool uses_ppapi, 290 PP_Bool uses_ppapi,
264 PP_Bool uses_nonsfi_mode, 291 PP_Bool uses_nonsfi_mode,
265 PP_Bool enable_ppapi_dev, 292 PP_Bool enable_ppapi_dev,
266 PP_Bool enable_dyncode_syscalls, 293 PP_Bool enable_dyncode_syscalls,
267 PP_Bool enable_exception_handling, 294 PP_Bool enable_exception_handling,
(...skipping 393 matching lines...) Expand 10 before | Expand all | Expand 10 after
661 uint64_t loaded_bytes, 688 uint64_t loaded_bytes,
662 uint64_t total_bytes) { 689 uint64_t total_bytes) {
663 ProgressEvent event(event_type, 690 ProgressEvent event(event_type,
664 resource_url, 691 resource_url,
665 PP_ToBool(length_is_computable), 692 PP_ToBool(length_is_computable),
666 loaded_bytes, 693 loaded_bytes,
667 total_bytes); 694 total_bytes);
668 DispatchProgressEvent(instance, event); 695 DispatchProgressEvent(instance, event);
669 } 696 }
670 697
671 void NexeFileDidOpen(PP_Instance instance,
672 int32_t pp_error,
673 int32_t fd,
674 int32_t http_status,
675 int64_t nexe_bytes_read,
676 const char* url,
677 int64_t time_since_open) {
678 NexeLoadManager* load_manager = GetNexeLoadManager(instance);
679 if (load_manager) {
680 load_manager->NexeFileDidOpen(pp_error,
681 fd,
682 http_status,
683 nexe_bytes_read,
684 url,
685 time_since_open);
686 }
687 }
688
689 void ReportLoadSuccess(PP_Instance instance, 698 void ReportLoadSuccess(PP_Instance instance,
690 const char* url, 699 const char* url,
691 uint64_t loaded_bytes, 700 uint64_t loaded_bytes,
692 uint64_t total_bytes) { 701 uint64_t total_bytes) {
693 NexeLoadManager* load_manager = GetNexeLoadManager(instance); 702 NexeLoadManager* load_manager = GetNexeLoadManager(instance);
694 if (load_manager) 703 if (load_manager)
695 load_manager->ReportLoadSuccess(url, loaded_bytes, total_bytes); 704 load_manager->ReportLoadSuccess(url, loaded_bytes, total_bytes);
696 } 705 }
697 706
698 void ReportLoadError(PP_Instance instance, 707 void ReportLoadError(PP_Instance instance,
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after
883 struct PP_Var* out_data, 892 struct PP_Var* out_data,
884 base::Time start_time, 893 base::Time start_time,
885 PP_NaClError pp_nacl_error, 894 PP_NaClError pp_nacl_error,
886 const std::string& data); 895 const std::string& data);
887 896
888 void DownloadManifestToBuffer(PP_Instance instance, 897 void DownloadManifestToBuffer(PP_Instance instance,
889 struct PP_Var* out_data, 898 struct PP_Var* out_data,
890 struct PP_CompletionCallback callback) { 899 struct PP_CompletionCallback callback) {
891 nacl::NexeLoadManager* load_manager = GetNexeLoadManager(instance); 900 nacl::NexeLoadManager* load_manager = GetNexeLoadManager(instance);
892 DCHECK(load_manager); 901 DCHECK(load_manager);
893 if (!load_manager) { 902 content::PepperPluginInstance* plugin_instance =
903 content::PepperPluginInstance::Get(instance);
904 if (!load_manager || !plugin_instance) {
894 ppapi::PpapiGlobals::Get()->GetMainThreadMessageLoop()->PostTask( 905 ppapi::PpapiGlobals::Get()->GetMainThreadMessageLoop()->PostTask(
895 FROM_HERE, 906 FROM_HERE,
896 base::Bind(callback.func, callback.user_data, 907 base::Bind(callback.func, callback.user_data,
897 static_cast<int32_t>(PP_ERROR_FAILED))); 908 static_cast<int32_t>(PP_ERROR_FAILED)));
898 } 909 }
910 const blink::WebDocument& document =
911 plugin_instance->GetContainer()->element().document();
899 912
900 const GURL& gurl = load_manager->manifest_base_url(); 913 const GURL& gurl = load_manager->manifest_base_url();
901 914 scoped_ptr<blink::WebURLLoader> url_loader(
902 content::PepperPluginInstance* plugin_instance = 915 CreateWebURLLoader(document, gurl));
903 content::PepperPluginInstance::Get(instance); 916 blink::WebURLRequest request = CreateWebURLRequest(document, gurl);
904 blink::WebURLLoaderOptions options;
905 options.untrustedHTTP = true;
906
907 blink::WebSecurityOrigin security_origin =
908 plugin_instance->GetContainer()->element().document().securityOrigin();
909 // Options settings here follow the original behavior in the trusted
910 // plugin and PepperURLLoaderHost.
911 if (security_origin.canRequest(gurl)) {
912 options.allowCredentials = true;
913 } else {
914 // Allow CORS.
915 options.crossOriginRequestPolicy =
916 blink::WebURLLoaderOptions::CrossOriginRequestPolicyUseAccessControl;
917 }
918
919 blink::WebFrame* frame =
920 plugin_instance->GetContainer()->element().document().frame();
921 blink::WebURLLoader* url_loader = frame->createAssociatedURLLoader(options);
922 blink::WebURLRequest request;
923 request.initialize();
924 request.setURL(gurl);
925 request.setFirstPartyForCookies(frame->document().firstPartyForCookies());
926 917
927 // ManifestDownloader deletes itself after invoking the callback. 918 // ManifestDownloader deletes itself after invoking the callback.
928 ManifestDownloader* client = new ManifestDownloader( 919 ManifestDownloader* manifest_downloader = new ManifestDownloader(
920 url_loader.Pass(),
929 load_manager->is_installed(), 921 load_manager->is_installed(),
930 base::Bind(DownloadManifestToBufferCompletion, 922 base::Bind(DownloadManifestToBufferCompletion,
931 instance, callback, out_data, base::Time::Now())); 923 instance, callback, out_data, base::Time::Now()));
932 url_loader->loadAsynchronously(request, client); 924 manifest_downloader->Load(request);
933 } 925 }
934 926
935 void DownloadManifestToBufferCompletion(PP_Instance instance, 927 void DownloadManifestToBufferCompletion(PP_Instance instance,
936 struct PP_CompletionCallback callback, 928 struct PP_CompletionCallback callback,
937 struct PP_Var* out_data, 929 struct PP_Var* out_data,
938 base::Time start_time, 930 base::Time start_time,
939 PP_NaClError pp_nacl_error, 931 PP_NaClError pp_nacl_error,
940 const std::string& data) { 932 const std::string& data) {
941 base::TimeDelta download_time = base::Time::Now() - start_time; 933 base::TimeDelta download_time = base::Time::Now() - start_time;
942 HistogramTimeSmall("NaCl.Perf.StartupTime.ManifestDownload", 934 HistogramTimeSmall("NaCl.Perf.StartupTime.ManifestDownload",
(...skipping 303 matching lines...) Expand 10 before | Expand all | Expand 10 after
1246 } 1238 }
1247 1239
1248 void PostMessageToJavaScript(PP_Instance instance, const char* message) { 1240 void PostMessageToJavaScript(PP_Instance instance, const char* message) {
1249 ppapi::PpapiGlobals::Get()->GetMainThreadMessageLoop()->PostTask( 1241 ppapi::PpapiGlobals::Get()->GetMainThreadMessageLoop()->PostTask(
1250 FROM_HERE, 1242 FROM_HERE,
1251 base::Bind(&PostMessageToJavaScriptMainThread, 1243 base::Bind(&PostMessageToJavaScriptMainThread,
1252 instance, 1244 instance,
1253 std::string(message))); 1245 std::string(message)));
1254 } 1246 }
1255 1247
1248 // Encapsulates some of the state for a call to DownloadNexe to prevent
1249 // argument lists from getting too long.
1250 struct DownloadNexeRequest {
1251 PP_Instance instance;
1252 const char* url;
bbudge 2014/05/14 21:46:18 This pointer makes me very uneasy. It seems it cou
teravest 2014/05/15 19:12:21 Done.
1253 PP_CompletionCallback callback;
1254 base::Time start_time;
1255 };
1256
1257 // A utility class to ensure that we don't send progress events more often than
1258 // every 10ms for a given file.
1259 class DownloadProgressTracker {
bbudge 2014/05/14 21:46:18 How about ProgressEventRateLimiter?
teravest 2014/05/15 19:12:21 Done.
1260 public:
1261 explicit DownloadProgressTracker(PP_Instance instance) : instance_(instance) {
1262 }
1263
1264 void ReportProgress(const std::string& url,
1265 int64_t total_bytes_received,
1266 int64_t total_bytes_to_be_received) {
1267 base::Time now = base::Time::Now();
1268 if (now - last_event_ > base::TimeDelta::FromMilliseconds(10)) {
1269 DispatchProgressEvent(instance_,
1270 ProgressEvent(PP_NACL_EVENT_PROGRESS,
1271 url,
1272 total_bytes_to_be_received >= 0,
1273 total_bytes_received,
1274 total_bytes_to_be_received));
1275 last_event_ = now;
1276 }
1277 }
1278
1279 private:
1280 PP_Instance instance_;
1281 base::Time last_event_;
1282 };
1283
1284 void DownloadNexeCompletion(const DownloadNexeRequest& request,
1285 scoped_ptr<blink::WebURLLoader> loader,
1286 base::PlatformFile target_file,
1287 PP_FileHandle* out_handle,
1288 FileDownloader::Status status,
1289 int http_status);
1290
1291 void DownloadNexe(PP_Instance instance,
1292 const char* url,
1293 PP_FileHandle* out_handle,
1294 PP_CompletionCallback callback) {
1295 CHECK(url);
1296 CHECK(out_handle);
1297 DownloadNexeRequest request;
1298 request.instance = instance;
1299 request.url = url;
1300 request.callback = callback;
1301 request.start_time = base::Time::Now();
1302
1303 // Try the fast path for retrieving the file first.
1304 uint64_t file_token_lo = 0;
1305 uint64_t file_token_hi = 0;
1306 PP_FileHandle file_handle = OpenNaClExecutable(instance,
1307 url,
1308 &file_token_lo,
1309 &file_token_hi);
1310 if (file_handle != PP_kInvalidFileHandle) {
1311 DownloadNexeCompletion(request,
1312 scoped_ptr<blink::WebURLLoader>(),
1313 file_handle,
1314 out_handle,
1315 FileDownloader::SUCCESS,
1316 200);
1317 return;
1318 }
1319
1320 // The fast path didn't work, we'll fetch the file using URLLoader and write
1321 // it to local storage.
1322 base::PlatformFile target_file = CreateTemporaryFile(instance);
1323 GURL gurl(url);
1324
1325 content::PepperPluginInstance* plugin_instance =
1326 content::PepperPluginInstance::Get(instance);
1327 if (!plugin_instance) {
1328 ppapi::PpapiGlobals::Get()->GetMainThreadMessageLoop()->PostTask(
1329 FROM_HERE,
1330 base::Bind(callback.func, callback.user_data,
1331 static_cast<int32_t>(PP_ERROR_FAILED)));
1332 }
1333 const blink::WebDocument& document =
1334 plugin_instance->GetContainer()->element().document();
1335 scoped_ptr<blink::WebURLLoader> url_loader(
1336 CreateWebURLLoader(document, gurl));
1337 blink::WebURLRequest url_request = CreateWebURLRequest(document, gurl);
1338
1339 DownloadProgressTracker* tracker = new DownloadProgressTracker(instance);
1340
1341 // FileDownloader deletes itself after invoking the callback.
1342 FileDownloader* file_downloader = new FileDownloader(
1343 url_loader.Pass(),
1344 target_file,
1345 base::Bind(&DownloadNexeCompletion, request, base::Passed(&url_loader),
1346 target_file, out_handle),
bbudge 2014/05/14 21:46:18 In this case, request's 'url' field likely will be
teravest 2014/05/15 19:12:21 Changed to std::string.
1347 base::Bind(&DownloadProgressTracker::ReportProgress,
1348 base::Owned(tracker), url));
1349 file_downloader->Load(url_request);
1350 }
1351
1352 void DownloadNexeCompletion(const DownloadNexeRequest& request,
1353 scoped_ptr<blink::WebURLLoader> loader,
1354 base::PlatformFile target_file,
1355 PP_FileHandle* out_handle,
1356 FileDownloader::Status status,
1357 int http_status) {
1358 int32_t pp_error;
1359 switch (status) {
1360 case FileDownloader::SUCCESS:
1361 *out_handle = target_file;
1362 pp_error = PP_OK;
1363 break;
1364 case FileDownloader::ACCESS_DENIED:
1365 pp_error = PP_ERROR_NOACCESS;
1366 break;
1367 case FileDownloader::FAILED:
1368 pp_error = PP_ERROR_FAILED;
1369 break;
1370 default:
1371 NOTREACHED();
1372 return;
1373 }
1374
1375 int64_t bytes_read = -1;
1376 if (pp_error == PP_OK && target_file != base::kInvalidPlatformFileValue) {
1377 base::PlatformFileInfo info;
1378 if (GetPlatformFileInfo(target_file, &info))
1379 bytes_read = info.size;
1380 }
1381
1382 if (bytes_read == -1) {
1383 base::ClosePlatformFile(target_file);
1384 pp_error = PP_ERROR_FAILED;
1385 }
1386
1387 base::TimeDelta download_time = base::Time::Now() - request.start_time;
1388
1389 NexeLoadManager* load_manager = GetNexeLoadManager(request.instance);
1390 if (load_manager) {
1391 load_manager->NexeFileDidOpen(pp_error,
1392 target_file,
1393 http_status,
1394 bytes_read,
1395 request.url,
1396 download_time);
1397 }
1398
1399 request.callback.func(request.callback.user_data, pp_error);
1400 }
1401
1256 const PPB_NaCl_Private nacl_interface = { 1402 const PPB_NaCl_Private nacl_interface = {
1257 &LaunchSelLdr, 1403 &LaunchSelLdr,
1258 &StartPpapiProxy, 1404 &StartPpapiProxy,
1259 &UrandomFD, 1405 &UrandomFD,
1260 &Are3DInterfacesDisabled, 1406 &Are3DInterfacesDisabled,
1261 &BrokerDuplicateHandle, 1407 &BrokerDuplicateHandle,
1262 &GetReadonlyPnaclFD, 1408 &GetReadonlyPnaclFD,
1263 &CreateTemporaryFile, 1409 &CreateTemporaryFile,
1264 &GetNumberOfProcessors, 1410 &GetNumberOfProcessors,
1265 &PPIsNonSFIModeEnabled, 1411 &PPIsNonSFIModeEnabled,
1266 &GetNexeFd, 1412 &GetNexeFd,
1267 &ReportTranslationFinished, 1413 &ReportTranslationFinished,
1268 &OpenNaClExecutable, 1414 &OpenNaClExecutable,
1269 &DispatchEvent, 1415 &DispatchEvent,
1270 &NexeFileDidOpen,
1271 &ReportLoadSuccess, 1416 &ReportLoadSuccess,
1272 &ReportLoadError, 1417 &ReportLoadError,
1273 &ReportLoadAbort, 1418 &ReportLoadAbort,
1274 &NexeDidCrash, 1419 &NexeDidCrash,
1275 &InstanceCreated, 1420 &InstanceCreated,
1276 &InstanceDestroyed, 1421 &InstanceDestroyed,
1277 &NaClDebugEnabledForURL, 1422 &NaClDebugEnabledForURL,
1278 &GetSandboxArch, 1423 &GetSandboxArch,
1279 &LogToConsole, 1424 &LogToConsole,
1280 &GetNaClReadyState, 1425 &GetNaClReadyState,
(...skipping 11 matching lines...) Expand all
1292 &GetManifestURLArgument, 1437 &GetManifestURLArgument,
1293 &DevInterfacesEnabled, 1438 &DevInterfacesEnabled,
1294 &DownloadManifestToBuffer, 1439 &DownloadManifestToBuffer,
1295 &CreatePNaClManifest, 1440 &CreatePNaClManifest,
1296 &CreateJsonManifest, 1441 &CreateJsonManifest,
1297 &DestroyManifest, 1442 &DestroyManifest,
1298 &ManifestGetProgramURL, 1443 &ManifestGetProgramURL,
1299 &ManifestResolveKey, 1444 &ManifestResolveKey,
1300 &GetPNaClResourceInfo, 1445 &GetPNaClResourceInfo,
1301 &GetCpuFeatureAttrs, 1446 &GetCpuFeatureAttrs,
1302 &PostMessageToJavaScript 1447 &PostMessageToJavaScript,
1448 &DownloadNexe
1303 }; 1449 };
1304 1450
1305 } // namespace 1451 } // namespace
1306 1452
1307 const PPB_NaCl_Private* GetNaClPrivateInterface() { 1453 const PPB_NaCl_Private* GetNaClPrivateInterface() {
1308 return &nacl_interface; 1454 return &nacl_interface;
1309 } 1455 }
1310 1456
1311 } // namespace nacl 1457 } // namespace nacl
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698