1 {{+bindTo:partials.standard_nacl_article}}
3 <section id=
"url-loading">
4 <span id=
"devguide-coding-url-loading"></span><h1 id=
"url-loading"><span id=
"devguide-coding-url-loading"></span>URL Loading
</h1>
5 <div class=
"contents local" id=
"contents" style=
"display: none">
7 <li><a class=
"reference internal" href=
"#introduction" id=
"id1">Introduction
</a></li>
8 <li><a class=
"reference internal" href=
"#reference-information" id=
"id2">Reference information
</a></li>
9 <li><a class=
"reference internal" href=
"#background" id=
"id3">Background
</a></li>
10 <li><p class=
"first"><a class=
"reference internal" href=
"#the-url-loader-example" id=
"id4">The
<code>url_loader
</code> example
</a></p>
11 <ul class=
"small-gap">
12 <li><a class=
"reference internal" href=
"#url-loading-overview" id=
"id5">URL loading overview
</a></li>
15 <li><p class=
"first"><a class=
"reference internal" href=
"#url-loader-deep-dive" id=
"id6"><code>url_loader
</code> deep dive
</a></p>
16 <ul class=
"small-gap">
17 <li><a class=
"reference internal" href=
"#setting-up-the-request" id=
"id7">Setting up the request
</a></li>
18 <li><a class=
"reference internal" href=
"#downloading-the-data" id=
"id8">Downloading the data
</a></li>
19 <li><a class=
"reference internal" href=
"#displaying-a-result" id=
"id9">Displaying a result
</a></li>
24 </div><h2 id=
"introduction">Introduction
</h2>
25 <p>This section describes how to use the
<a class=
"reference external" href=
"/native-client/pepper_stable/cpp/classpp_1_1_u_r_l_loader">URLLoader API
</a> to load resources
26 such as images and sound files from a server into your application.
</p>
27 <p>The example discussed in this section is included in the SDK in the directory
28 <code>examples/api/url_loader
</code>.
</p>
29 <h2 id=
"reference-information">Reference information
</h2>
30 <p>For reference information related to loading data from URLs, see the
31 following documentation:
</p>
32 <ul class=
"small-gap">
33 <li><a class=
"reference external" href=
"/native-client/pepper_stable/cpp/url__loader_8h">url_loader.h
</a> - Contains
34 <code>URLLoader
</code> class for loading data from URLs
</li>
35 <li><a class=
"reference external" href=
"/native-client/pepper_stable/cpp/url__request__info_8h">url_request_info.h
</a> - Contains
36 <code>URLRequest
</code> class for creating and manipulating URL requests
</li>
37 <li><a class=
"reference external" href=
"/native-client/pepper_stable/cpp/url__response__info_8h">url_response_info.h
</a> - Contains
38 <code>URLResponse
</code> class for examaning URL responses
</li>
40 <h2 id=
"background">Background
</h2>
41 <p>When a user launches your Native Client web application, Chrome downloads and
42 caches your application
’s HTML file, manifest file (.nmf), and Native Client
43 module (.pexe or .nexe). If your application needs additional assets, such as
44 images and sound files, it must explicitly load those assets. You can use the
45 Pepper APIs described in this section to load assets from a URL into your
47 <p>After you
’ve loaded assets into your application, Chrome will cache those
48 assets. To avoid being at the whim of the Chrome cache, however, you may want
49 to use the
<a class=
"reference external" href=
"/native-client/pepper_stable/cpp/classpp_1_1_file_i_o">Pepper FileIO API
</a> to write those assets
50 to a persistent, sandboxed location on the user
’s file system.
</p>
51 <h2 id=
"the-url-loader-example">The
<code>url_loader
</code> example
</h2>
52 <p>The SDK includes an example called
<code>url_loader
</code> demonstrating downloading
53 files from a server. This example has these primary files:
</p>
54 <ul class=
"small-gap">
55 <li><code>index.html
</code> - The HTML code that launches the Native Client module.
</li>
56 <li><code>example.js
</code> - The JavaScript file for index.html. It has code that sends
57 a PostMessage request to the Native Client module when the
“Get URL
” button
59 <li><code>url_loader_success.html
</code> - An HTML file on the server whose contents are
60 being retrieved using the
<code>URLLoader
</code> API.
</li>
61 <li><code>url_loader.cc
</code> - The code that sets up and provides and entry point into
62 the Native client module.
</li>
63 <li><code>url_loader_handler.cc
</code> - The code that retrieves the contents of the
64 url_loader_success.html file and returns the results (this is where the
65 bulk of the work is done).
</li>
67 <p>The remainder of this document covers the code in the
<code>url_loader.cc
</code> and
68 <code>url_loader_handler.cc
</code> files.
</p>
69 <h3 id=
"url-loading-overview">URL loading overview
</h3>
70 <p>Like many Pepper APIs, the
<code>URLLoader
</code> API includes a set of methods that
71 execute asynchronously and that invoke callback functions in your Native Client
72 module. The high-level flow for the
<code>url_loader
</code> example is described below.
73 Note that methods in the namespace
<code>pp::URLLoader
</code> are part of the Pepper
74 <code>URLLoader
</code> API, while the rest of the functions are part of the code in the
75 Native Client module (specifically in the file
<code>url_loader_handler.cc
</code>). The
76 following image shows the flow of the
<code>url_loader_handler
</code> code:
</p>
77 <img alt=
"/native-client/images/pepper-urlloader-api.png" src=
"/native-client/images/pepper-urlloader-api.png" />
78 <p>Following are the high-level steps involved in URL loading.
</p>
79 <ol class=
"arabic simple">
80 <li>The Native Client module calls
<code>pp::URLLoader::Open
</code> to begin opening the
82 <li>When
<code>Open
</code> completes, it invokes a callback function in the Native Client
83 module (in this case,
<code>OnOpen
</code>).
</li>
84 <li>The Native Client module calls the Pepper function
85 <code>URLLoader::ReadResponseBody
</code> to begin reading the response body with the
86 data.
<code>ReadResponseBody
</code> is passed an optional callback function in the
87 Native Client module (in this case, On
<code>Read
</code>). The callback function is
88 an optional callback because
<code>ReadResponseBody
</code> may read data and return
89 synchronously if data is available (this improves performance for large
90 files and fast connections).
</li>
92 <p>The remainder of this document demonstrates how the previous steps are
93 implemented in the
<code>url_loader
</code> example.
</p>
94 <h2 id=
"url-loader-deep-dive"><code>url_loader
</code> deep dive
</h2>
95 <h3 id=
"setting-up-the-request">Setting up the request
</h3>
96 <p><code>HandleMessage
</code> in
<code>url_loader.cc
</code> creates a
<code>URLLoaderHandler
</code> instance
97 and passes it the URL of the asset to be retrieved. Then
<code>HandleMessage
</code>
98 calls
<code>Start
</code> to start retrieving the asset from the server:
</p>
99 <pre class=
"prettyprint">
100 void URLLoaderInstance::HandleMessage(const pp::Var
& var_message) {
101 if (!var_message.is_string()) {
104 std::string message = var_message.AsString();
105 if (message.find(kLoadUrlMethodId) ==
0) {
106 // The argument to getUrl is everything after the first ':'.
107 size_t sep_pos = message.find_first_of(kMessageArgumentSeparator);
108 if (sep_pos != std::string::npos) {
109 std::string url = message.substr(sep_pos +
1);
110 printf(
"URLLoaderInstance::HandleMessage('%s', '%s')\n
",
114 URLLoaderHandler* handler = URLLoaderHandler::Create(this, url);
115 if (handler != NULL) {
116 // Starts asynchronous download. When download is finished or when an
117 // error occurs, |handler| posts the results back to the browser
118 // vis PostMessage and self-destroys.
125 <p>Notice that the constructor for
<code>URLLoaderHandler
</code> in
126 <code>url_loader_handler.cc
</code> sets up the parameters of the URL request (using
127 <code>SetURL,
</code> <code>SetMethod
</code>, and
<code>SetRecordDownloadProgress
</code>):
</p>
128 <pre class=
"prettyprint">
129 URLLoaderHandler::URLLoaderHandler(pp::Instance* instance,
130 const std::string
& url)
131 : instance_(instance),
133 url_request_(instance),
134 url_loader_(instance),
135 buffer_(new char[READ_BUFFER_SIZE]),
137 url_request_.SetURL(url);
138 url_request_.SetMethod(
"GET
");
139 url_request_.SetRecordDownloadProgress(true);
142 <h3 id=
"downloading-the-data">Downloading the data
</h3>
143 <p><code>Start
</code> in
<code>url_loader_handler.cc
</code> creates a callback (
<code>cc
</code>) using a
144 <code>CompletionCallbackFactory
</code>. The callback is passed to
<code>Open
</code> to be called
145 upon its completion.
<code>Open
</code> begins loading the
<code>URLRequestInfo
</code>.
</p>
146 <pre class=
"prettyprint">
147 void URLLoaderHandler::Start() {
148 pp::CompletionCallback cc =
149 cc_factory_.NewCallback(
&URLLoaderHandler::OnOpen);
150 url_loader_.Open(url_request_, cc);
153 <p><code>OnOpen
</code> ensures that the Open call was successful and, if so, calls
154 <code>GetDownloadProgress
</code> to determine the amount of data to be downloaded so it
155 can allocate memory for the response body.
</p>
156 <p>Note that the amount of data to be downloaded may be unknown, in which case
157 <code>GetDownloadProgress
</code> sets
<code>total_bytes_to_be_received
</code> to -
1. It is not a
158 problem if
<code>total_bytes_to_be_received
</code> is set to -
1 or if
159 <code>GetDownloadProgress
</code> fails; in these scenarios memory for the read buffer
160 can
’t be allocated in advance and must be allocated as data is received.
</p>
161 <p>Finally,
<code>OnOpen
</code> calls
<code>ReadBody.
</code></p>
162 <pre class=
"prettyprint">
163 void URLLoaderHandler::OnOpen(int32_t result) {
164 if (result != PP_OK) {
165 ReportResultAndDie(url_,
"pp::URLLoader::Open() failed
", false);
168 int64_t bytes_received =
0;
169 int64_t total_bytes_to_be_received =
0;
170 if (url_loader_.GetDownloadProgress(
&bytes_received,
171 &total_bytes_to_be_received)) {
172 if (total_bytes_to_be_received
> 0) {
173 url_response_body_.reserve(total_bytes_to_be_received);
176 url_request_.SetRecordDownloadProgress(false);
180 <p><code>ReadBody
</code> creates another
<code>CompletionCallback
</code> (a
<code>NewOptionalCallback
</code>)
181 and passes it to
<code>ReadResponseBody,
</code> which reads the response body, and
182 <code>AppendDataBytes,
</code> which appends the resulting data to the previously read
184 <pre class=
"prettyprint">
185 void URLLoaderHandler::ReadBody() {
186 pp::CompletionCallback cc =
187 cc_factory_.NewOptionalCallback(
&URLLoaderHandler::OnRead);
188 int32_t result = PP_OK;
190 result = url_loader_.ReadResponseBody(buffer_, READ_BUFFER_SIZE, cc);
192 AppendDataBytes(buffer_, result);
194 } while (result
> 0);
196 if (result != PP_OK_COMPLETIONPENDING) {
201 void URLLoaderHandler::AppendDataBytes(const char* buffer, int32_t num_bytes) {
202 if (num_bytes
<=
0)
204 num_bytes = std::min(READ_BUFFER_SIZE, num_bytes);
205 url_response_body_.insert(
206 url_response_body_.end(), buffer, buffer + num_bytes);
209 <p>Eventually either all the bytes have been read for the entire file (resulting
210 in
<code>PP_OK
</code> or
0), all the bytes have been read for what has been
211 downloaded, but more is to be downloaded (
<code>PP_OK_COMPLETIONPENDING
</code> or -
1),
212 or there is an error (less than -
1).
<code>OnRead
</code> is called in the event of an
213 error or
<code>PP_OK
</code>.
</p>
214 <h3 id=
"displaying-a-result">Displaying a result
</h3>
215 <p>OnRead calls
<code>ReportResultAndDie
</code> when either an error or
<code>PP_OK
</code> is
216 returned to indicate streaming of file is complete.
<code>ReportResultAndDie
</code> then
217 calls
<code>ReportResult,
</code> which calls
<code>PostMessage
</code> to send the result back to
221 {{/partials.standard_nacl_article}}