summaryrefslogtreecommitdiffstats
path: root/ppapi
diff options
context:
space:
mode:
authorjvoung@chromium.org <jvoung@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-01-30 12:01:52 +0000
committerjvoung@chromium.org <jvoung@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-01-30 12:01:52 +0000
commitdfd02ec85d25bf1a8b10696fc604bc61b35d3fa9 (patch)
tree7fae4a100eb77cdcea285105811f9405fee3f5c1 /ppapi
parent9b621c69897dffde4228287657eac010411de3fc (diff)
downloadchromium_src-dfd02ec85d25bf1a8b10696fc604bc61b35d3fa9.zip
chromium_src-dfd02ec85d25bf1a8b10696fc604bc61b35d3fa9.tar.gz
chromium_src-dfd02ec85d25bf1a8b10696fc604bc61b35d3fa9.tar.bz2
Report min (compile, download) as the progress event for PNaCl.
With dschuff's patch to LLC that limits the streaming buffer inside LLC so that the StreamBytes RPC blocks until enough of the buffer is consumed. Thus it never goes faster than the compile. StreamBytes also depends on bytes being downloaded, so it never goes faster than the download. This allows us to report compile progress if downloading is faster than a compile, or report download progress if compiling is faster. BUG=none TEST=browser_tests --gtest_filter=NaClBrowserTest*ProgressEvents* and manual Review URL: https://chromiumcodereview.appspot.com/12093009 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@179605 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ppapi')
-rw-r--r--ppapi/native_client/src/trusted/plugin/file_downloader.cc13
-rw-r--r--ppapi/native_client/src/trusted/plugin/file_downloader.h21
-rw-r--r--ppapi/native_client/src/trusted/plugin/plugin.cc16
-rw-r--r--ppapi/native_client/src/trusted/plugin/pnacl_coordinator.cc37
-rw-r--r--ppapi/native_client/src/trusted/plugin/pnacl_coordinator.h13
-rw-r--r--ppapi/native_client/src/trusted/plugin/pnacl_translate_thread.cc9
-rw-r--r--ppapi/native_client/src/trusted/plugin/pnacl_translate_thread.h3
-rw-r--r--ppapi/native_client/tests/ppapi_browser/progress_event_listener.js40
8 files changed, 136 insertions, 16 deletions
diff --git a/ppapi/native_client/src/trusted/plugin/file_downloader.cc b/ppapi/native_client/src/trusted/plugin/file_downloader.cc
index 920dbf5..1f6b6d4 100644
--- a/ppapi/native_client/src/trusted/plugin/file_downloader.cc
+++ b/ppapi/native_client/src/trusted/plugin/file_downloader.cc
@@ -46,13 +46,14 @@ bool FileDownloader::OpenStream(
const pp::CompletionCallback& callback,
StreamCallbackSource* stream_callback_source) {
data_stream_callback_source_ = stream_callback_source;
- return Open(url, DOWNLOAD_STREAM, callback, NULL);
+ return Open(url, DOWNLOAD_STREAM, callback, true, NULL);
}
bool FileDownloader::Open(
const nacl::string& url,
DownloadMode mode,
const pp::CompletionCallback& callback,
+ bool record_progress,
PP_URLLoaderTrusted_StatusCallback progress_callback) {
PLUGIN_PRINTF(("FileDownloader::Open (url=%s)\n", url.c_str()));
if (callback.pp_completion_callback().func == NULL ||
@@ -98,6 +99,8 @@ bool FileDownloader::Open(
}
}
+ url_request.SetRecordDownloadProgress(record_progress);
+
if (url_loader_trusted_interface_ != NULL) {
if (grant_universal_access) {
// TODO(sehr,jvoung): See if we can remove this -- currently
@@ -106,7 +109,6 @@ bool FileDownloader::Open(
url_loader_.pp_resource());
}
if (progress_callback != NULL) {
- url_request.SetRecordDownloadProgress(true);
url_loader_trusted_interface_->RegisterStatusCallback(
url_loader_.pp_resource(), progress_callback);
}
@@ -349,6 +351,13 @@ void FileDownloader::URLReadBodyNotify(int32_t pp_error) {
}
}
+bool FileDownloader::GetDownloadProgress(
+ int64_t* bytes_received,
+ int64_t* total_bytes_to_be_received) const {
+ return url_loader_.GetDownloadProgress(bytes_received,
+ total_bytes_to_be_received);
+}
+
void FileDownloader::FileOpenNotify(int32_t pp_error) {
PLUGIN_PRINTF(("FileDownloader::FileOpenNotify (pp_error=%"NACL_PRId32")\n",
pp_error));
diff --git a/ppapi/native_client/src/trusted/plugin/file_downloader.h b/ppapi/native_client/src/trusted/plugin/file_downloader.h
index 914ca62..3f1e2b6 100644
--- a/ppapi/native_client/src/trusted/plugin/file_downloader.h
+++ b/ppapi/native_client/src/trusted/plugin/file_downloader.h
@@ -62,11 +62,15 @@ class FileDownloader {
// Returns true when callback is scheduled to be called on success or failure.
// Returns false if callback is NULL, Initialize() has not been called or if
// the PPB_FileIO_Trusted interface is not available.
- // If |progress_callback| is not NULL, it will be invoked for every progress
- // update received by the loader.
+ // If |record_progress| is true, then download progress will be recorded,
+ // and can be polled through GetDownloadProgress().
+ // If |progress_callback| is not NULL and |record_progress| is true,
+ // then the callback will be invoked for every progress update received
+ // by the loader.
bool Open(const nacl::string& url,
DownloadMode mode,
const pp::CompletionCallback& callback,
+ bool record_progress,
PP_URLLoaderTrusted_StatusCallback progress_callback);
// Same as Open, but used for streaming the file data directly to the
@@ -99,6 +103,19 @@ class FileDownloader {
// Returns the PP_Resource of the active URL loader, or kInvalidResource.
PP_Resource url_loader() const { return url_loader_.pp_resource(); }
+ // GetDownloadProgress() returns the current download progress, which is
+ // meaningful after Open() has been called. Progress only refers to the
+ // response body and does not include the headers.
+ //
+ // This data is only available if the |record_progress| true in the
+ // Open() call. If progress is being recorded, then |bytes_received|
+ // will be set to the number of bytes received thus far,
+ // and |total_bytes_to_be_received| will be set to the total number
+ // of bytes to be received. The total bytes to be received may be unknown,
+ // in which case |total_bytes_to_be_received| will be set to -1.
+ bool GetDownloadProgress(int64_t* bytes_received,
+ int64_t* total_bytes_to_be_received) const;
+
// Returns the buffer used for DOWNLOAD_TO_BUFFER mode.
const std::deque<char>& buffer() const { return buffer_; }
diff --git a/ppapi/native_client/src/trusted/plugin/plugin.cc b/ppapi/native_client/src/trusted/plugin/plugin.cc
index 0ea8fd2..31f233e 100644
--- a/ppapi/native_client/src/trusted/plugin/plugin.cc
+++ b/ppapi/native_client/src/trusted/plugin/plugin.cc
@@ -975,12 +975,7 @@ void Plugin::BitcodeDidTranslate(int32_t pp_error) {
return;
}
- // TODO(dschuff,jvoung): We could have a UMA stat for total time taken
- // to translate. We may also want a breakdown (how long does it take
- // to start up the LLC nexe process, LD nexe process, etc.).
-
// Inform JavaScript that we successfully translated the bitcode to a nexe.
- EnqueueProgressEvent(kProgressEventProgress);
nacl::scoped_ptr<nacl::DescWrapper>
wrapper(pnacl_coordinator_.get()->ReleaseTranslatedFD());
ErrorInfo error_info;
@@ -1001,9 +996,10 @@ void Plugin::BitcodeDidTranslateContinuation(int32_t pp_error) {
NaClLog(4, "Entered BitcodeDidTranslateContinuation\n");
UNREFERENCED_PARAMETER(pp_error);
if (was_successful) {
- ReportLoadSuccess(LENGTH_IS_NOT_COMPUTABLE,
- kUnknownBytes,
- kUnknownBytes);
+ int64_t loaded;
+ int64_t total;
+ pnacl_coordinator_->GetCurrentProgress(&loaded, &total);
+ ReportLoadSuccess(LENGTH_IS_COMPUTABLE, loaded, total);
} else {
ReportLoadError(error_info);
}
@@ -1216,6 +1212,7 @@ void Plugin::ProcessNaClManifest(const nacl::string& manifest_json) {
nexe_downloader_.Open(program_url,
DOWNLOAD_TO_FILE,
open_callback,
+ true,
&UpdateDownloadProgress));
return;
}
@@ -1259,6 +1256,7 @@ void Plugin::RequestNaClManifest(const nacl::string& url) {
CHECK(nexe_downloader_.Open(nmf_resolved_url.AsString(),
DOWNLOAD_TO_BUFFER,
open_callback,
+ false,
NULL));
} else {
pp::CompletionCallback open_callback =
@@ -1267,6 +1265,7 @@ void Plugin::RequestNaClManifest(const nacl::string& url) {
CHECK(nexe_downloader_.Open(nmf_resolved_url.AsString(),
DOWNLOAD_TO_FILE,
open_callback,
+ false,
NULL));
}
}
@@ -1347,6 +1346,7 @@ bool Plugin::StreamAsFile(const nacl::string& url,
return downloader->Open(url,
DOWNLOAD_TO_FILE,
open_callback,
+ true,
&UpdateDownloadProgress);
}
diff --git a/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.cc b/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.cc
index 01f9002..a94bb73 100644
--- a/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.cc
+++ b/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.cc
@@ -345,7 +345,9 @@ PnaclCoordinator::PnaclCoordinator(
error_already_reported_(false),
off_the_record_(false),
pnacl_init_time_(0),
- pexe_size_(0) {
+ pexe_size_(0),
+ pexe_bytes_compiled_(0),
+ expected_pexe_size_(-1) {
PLUGIN_PRINTF(("PnaclCoordinator::PnaclCoordinator (this=%p, plugin=%p)\n",
static_cast<void*>(this), static_cast<void*>(plugin)));
callback_factory_.Initialize(this);
@@ -691,7 +693,6 @@ void PnaclCoordinator::NexeReadDidOpen(int32_t pp_error) {
} else {
translated_fd_.reset(temp_nexe_file_->release_read_wrapper());
}
- plugin_->EnqueueProgressEvent(Plugin::kProgressEventProgress);
translate_notify_callback_.Run(pp_error);
}
@@ -885,6 +886,37 @@ StreamCallback PnaclCoordinator::GetCallback() {
&PnaclCoordinator::BitcodeStreamGotData);
}
+void PnaclCoordinator::BitcodeGotCompiled(int32_t pp_error,
+ int64_t bytes_compiled) {
+ // If we don't know the expected total yet, ask.
+ pexe_bytes_compiled_ += bytes_compiled;
+ if (expected_pexe_size_ == -1) {
+ int64_t amount_downloaded; // dummy variable.
+ streaming_downloader_->GetDownloadProgress(&amount_downloaded,
+ &expected_pexe_size_);
+ }
+ bool length_computable = (expected_pexe_size_ != -1);
+ plugin_->EnqueueProgressEvent(plugin::Plugin::kProgressEventProgress,
+ pexe_url_,
+ (length_computable ?
+ plugin::Plugin::LENGTH_IS_COMPUTABLE :
+ plugin::Plugin::LENGTH_IS_NOT_COMPUTABLE),
+ pexe_bytes_compiled_,
+ expected_pexe_size_);
+}
+
+pp::CompletionCallback PnaclCoordinator::GetCompileProgressCallback(
+ int64_t bytes_compiled) {
+ return callback_factory_.NewCallback(&PnaclCoordinator::BitcodeGotCompiled,
+ bytes_compiled);
+}
+
+void PnaclCoordinator::GetCurrentProgress(int64_t* bytes_loaded,
+ int64_t* bytes_total) {
+ *bytes_loaded = pexe_bytes_compiled_;
+ *bytes_total = expected_pexe_size_;
+}
+
void PnaclCoordinator::ObjectFileDidOpen(int32_t pp_error) {
PLUGIN_PRINTF(("PnaclCoordinator::ObjectFileDidOpen (pp_error=%"
NACL_PRId32")\n", pp_error));
@@ -918,6 +950,7 @@ void PnaclCoordinator::RunTranslate(int32_t pp_error) {
temp_nexe_file_.get(),
&error_info_,
resources_.get(),
+ this,
plugin_);
}
diff --git a/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.h b/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.h
index 1deb3a9..a36b99e 100644
--- a/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.h
+++ b/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.h
@@ -134,6 +134,13 @@ class PnaclCoordinator: public CallbackSource<FileStreamData> {
// (BitcodeStreamGotData) passes it to llc over SRPC.
StreamCallback GetCallback();
+ // Return a callback that should be notified when |bytes_compiled| bytes
+ // have been compiled.
+ pp::CompletionCallback GetCompileProgressCallback(int64_t bytes_compiled);
+
+ // Get the last known load progress.
+ void GetCurrentProgress(int64_t* bytes_loaded, int64_t* bytes_total);
+
private:
NACL_DISALLOW_COPY_AND_ASSIGN(PnaclCoordinator);
@@ -158,6 +165,8 @@ class PnaclCoordinator: public CallbackSource<FileStreamData> {
void CachedFileDidOpen(int32_t pp_error);
// Invoked when a pexe data chunk arrives (when using streaming translation)
void BitcodeStreamGotData(int32_t pp_error, FileStreamData data);
+ // Invoked when a pexe data chunk is compiled.
+ void BitcodeGotCompiled(int32_t pp_error, int64_t bytes_compiled);
// Invoked when the pexe download finishes (using streaming translation)
void BitcodeStreamDidFinish(int32_t pp_error);
// Invoked when the write descriptor for obj_file_ is created.
@@ -243,7 +252,9 @@ class PnaclCoordinator: public CallbackSource<FileStreamData> {
// State for timing and size information for UMA stats.
int64_t pnacl_init_time_;
- size_t pexe_size_; // Count as we stream -- will converge to pexe size.
+ int64_t pexe_size_; // Count as we stream -- will converge to pexe size.
+ int64_t pexe_bytes_compiled_; // Count as we compile.
+ int64_t expected_pexe_size_; // Expected download total (-1 if unknown).
// The helper thread used to do translations via SRPC.
// Keep this last in declaration order to ensure the other variables
diff --git a/ppapi/native_client/src/trusted/plugin/pnacl_translate_thread.cc b/ppapi/native_client/src/trusted/plugin/pnacl_translate_thread.cc
index d3d6439..e51a0ce 100644
--- a/ppapi/native_client/src/trusted/plugin/pnacl_translate_thread.cc
+++ b/ppapi/native_client/src/trusted/plugin/pnacl_translate_thread.cc
@@ -24,6 +24,7 @@ PnaclTranslateThread::PnaclTranslateThread() : llc_subprocess_active_(false),
nexe_file_(NULL),
coordinator_error_info_(NULL),
resources_(NULL),
+ coordinator_(NULL),
plugin_(NULL) {
NaClXMutexCtor(&subprocess_mu_);
NaClXMutexCtor(&cond_mu_);
@@ -38,6 +39,7 @@ void PnaclTranslateThread::RunTranslate(
TempFile* nexe_file,
ErrorInfo* error_info,
PnaclResources* resources,
+ PnaclCoordinator* coordinator,
Plugin* plugin) {
PLUGIN_PRINTF(("PnaclStreamingTranslateThread::RunTranslate)\n"));
manifest_ = manifest;
@@ -46,6 +48,7 @@ void PnaclTranslateThread::RunTranslate(
nexe_file_ = nexe_file;
coordinator_error_info_ = error_info;
resources_ = resources;
+ coordinator_ = coordinator;
plugin_ = plugin;
// Invoke llc followed by ld off the main thread. This allows use of
@@ -168,6 +171,7 @@ void PnaclTranslateThread::DoTranslate() {
}
PLUGIN_PRINTF(("PnaclCoordinator: StreamInit successful\n"));
+ pp::Core* core = pp::Module::Get()->core();
// llc process is started.
while(!done_ || data_buffers_.size() > 0) {
@@ -193,6 +197,10 @@ void PnaclTranslateThread::DoTranslate() {
return;
}
PLUGIN_PRINTF(("StreamChunk Successful\n"));
+ core->CallOnMainThread(
+ 0,
+ coordinator_->GetCompileProgressCallback(data.size()),
+ PP_OK);
} else {
NaClXMutexUnlock(&cond_mu_);
}
@@ -235,7 +243,6 @@ void PnaclTranslateThread::DoTranslate() {
if(!RunLdSubprocess(is_shared_library, soname, lib_dependencies)) {
return;
}
- pp::Core* core = pp::Module::Get()->core();
core->CallOnMainThread(0, report_translate_finished_, PP_OK);
}
diff --git a/ppapi/native_client/src/trusted/plugin/pnacl_translate_thread.h b/ppapi/native_client/src/trusted/plugin/pnacl_translate_thread.h
index bcc77a7..bb3ea8c 100644
--- a/ppapi/native_client/src/trusted/plugin/pnacl_translate_thread.h
+++ b/ppapi/native_client/src/trusted/plugin/pnacl_translate_thread.h
@@ -28,6 +28,7 @@ namespace plugin {
class Manifest;
class NaClSubprocess;
class Plugin;
+class PnaclCoordinator;
class PnaclResources;
class TempFile;
@@ -52,6 +53,7 @@ class PnaclTranslateThread {
TempFile* nexe_file,
ErrorInfo* error_info,
PnaclResources* resources,
+ PnaclCoordinator* coordinator,
Plugin* plugin);
// Kill the llc and/or ld subprocesses. This happens by closing the command
@@ -122,6 +124,7 @@ class PnaclTranslateThread {
TempFile* nexe_file_;
ErrorInfo* coordinator_error_info_;
PnaclResources* resources_;
+ PnaclCoordinator* coordinator_;
Plugin* plugin_;
private:
NACL_DISALLOW_COPY_AND_ASSIGN(PnaclTranslateThread);
diff --git a/ppapi/native_client/tests/ppapi_browser/progress_event_listener.js b/ppapi/native_client/tests/ppapi_browser/progress_event_listener.js
index 4892a5f..42d3fc6 100644
--- a/ppapi/native_client/tests/ppapi_browser/progress_event_listener.js
+++ b/ppapi/native_client/tests/ppapi_browser/progress_event_listener.js
@@ -47,6 +47,26 @@ function EventStateMachine() {
this_.currentState = event_type;
this_.stateHistogram[this_.currentState]++;
}
+
+ // True if an event with lengthComputable is ever triggered.
+ this.stateSawLengthComputable = false;
+ // The last event.total seen from an event with lengthComputable being true.
+ this.stateProgressTotal = -1;
+ // The last event.loaded seen from an event with lengthComputable being true.
+ this.stateProgressPrev = -1;
+ // Function to record progress stats.
+ this.recordProgress = function(event) {
+ // Can either record progress from a progress event with lengthComputable,
+ // or from a loadend event.
+ if (event.type == 'progress' && event.lengthComputable) {
+ this.stateSawLengthComputable = true;
+ this.stateProgressTotal = event.total;
+ this.stateProgressPrev = event.loaded;
+ } else if (event.type == 'loadend' && event.lengthComputable) {
+ this.stateProgressTotal = event.total;
+ this.stateProgressPrev = event.loaded;
+ }
+ }
}
// event_machines is a collection of EventStateMachines, one for each element
@@ -78,6 +98,8 @@ var setListeners = function(body_element) {
var event_machine = lookupEventMachine(element_id);
// Update the state of the machine.
event_machine.transitionTo(e.type);
+ // Record progress information if possible.
+ event_machine.recordProgress(e);
}
// Add the listener for all of the ProgressEvent event types.
body_element.addEventListener('loadstart', eventListener, true);
@@ -112,6 +134,24 @@ function testProgressEventStateMachine(tester,
// loaded and another when the .nexe is loaded.
assert(eventMachine.stateHistogram['progress'] >= progressMinCount);
});
+ tester.addTest('progress_samples_' + embedId, function() {
+ console.log('stateSawLengthComputable ' +
+ eventMachine.stateSawLengthComputable);
+ console.log('stateProgressPrev ' +
+ eventMachine.stateProgressPrev);
+ console.log('stateProgressTotal ' +
+ eventMachine.stateProgressTotal);
+
+ assert(eventMachine.stateSawLengthComputable);
+ // Progress events are not necessarily monotonic. For glibc, each DSO
+ // will trigger a different series of progress events with different totals.
+ // For glibc, the final loadend progress event may even correspond to
+ // the very first load event, instead of corresponding to the last...
+ // So, all we check is that the latest values make some sense.
+ assert(eventMachine.stateProgressPrev > 0);
+ assert(eventMachine.stateProgressTotal > 0);
+ assert(eventMachine.stateProgressPrev <= eventMachine.stateProgressTotal);
+ });
tester.addTest('error_count_' + embedId, function() {
// Check that the right number of 'error' events were dispatched.
assertEqual(eventMachine.stateHistogram['error'], errorCount);