Chromium Code Reviews| Index: components/nacl/renderer/ppb_nacl_private_impl.cc |
| diff --git a/components/nacl/renderer/ppb_nacl_private_impl.cc b/components/nacl/renderer/ppb_nacl_private_impl.cc |
| index 429d99e74c7c76225517bb868889fa5ae2ebc32c..5d9ffa9b4dff035c3928727ed81d5f5675c12935 100644 |
| --- a/components/nacl/renderer/ppb_nacl_private_impl.cc |
| +++ b/components/nacl/renderer/ppb_nacl_private_impl.cc |
| @@ -21,6 +21,7 @@ |
| #include "components/nacl/common/nacl_nonsfi_util.h" |
| #include "components/nacl/common/nacl_switches.h" |
| #include "components/nacl/common/nacl_types.h" |
| +#include "components/nacl/renderer/file_downloader.h" |
| #include "components/nacl/renderer/histogram.h" |
| #include "components/nacl/renderer/json_manifest.h" |
| #include "components/nacl/renderer/manifest_downloader.h" |
| @@ -255,6 +256,32 @@ class ManifestServiceProxy : public ManifestServiceChannel::Delegate { |
| DISALLOW_COPY_AND_ASSIGN(ManifestServiceProxy); |
| }; |
| +blink::WebURLLoader* CreateWebURLLoader(const blink::WebDocument& document, |
| + const GURL& gurl) { |
| + blink::WebURLLoaderOptions options; |
| + options.untrustedHTTP = true; |
| + |
| + // Options settings here follow the original behavior in the trusted |
| + // plugin and PepperURLLoaderHost. |
| + if (document.securityOrigin().canRequest(gurl)) { |
| + options.allowCredentials = true; |
| + } else { |
| + // Allow CORS. |
| + options.crossOriginRequestPolicy = |
| + blink::WebURLLoaderOptions::CrossOriginRequestPolicyUseAccessControl; |
| + } |
| + return document.frame()->createAssociatedURLLoader(options); |
| +} |
| + |
| +blink::WebURLRequest CreateWebURLRequest(const blink::WebDocument& document, |
| + const GURL& gurl) { |
| + blink::WebURLRequest request; |
| + request.initialize(); |
| + request.setURL(gurl); |
| + request.setFirstPartyForCookies(document.firstPartyForCookies()); |
| + return request; |
| +} |
| + |
| // Launch NaCl's sel_ldr process. |
| void LaunchSelLdr(PP_Instance instance, |
| PP_Bool main_service_runtime, |
| @@ -668,24 +695,6 @@ void DispatchEvent(PP_Instance instance, |
| DispatchProgressEvent(instance, event); |
| } |
| -void NexeFileDidOpen(PP_Instance instance, |
| - int32_t pp_error, |
| - int32_t fd, |
| - int32_t http_status, |
| - int64_t nexe_bytes_read, |
| - const char* url, |
| - int64_t time_since_open) { |
| - NexeLoadManager* load_manager = GetNexeLoadManager(instance); |
| - if (load_manager) { |
| - load_manager->NexeFileDidOpen(pp_error, |
| - fd, |
| - http_status, |
| - nexe_bytes_read, |
| - url, |
| - time_since_open); |
| - } |
| -} |
| - |
| void ReportLoadSuccess(PP_Instance instance, |
| const char* url, |
| uint64_t loaded_bytes, |
| @@ -890,46 +899,29 @@ void DownloadManifestToBuffer(PP_Instance instance, |
| struct PP_CompletionCallback callback) { |
| nacl::NexeLoadManager* load_manager = GetNexeLoadManager(instance); |
| DCHECK(load_manager); |
| - if (!load_manager) { |
| + content::PepperPluginInstance* plugin_instance = |
| + content::PepperPluginInstance::Get(instance); |
| + if (!load_manager || !plugin_instance) { |
| ppapi::PpapiGlobals::Get()->GetMainThreadMessageLoop()->PostTask( |
| FROM_HERE, |
| base::Bind(callback.func, callback.user_data, |
| static_cast<int32_t>(PP_ERROR_FAILED))); |
| } |
| + const blink::WebDocument& document = |
| + plugin_instance->GetContainer()->element().document(); |
| const GURL& gurl = load_manager->manifest_base_url(); |
| - |
| - content::PepperPluginInstance* plugin_instance = |
| - content::PepperPluginInstance::Get(instance); |
| - blink::WebURLLoaderOptions options; |
| - options.untrustedHTTP = true; |
| - |
| - blink::WebSecurityOrigin security_origin = |
| - plugin_instance->GetContainer()->element().document().securityOrigin(); |
| - // Options settings here follow the original behavior in the trusted |
| - // plugin and PepperURLLoaderHost. |
| - if (security_origin.canRequest(gurl)) { |
| - options.allowCredentials = true; |
| - } else { |
| - // Allow CORS. |
| - options.crossOriginRequestPolicy = |
| - blink::WebURLLoaderOptions::CrossOriginRequestPolicyUseAccessControl; |
| - } |
| - |
| - blink::WebFrame* frame = |
| - plugin_instance->GetContainer()->element().document().frame(); |
| - blink::WebURLLoader* url_loader = frame->createAssociatedURLLoader(options); |
| - blink::WebURLRequest request; |
| - request.initialize(); |
| - request.setURL(gurl); |
| - request.setFirstPartyForCookies(frame->document().firstPartyForCookies()); |
| + scoped_ptr<blink::WebURLLoader> url_loader( |
| + CreateWebURLLoader(document, gurl)); |
| + blink::WebURLRequest request = CreateWebURLRequest(document, gurl); |
| // ManifestDownloader deletes itself after invoking the callback. |
| - ManifestDownloader* client = new ManifestDownloader( |
| + ManifestDownloader* manifest_downloader = new ManifestDownloader( |
| + url_loader.Pass(), |
| load_manager->is_installed(), |
| base::Bind(DownloadManifestToBufferCompletion, |
| instance, callback, out_data, base::Time::Now())); |
| - url_loader->loadAsynchronously(request, client); |
| + manifest_downloader->Load(request); |
| } |
| void DownloadManifestToBufferCompletion(PP_Instance instance, |
| @@ -1253,6 +1245,160 @@ void PostMessageToJavaScript(PP_Instance instance, const char* message) { |
| std::string(message))); |
| } |
| +// Encapsulates some of the state for a call to DownloadNexe to prevent |
| +// argument lists from getting too long. |
| +struct DownloadNexeRequest { |
| + PP_Instance instance; |
| + 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.
|
| + PP_CompletionCallback callback; |
| + base::Time start_time; |
| +}; |
| + |
| +// A utility class to ensure that we don't send progress events more often than |
| +// every 10ms for a given file. |
| +class DownloadProgressTracker { |
|
bbudge
2014/05/14 21:46:18
How about ProgressEventRateLimiter?
teravest
2014/05/15 19:12:21
Done.
|
| + public: |
| + explicit DownloadProgressTracker(PP_Instance instance) : instance_(instance) { |
| + } |
| + |
| + void ReportProgress(const std::string& url, |
| + int64_t total_bytes_received, |
| + int64_t total_bytes_to_be_received) { |
| + base::Time now = base::Time::Now(); |
| + if (now - last_event_ > base::TimeDelta::FromMilliseconds(10)) { |
| + DispatchProgressEvent(instance_, |
| + ProgressEvent(PP_NACL_EVENT_PROGRESS, |
| + url, |
| + total_bytes_to_be_received >= 0, |
| + total_bytes_received, |
| + total_bytes_to_be_received)); |
| + last_event_ = now; |
| + } |
| + } |
| + |
| + private: |
| + PP_Instance instance_; |
| + base::Time last_event_; |
| +}; |
| + |
| +void DownloadNexeCompletion(const DownloadNexeRequest& request, |
| + scoped_ptr<blink::WebURLLoader> loader, |
| + base::PlatformFile target_file, |
| + PP_FileHandle* out_handle, |
| + FileDownloader::Status status, |
| + int http_status); |
| + |
| +void DownloadNexe(PP_Instance instance, |
| + const char* url, |
| + PP_FileHandle* out_handle, |
| + PP_CompletionCallback callback) { |
| + CHECK(url); |
| + CHECK(out_handle); |
| + DownloadNexeRequest request; |
| + request.instance = instance; |
| + request.url = url; |
| + request.callback = callback; |
| + request.start_time = base::Time::Now(); |
| + |
| + // Try the fast path for retrieving the file first. |
| + uint64_t file_token_lo = 0; |
| + uint64_t file_token_hi = 0; |
| + PP_FileHandle file_handle = OpenNaClExecutable(instance, |
| + url, |
| + &file_token_lo, |
| + &file_token_hi); |
| + if (file_handle != PP_kInvalidFileHandle) { |
| + DownloadNexeCompletion(request, |
| + scoped_ptr<blink::WebURLLoader>(), |
| + file_handle, |
| + out_handle, |
| + FileDownloader::SUCCESS, |
| + 200); |
| + return; |
| + } |
| + |
| + // The fast path didn't work, we'll fetch the file using URLLoader and write |
| + // it to local storage. |
| + base::PlatformFile target_file = CreateTemporaryFile(instance); |
| + GURL gurl(url); |
| + |
| + content::PepperPluginInstance* plugin_instance = |
| + content::PepperPluginInstance::Get(instance); |
| + if (!plugin_instance) { |
| + ppapi::PpapiGlobals::Get()->GetMainThreadMessageLoop()->PostTask( |
| + FROM_HERE, |
| + base::Bind(callback.func, callback.user_data, |
| + static_cast<int32_t>(PP_ERROR_FAILED))); |
| + } |
| + const blink::WebDocument& document = |
| + plugin_instance->GetContainer()->element().document(); |
| + scoped_ptr<blink::WebURLLoader> url_loader( |
| + CreateWebURLLoader(document, gurl)); |
| + blink::WebURLRequest url_request = CreateWebURLRequest(document, gurl); |
| + |
| + DownloadProgressTracker* tracker = new DownloadProgressTracker(instance); |
| + |
| + // FileDownloader deletes itself after invoking the callback. |
| + FileDownloader* file_downloader = new FileDownloader( |
| + url_loader.Pass(), |
| + target_file, |
| + base::Bind(&DownloadNexeCompletion, request, base::Passed(&url_loader), |
| + 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.
|
| + base::Bind(&DownloadProgressTracker::ReportProgress, |
| + base::Owned(tracker), url)); |
| + file_downloader->Load(url_request); |
| +} |
| + |
| +void DownloadNexeCompletion(const DownloadNexeRequest& request, |
| + scoped_ptr<blink::WebURLLoader> loader, |
| + base::PlatformFile target_file, |
| + PP_FileHandle* out_handle, |
| + FileDownloader::Status status, |
| + int http_status) { |
| + int32_t pp_error; |
| + switch (status) { |
| + case FileDownloader::SUCCESS: |
| + *out_handle = target_file; |
| + pp_error = PP_OK; |
| + break; |
| + case FileDownloader::ACCESS_DENIED: |
| + pp_error = PP_ERROR_NOACCESS; |
| + break; |
| + case FileDownloader::FAILED: |
| + pp_error = PP_ERROR_FAILED; |
| + break; |
| + default: |
| + NOTREACHED(); |
| + return; |
| + } |
| + |
| + int64_t bytes_read = -1; |
| + if (pp_error == PP_OK && target_file != base::kInvalidPlatformFileValue) { |
| + base::PlatformFileInfo info; |
| + if (GetPlatformFileInfo(target_file, &info)) |
| + bytes_read = info.size; |
| + } |
| + |
| + if (bytes_read == -1) { |
| + base::ClosePlatformFile(target_file); |
| + pp_error = PP_ERROR_FAILED; |
| + } |
| + |
| + base::TimeDelta download_time = base::Time::Now() - request.start_time; |
| + |
| + NexeLoadManager* load_manager = GetNexeLoadManager(request.instance); |
| + if (load_manager) { |
| + load_manager->NexeFileDidOpen(pp_error, |
| + target_file, |
| + http_status, |
| + bytes_read, |
| + request.url, |
| + download_time); |
| + } |
| + |
| + request.callback.func(request.callback.user_data, pp_error); |
| +} |
| + |
| const PPB_NaCl_Private nacl_interface = { |
| &LaunchSelLdr, |
| &StartPpapiProxy, |
| @@ -1267,7 +1413,6 @@ const PPB_NaCl_Private nacl_interface = { |
| &ReportTranslationFinished, |
| &OpenNaClExecutable, |
| &DispatchEvent, |
| - &NexeFileDidOpen, |
| &ReportLoadSuccess, |
| &ReportLoadError, |
| &ReportLoadAbort, |
| @@ -1299,7 +1444,8 @@ const PPB_NaCl_Private nacl_interface = { |
| &ManifestResolveKey, |
| &GetPNaClResourceInfo, |
| &GetCpuFeatureAttrs, |
| - &PostMessageToJavaScript |
| + &PostMessageToJavaScript, |
| + &DownloadNexe |
| }; |
| } // namespace |