Index: ppapi/examples/url_loader/stream_to_file.cc |
diff --git a/ppapi/examples/url_loader/streaming.cc b/ppapi/examples/url_loader/stream_to_file.cc |
similarity index 57% |
copy from ppapi/examples/url_loader/streaming.cc |
copy to ppapi/examples/url_loader/stream_to_file.cc |
index 18efe68bf488ce0366219c385c70521e83111dcf..887a9d71242042eebcaa4a6ec2d68e9b236ca9b5 100644 |
--- a/ppapi/examples/url_loader/streaming.cc |
+++ b/ppapi/examples/url_loader/stream_to_file.cc |
@@ -2,15 +2,16 @@ |
// Use of this source code is governed by a BSD-style license that can be |
// found in the LICENSE file. |
-// This example shows how to use the URLLoader in streaming mode (reading to |
-// memory as data comes over the network). This example uses PostMessage between |
-// the plugin and the url_loader.html page in this directory to start the load |
-// and to communicate the result. |
+// This example shows how to use the URLLoader in "stream to file" mode where |
+// the browser writes incoming data to a file, which you can read out via the |
+// file I/O APIs. |
// |
-// The other mode is to stream to a file instead. For that mode, call |
-// URLLoader.FinishSthreamingToFile once the "Open" callback is complete, and |
-// then call URLResponseInfo.GetBodyAsFileRef once the file stream is complete. |
+// This example uses PostMessage between the plugin and the url_loader.html |
+// page in this directory to start the load and to communicate the result. |
+#include "ppapi/c/ppb_file_io.h" |
+#include "ppapi/cpp/file_io.h" |
+#include "ppapi/cpp/file_ref.h" |
#include "ppapi/cpp/instance.h" |
#include "ppapi/cpp/module.h" |
#include "ppapi/cpp/url_loader.h" |
@@ -51,10 +52,10 @@ class MyInstance : public pp::Instance { |
// Callback for the URLLoader to tell us it finished opening the connection. |
void OnOpenComplete(int32_t result); |
- // Starts streaming data. |
- void ReadMore(); |
+ // Callback for when the file is completely filled with the download |
+ void OnStreamComplete(int32_t result); |
- // Callback for the URLLoader to tell us when it finished a read. |
+ void OnOpenFileComplete(int32_t result); |
void OnReadComplete(int32_t result); |
// Forwards the given string to the page. |
@@ -65,6 +66,8 @@ class MyInstance : public pp::Instance { |
pp::URLLoader loader_; |
pp::URLResponseInfo response_; |
+ pp::FileRef dest_file_; |
+ pp::FileIO file_io_; |
// The buffer used for the current read request. This is filled and then |
// copied into content_ to build up the entire document. |
@@ -85,6 +88,7 @@ void MyInstance::StartRequest(const std::string& url) { |
pp::URLRequestInfo request(this); |
request.SetURL(url); |
request.SetMethod("GET"); |
+ request.SetStreamToFile(true); |
loader_ = pp::URLLoader(this); |
loader_.Open(request, |
@@ -97,58 +101,47 @@ void MyInstance::OnOpenComplete(int32_t result) { |
return; |
} |
+ loader_.FinishStreamingToFile( |
+ factory_.NewCallback(&MyInstance::OnStreamComplete)); |
response_ = loader_.GetResponseInfo(); |
+ dest_file_ = response_.GetBodyAsFileRef(); |
+} |
- // Here you would process the headers. A real program would want to at least |
- // check the HTTP code and potentially cancel the request. |
- |
- // Start streaming. |
- ReadMore(); |
+void MyInstance::OnStreamComplete(int32_t result) { |
+ if (result == PP_OK) { |
+ file_io_ = pp::FileIO(this); |
+ file_io_.Open(dest_file_, PP_FILEOPENFLAG_READ, |
+ factory_.NewCallback(&MyInstance::OnOpenFileComplete)); |
+ } else { |
+ ReportResponse("Could not stream to file"); |
+ } |
} |
-void MyInstance::ReadMore() { |
- // Note that you specifically want an "optional" callback here. This will |
- // allow Read() to return synchronously, ignoring your completion callback, |
- // if data is available. For fast connections and large files, reading as |
- // fast as we can will make a large performance difference. However, in the |
- // case of a synchronous return, we need to be sure to run the callback we |
- // created since the loader won't do anything with it. |
- pp::CompletionCallback cc = |
- factory_.NewOptionalCallback(&MyInstance::OnReadComplete); |
- int32_t result = PP_OK; |
- do { |
- result = loader_.ReadResponseBody(buf_, kBufSize, cc); |
- // Handle streaming data directly. Note that we *don't* want to call |
- // OnReadComplete here, since in the case of result > 0 it will schedule |
- // another call to this function. If the network is very fast, we could |
- // end up with a deeply recursive stack. |
- if (result > 0) |
- content_.append(buf_, result); |
- } while (result > 0); |
- |
- if (result != PP_OK_COMPLETIONPENDING) { |
- // Either we reached the end of the stream (result == PP_OK) or there was |
- // an error. We want OnReadComplete to get called no matter what to handle |
- // that case, whether the error is synchronous or asynchronous. If the |
- // result code *is* COMPLETIONPENDING, our callback will be called |
- // asynchronously. |
- cc.Run(result); |
+void MyInstance::OnOpenFileComplete(int32_t result) { |
+ if (result == PP_OK) { |
+ // Note we only read the first 1024 bytes from the file in this example |
+ // to keep things simple. Please see a file I/O example for more details |
+ // on reading files. |
+ file_io_.Read(0, buf_, kBufSize, |
+ factory_.NewCallback(&MyInstance::OnReadComplete)); |
+ } else { |
+ ReportResponse("Could not open file"); |
} |
} |
void MyInstance::OnReadComplete(int32_t result) { |
- if (result == PP_OK) { |
- // Streaming the file is complete. |
- ReportResponse(content_); |
- } else if (result > 0) { |
- // The URLLoader just filled "result" number of bytes into our buffer. |
- // Save them and perform another read. |
+ if (result >= 0) { |
content_.append(buf_, result); |
- ReadMore(); |
+ ReportResponse(buf_); |
} else { |
- // A read error occurred. |
- ReportResponse("A read error occurred"); |
+ ReportResponse("Could not read file"); |
} |
+ |
+ // Release everything. |
+ loader_ = pp::URLLoader(); |
+ response_ = pp::URLResponseInfo(); |
+ dest_file_ = pp::FileRef(); |
+ file_io_ = pp::FileIO(); |
} |
void MyInstance::ReportResponse(const std::string& data) { |