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

Side by Side Diff: native_client_sdk/src/doc/_developer.chrome.com_generated/devguide/coding/file-io.html

Issue 140993006: [NaCl SDK Docs] Check in the generated NaCl SDK Documentation. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: try without pepper_{dev,beta,stable} Created 6 years, 11 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
(Empty)
1 {{+bindTo:partials.standard_nacl_article}}
2
3 <section id="file-i-o">
4 <span id="devguide-coding-fileio"></span><h1 id="file-i-o"><span id="devguide-co ding-fileio"></span>File I/O</h1>
5 <div class="contents local topic" id="contents">
6 <ul class="small-gap">
7 <li><a class="reference internal" href="#introduction" id="id2">Introduction</a> </li>
8 <li><a class="reference internal" href="#reference-information" id="id3">Referen ce information</a></li>
9 <li><p class="first"><a class="reference internal" href="#local-file-i-o" id="id 4">Local file I/O</a></p>
10 <ul class="small-gap">
11 <li><a class="reference internal" href="#enabling-local-file-i-o" id="id5">Enabl ing local file I/O</a></li>
12 <li><a class="reference internal" href="#testing-local-file-i-o" id="id6">Testin g local file I/O</a></li>
13 </ul>
14 </li>
15 <li><p class="first"><a class="reference internal" href="#the-file-io-example" i d="id7">The <code>file_io</code> example</a></p>
16 <ul class="small-gap">
17 <li><a class="reference internal" href="#file-i-o-overview" id="id8">File I/O ov erview</a></li>
18 <li><a class="reference internal" href="#creating-and-writing-a-file" id="id9">C reating and writing a file</a></li>
19 <li><a class="reference internal" href="#opening-and-reading-a-file" id="id10">O pening and reading a file</a></li>
20 <li><a class="reference internal" href="#deleting-a-file" id="id11">Deleting a f ile</a></li>
21 <li><a class="reference internal" href="#making-a-directory" id="id12">Making a directory</a></li>
22 <li><a class="reference internal" href="#listing-the-contents-of-a-directory" id ="id13">Listing the contents of a directory</a></li>
23 </ul>
24 </li>
25 <li><p class="first"><a class="reference internal" href="#file-io-deep-dive" id= "id14"><code>file_io</code> deep dive</a></p>
26 <ul class="small-gap">
27 <li><a class="reference internal" href="#opening-a-file-system-and-preparing-for -file-i-o" id="id15">Opening a file system and preparing for file I/O</a></li>
28 <li><a class="reference internal" href="#handling-messages-from-javascript" id=" id16">Handling messages from JavaScript</a></li>
29 <li><a class="reference internal" href="#saving-a-file" id="id17">Saving a file< /a></li>
30 <li><a class="reference internal" href="#loading-a-file" id="id18">Loading a fil e</a></li>
31 <li><a class="reference internal" href="#id1" id="id19">Deleting a file</a></li>
32 <li><a class="reference internal" href="#listing-files-in-a-directory" id="id20" >Listing files in a directory</a></li>
33 <li><a class="reference internal" href="#making-a-new-directory" id="id21">Makin g a new directory</a></li>
34 </ul>
35 </li>
36 </ul>
37 </div>
38 <section id="introduction">
39 <h2 id="introduction">Introduction</h2>
40 <p>This chapter describes how to use the <a class="reference external" href="htt ps://developers.google.com/native-client/peppercpp/classpp_1_1_file_i_o">FileIO API</a>
41 to read and write files using a local secure data store.</p>
42 <p>You might use the File IO API with the URL Loading APIs to create an overall
43 data download and caching solution for your NaCl applications. For example:</p>
44 <ol class="arabic simple">
45 <li>Use the File IO APIs to check the local disk to see if a file exists that
46 your program needs.</li>
47 <li>If the file exists locally, load it into memory using the File IO API. If
48 the file doesn&#8217;t exist locally, use the URL Loading API to retrieve the
49 file from the server.</li>
50 <li>Use the File IO API to write the file to disk.</li>
51 <li>Load the file into memory using the File IO API when needed by your
52 application.</li>
53 </ol>
54 <p>The example discussed in this chapter is included in the SDK in the directory
55 <code>examples/api/file_io</code>.</p>
56 </section><section id="reference-information">
57 <h2 id="reference-information">Reference information</h2>
58 <p>For reference information related to FileIO, see the following documentation: </p>
59 <ul class="small-gap">
60 <li><a class="reference external" href="https://developers.google.com/native-cli ent/peppercpp/file__io_8h">file_io.h</a> - API
61 to create a FileIO object</li>
62 <li><a class="reference external" href="https://developers.google.com/native-cli ent/peppercpp/file__ref_8h">file_ref.h</a> - API
63 to create a file reference or &#8220;weak pointer&#8221; to a file in a file sys tem</li>
64 <li><a class="reference external" href="https://developers.google.com/native-cli ent/peppercpp/file__system_8h">file_system.h</a> -
65 API to create a file system associated with a file</li>
66 </ul>
67 </section><section id="local-file-i-o">
68 <h2 id="local-file-i-o">Local file I/O</h2>
69 <p>Chrome provides an obfuscated, restricted area on disk to which a web app can
70 safely <a class="reference external" href="https://developers.google.com/chrome/ whitepapers/storage#persistent">read and write files</a>. The
71 Pepper FileIO, FileRef, and FileSystem APIs (collectively called the File IO
72 APIs) allow you to access this sandboxed local disk so you can read and write
73 files and manage caching yourself. The data is persistent between launches of
74 Chrome, and is not removed unless your application deletes it or the user
75 manually deletes it. There is no limit to the amount of local data you can
76 use, other than the actual space available on the local drive.</p>
77 <section id="enabling-local-file-i-o">
78 <span id="enabling-file-access"></span><span id="quota-management"></span><h3 id ="enabling-local-file-i-o"><span id="enabling-file-access"></span><span id="quot a-management"></span>Enabling local file I/O</h3>
79 <p>The easiest way to enable the writing of persistent local data is to include
80 the <a class="reference external" href="http://developer.chrome.com/extensions/d eclare_permissions.html#unlimitedStorage">unlimitedStorage permission</a>
81 in your Chrome Web Store manifest file. With this permission you can use the
82 Pepper FileIO API without the need to request disk space at run time. When
83 the user installs the app Chrome displays a message announcing that the app
84 writes to the local disk.</p>
85 <p>If you do not use the <code>unlimitedStorage</code> permission you must inclu de
86 JavaScript code that calls the <a class="reference external" href="http://update s.html5rocks.com/2011/11/Quota-Management-API-Fast-Facts">HTML5 Quota Management API</a> to
87 explicitly request local disk space before using the FileIO API. In this case
88 Chrome will prompt the user to accept a requestQuota call every time one is
89 made.</p>
90 </section><section id="testing-local-file-i-o">
91 <h3 id="testing-local-file-i-o">Testing local file I/O</h3>
92 <p>You should be aware that using the <code>unlimitedStorage</code> manifest per mission
93 constrains the way you can test your app. Three of the four techniques
94 described in <a class="reference internal" href="/native-client/devguide/devcycl e/running.html"><em>Running Native Client Applications</em></a>
95 read the Chrome Web Store manifest file and enable the <code>unlimitedStorage</c ode>
96 permission when it appears, but the first technique (local server) does not.
97 If you want to test the file IO portion of your app with a simple local server,
98 you need to include JavaScript code that calls the HTML5 Quota Management API.
99 When you deliver your application you can replace this code with the
100 <code>unlimitedStorage</code> manifest permission.</p>
101 </section></section><section id="the-file-io-example">
102 <h2 id="the-file-io-example">The <code>file_io</code> example</h2>
103 <p>The Native Client SDK includes an example, <code>file_io</code>, that demonst rates how
104 to read and write a local disk file. Since you will probably run the example
105 from a local server without a Chrome Web Store manifest file, the example&#8217; s
106 index file uses JavaScript to perform the Quota Management setup as described
107 above. The example has these primary files:</p>
108 <ul class="small-gap">
109 <li><code>index.html</code> - The HTML code that launches the Native Client modu le and
110 displays the user interface.</li>
111 <li><code>example.js</code> - JavaScript code that requests quota (as described above). It
112 also listens for user interaction with the user interface, and forwards the
113 requests to the Native Client module.</li>
114 <li><code>file_io.cc</code> - The code that sets up and provides an entry point to the
115 Native Client module.</li>
116 </ul>
117 <p>The remainder of this section covers the code in the <code>file_io.cc</code> file for
118 reading and writing files.</p>
119 <section id="file-i-o-overview">
120 <h3 id="file-i-o-overview">File I/O overview</h3>
121 <p>Like many Pepper APIs, the File IO API includes a set of methods that execute
122 asynchronously and that invoke callback functions in your Native Client module.
123 Unlike most other examples, the <code>file_io</code> example also demonstrates h ow to
124 make Pepper calls synchronously on a worker thread.</p>
125 <p>It is illegal to make blocking calls to Pepper on the module&#8217;s main thr ead.
126 This restriction is lifted when running on a worker thread&#8212;this is called
127 &#8220;calling Pepper off the main thread&#8221;. This often simplifies the logi c of your
128 code; multiple asynchronous Pepper functions can be called from one function on
129 your worker thread, so you can use the stack and standard control flow
130 structures normally.</p>
131 <p>The high-level flow for the <code>file_io</code> example is described below. Note that
132 methods in the namespace <code>pp</code> are part of the Pepper C++ API.</p>
133 </section><section id="creating-and-writing-a-file">
134 <h3 id="creating-and-writing-a-file">Creating and writing a file</h3>
135 <p>Following are the high-level steps involved in creating and writing to a
136 file:</p>
137 <ol class="arabic simple">
138 <li><code>pp::FileIO::Open</code> is called with the <code>PP_FILEOPEN_FLAG_CREA TE</code> flag to
139 create a file. Because the callback function is <code>pp::BlockUntilComplete</c ode>,
140 this thread is blocked until <code>Open</code> succeeds or fails.</li>
141 <li><code>pp::FileIO::Write</code> is called to write the contents. Again, the t hread is
142 blocked until the call to <code>Write</code> completes. If there is more data to
143 write, <code>Write</code> is called again.</li>
144 <li>When there is no more data to write, call <code>pp::FileIO::Flush</code>.</l i>
145 </ol>
146 </section><section id="opening-and-reading-a-file">
147 <h3 id="opening-and-reading-a-file">Opening and reading a file</h3>
148 <p>Following are the high-level steps involved in opening and reading a file:</p >
149 <ol class="arabic simple">
150 <li><code>pp::FileIO::Open</code> is called to open the file. Because the callba ck
151 function is <code>pp::BlockUntilComplete</code>, this thread is blocked until Op en
152 succeeds or fails.</li>
153 <li><code>pp::FileIO::Query</code> is called to query information about the file , such as
154 its file size. The thread is blocked until <code>Query</code> completes.</li>
155 <li><code>pp::FileIO::Read</code> is called to read the contents. The thread is blocked
156 until <code>Read</code> completes. If there is more data to read, <code>Read</co de> is called
157 again.</li>
158 </ol>
159 </section><section id="deleting-a-file">
160 <h3 id="deleting-a-file">Deleting a file</h3>
161 <p>Deleting a file is straightforward: call <code>pp::FileRef::Delete</code>. Th e thread is
162 blocked until <code>Delete</code> completes.</p>
163 </section><section id="making-a-directory">
164 <h3 id="making-a-directory">Making a directory</h3>
165 <p>Making a directory is also straightforward: call <code>pp::File::MakeDirector y</code>.
166 The thread is blocked until <code>MakeDirectory</code> completes.</p>
167 </section><section id="listing-the-contents-of-a-directory">
168 <h3 id="listing-the-contents-of-a-directory">Listing the contents of a directory </h3>
169 <p>Following are the high-level steps involved in listing a directory:</p>
170 <ol class="arabic simple">
171 <li><code>pp::FileRef::ReadDirectoryEntries</code> is called, and given a direct ory entry
172 to list. A callback is given as well; many of the other functions use
173 <code>pp::BlockUntilComplete</code>, but <code>ReadDirectoryEntries</code> retur ns results in
174 its callback, so it must be specified.</li>
175 <li>When the call to <code>ReadDirectoryEntries</code> completes, it calls
176 <code>ListCallback</code> which packages up the results into a string message, a nd
177 sends it to JavaScript.</li>
178 </ol>
179 </section></section><section id="file-io-deep-dive">
180 <h2 id="file-io-deep-dive"><code>file_io</code> deep dive</h2>
181 <p>The <code>file_io</code> example displays a user interface with a couple of f ields and
182 several buttons. Following is a screenshot of the <code>file_io</code> example:< /p>
183 <img alt="/native-client/images/fileioexample.png" src="/native-client/images/fi leioexample.png" />
184 <p>Each radio button is a file operation you can perform, with some reasonable
185 default values for filenames. Try typing a message in the large input box and
186 clicking <code>Save</code>, then switching to the <code>Load File</code> operati on, and
187 clicking <code>Load</code>.</p>
188 <p>Let&#8217;s take a look at what is going on under the hood.</p>
189 <section id="opening-a-file-system-and-preparing-for-file-i-o">
190 <h3 id="opening-a-file-system-and-preparing-for-file-i-o">Opening a file system and preparing for file I/O</h3>
191 <p><code>pp::Instance::Init</code> is called when an instance of a module is cre ated. In
192 this example, <code>Init</code> starts a new thread (via the <code>pp::SimpleThr ead</code>
193 class), and tells it to open the filesystem:</p>
194 <pre class="prettyprint">
195 virtual bool Init(uint32_t /*argc*/,
196 const char * /*argn*/ [],
197 const char * /*argv*/ []) {
198 file_thread_.Start();
199 // Open the file system on the file_thread_. Since this is the first
200 // operation we perform there, and because we do everything on the
201 // file_thread_ synchronously, this ensures that the FileSystem is open
202 // before any FileIO operations execute.
203 file_thread_.message_loop().PostWork(
204 callback_factory_.NewCallback(&amp;FileIoInstance::OpenFileSystem));
205 return true;
206 }
207 </pre>
208 <p>When the file thread starts running, it will call <code>OpenFileSystem</code> . This
209 calls <code>pp::FileSystem::Open</code> and blocks the file thread until the fun ction
210 returns.</p>
211 <aside class="note">
212 Note that the call to <code>pp::FileSystem::Open</code> uses
213 <code>pp::BlockUntilComplete</code> as its callback. This is only possible becau se we
214 are running off the main thread; if you try to make a blocking call from the
215 main thread, the function will return the error
216 <code>PP_ERROR_BLOCKS_MAIN_THREAD</code>.
217 </aside>
218 <pre class="prettyprint">
219 void OpenFileSystem(int32_t /*result*/) {
220 int32_t rv = file_system_.Open(1024 * 1024, pp::BlockUntilComplete());
221 if (rv == PP_OK) {
222 file_system_ready_ = true;
223 // Notify the user interface that we're ready
224 PostMessage(&quot;READY|&quot;);
225 } else {
226 ShowErrorMessage(&quot;Failed to open file system&quot;, rv);
227 }
228 }
229 </pre>
230 </section><section id="handling-messages-from-javascript">
231 <h3 id="handling-messages-from-javascript">Handling messages from JavaScript</h3 >
232 <p>When you click the <code>Save</code> button, JavaScript posts a message to th e NaCl
233 module with the file operation to perform sent as a string (See <a class="refere nce internal" href="/native-client/devguide/coding/message-system.html"><em>Mess aging
234 System</em></a> for more details on message passing). The string is
235 parsed by <code>HandleMessage</code>, and new work is added to the file thread:< /p>
236 <pre class="prettyprint">
237 virtual void HandleMessage(const pp::Var&amp; var_message) {
238 if (!var_message.is_string())
239 return;
240
241 // Parse message into: instruction file_name_length file_name [file_text]
242 std::string message = var_message.AsString();
243 std::string instruction;
244 std::string file_name;
245 std::stringstream reader(message);
246 int file_name_length;
247
248 reader &gt;&gt; instruction &gt;&gt; file_name_length;
249 file_name.resize(file_name_length);
250 reader.ignore(1); // Eat the delimiter
251 reader.read(&amp;file_name[0], file_name_length);
252
253 ...
254
255 // Dispatch the instruction
256 if (instruction == kLoadPrefix) {
257 file_thread_.message_loop().PostWork(
258 callback_factory_.NewCallback(&amp;FileIoInstance::Load, file_name));
259 } else if (instruction == kSavePrefix) {
260 ...
261 }
262 }
263 </pre>
264 </section><section id="saving-a-file">
265 <h3 id="saving-a-file">Saving a file</h3>
266 <p><code>FileIoInstance::Save</code> is called when the <code>Save</code> button is pressed. First,
267 it checks to see that the FileSystem has been successfully opened:</p>
268 <pre class="prettyprint">
269 if (!file_system_ready_) {
270 ShowErrorMessage(&quot;File system is not open&quot;, PP_ERROR_FAILED);
271 return;
272 }
273 </pre>
274 <p>It then creates a <code>pp::FileRef</code> resource with the name of the file . A
275 <code>FileRef</code> resource is a weak reference to a file in the FileSystem; t hat is,
276 a file can still be deleted even if there are outstanding <code>FileRef</code>
277 resources.</p>
278 <pre class="prettyprint">
279 pp::FileRef ref(file_system_, file_name.c_str());
280 </pre>
281 <p>Next, a <code>pp::FileIO</code> resource is created and opened. The call to
282 <code>pp::FileIO::Open</code> passes <code>PP_FILEOPEFLAG_WRITE</code> to open t he file for
283 writing, <code>PP_FILEOPENFLAG_CREATE</code> to create a new file if it doesn&#8 217;t already
284 exist and <code>PP_FILEOPENFLAG_TRUNCATE</code> to clear the file of any previou s
285 content:</p>
286 <pre class="prettyprint">
287 pp::FileIO file(this);
288
289 int32_t open_result =
290 file.Open(ref,
291 PP_FILEOPENFLAG_WRITE | PP_FILEOPENFLAG_CREATE |
292 PP_FILEOPENFLAG_TRUNCATE,
293 pp::BlockUntilComplete());
294 if (open_result != PP_OK) {
295 ShowErrorMessage(&quot;File open for write failed&quot;, open_result);
296 return;
297 }
298 </pre>
299 <p>Now that the file is opened, it is written to in chunks. In an asynchronous
300 model, this would require writing a separate function, storing the current
301 state on the free store and a chain of callbacks. Because this function is
302 called off the main thread, <code>pp::FileIO::Write</code> can be called synchro nously
303 and a conventional do/while loop can be used:</p>
304 <pre class="prettyprint">
305 int64_t offset = 0;
306 int32_t bytes_written = 0;
307 do {
308 bytes_written = file.Write(offset,
309 file_contents.data() + offset,
310 file_contents.length(),
311 pp::BlockUntilComplete());
312 if (bytes_written &gt; 0) {
313 offset += bytes_written;
314 } else {
315 ShowErrorMessage(&quot;File write failed&quot;, bytes_written);
316 return;
317 }
318 } while (bytes_written &lt; static_cast&lt;int64_t&gt;(file_contents.length()));
319 </pre>
320 <p>Finally, the file is flushed to push all changes to disk:</p>
321 <pre class="prettyprint">
322 int32_t flush_result = file.Flush(pp::BlockUntilComplete());
323 if (flush_result != PP_OK) {
324 ShowErrorMessage(&quot;File fail to flush&quot;, flush_result);
325 return;
326 }
327 </pre>
328 </section><section id="loading-a-file">
329 <h3 id="loading-a-file">Loading a file</h3>
330 <p><code>FileIoInstance::Load</code> is called when the <code>Load</code> button is pressed. Like
331 the <code>Save</code> function, <code>Load</code> first checks to see if the Fil eSystem has been
332 successfully opened, and creates a new <code>FileRef</code>:</p>
333 <pre class="prettyprint">
334 if (!file_system_ready_) {
335 ShowErrorMessage(&quot;File system is not open&quot;, PP_ERROR_FAILED);
336 return;
337 }
338 pp::FileRef ref(file_system_, file_name.c_str());
339 </pre>
340 <p>Next, <code>Load</code> creates and opens a new <code>FileIO</code> resource, passing
341 <code>PP_FILEOPENFLAG_READ</code> to open the file for reading. The result is co mpared
342 to <code>PP_ERROR_FILENOTFOUND</code> to give a better error message when the fi le
343 doesn&#8217;t exist:</p>
344 <pre class="prettyprint">
345 int32_t open_result =
346 file.Open(ref, PP_FILEOPENFLAG_READ, pp::BlockUntilComplete());
347 if (open_result == PP_ERROR_FILENOTFOUND) {
348 ShowErrorMessage(&quot;File not found&quot;, open_result);
349 return;
350 } else if (open_result != PP_OK) {
351 ShowErrorMessage(&quot;File open for read failed&quot;, open_result);
352 return;
353 }
354 </pre>
355 <p>Then <code>Load</code> calls <code>pp::FileIO::Query</code> to get metadata a bout the file, such
356 as its size. This is used to allocate a <code>std::vector</code> buffer that hol ds the
357 data from the file in memory:</p>
358 <pre class="prettyprint">
359 int32_t query_result = file.Query(&amp;info, pp::BlockUntilComplete());
360 if (query_result != PP_OK) {
361 ShowErrorMessage(&quot;File query failed&quot;, query_result);
362 return;
363 }
364
365 ...
366
367 std::vector&lt;char&gt; data(info.size);
368 </pre>
369 <p>Similar to <code>Save</code>, a conventional while loop is used to read the f ile into
370 the newly allocated buffer:</p>
371 <pre class="prettyprint">
372 int64_t offset = 0;
373 int32_t bytes_read = 0;
374 int32_t bytes_to_read = info.size;
375 while (bytes_to_read &gt; 0) {
376 bytes_read = file.Read(offset,
377 &amp;data[offset],
378 data.size() - offset,
379 pp::BlockUntilComplete());
380 if (bytes_read &gt; 0) {
381 offset += bytes_read;
382 bytes_to_read -= bytes_read;
383 } else if (bytes_read &lt; 0) {
384 // If bytes_read &lt; PP_OK then it indicates the error code.
385 ShowErrorMessage(&quot;File read failed&quot;, bytes_read);
386 return;
387 }
388 }
389 </pre>
390 <p>Finally, the contents of the file are sent back to JavaScript, to be displaye d
391 on the page. This example uses &#8220;<code>DISP|</code>&#8221; as a prefix comm and for display
392 information:</p>
393 <pre class="prettyprint">
394 std::string string_data(data.begin(), data.end());
395 PostMessage(&quot;DISP|&quot; + string_data);
396 ShowStatusMessage(&quot;Load success&quot;);
397 </pre>
398 </section><section id="id1">
399 <h3 id="id1">Deleting a file</h3>
400 <p><code>FileIoInstance::Delete</code> is called when the <code>Delete</code> bu tton is pressed.
401 First, it checks whether the FileSystem has been opened, and creates a new
402 <code>FileRef</code>:</p>
403 <pre class="prettyprint">
404 if (!file_system_ready_) {
405 ShowErrorMessage(&quot;File system is not open&quot;, PP_ERROR_FAILED);
406 return;
407 }
408 pp::FileRef ref(file_system_, file_name.c_str());
409 </pre>
410 <p>Unlike <code>Save</code> and <code>Load</code>, <code>Delete</code> is called on the <code>FileRef</code> resource,
411 not a <code>FileIO</code> resource. Note that the result is checked for
412 <code>PP_ERROR_FILENOTFOUND</code> to give a better error message when trying to delete
413 a non-existent file:</p>
414 <pre class="prettyprint">
415 int32_t result = ref.Delete(pp::BlockUntilComplete());
416 if (result == PP_ERROR_FILENOTFOUND) {
417 ShowStatusMessage(&quot;File/Directory not found&quot;);
418 return;
419 } else if (result != PP_OK) {
420 ShowErrorMessage(&quot;Deletion failed&quot;, result);
421 return;
422 }
423 </pre>
424 </section><section id="listing-files-in-a-directory">
425 <h3 id="listing-files-in-a-directory">Listing files in a directory</h3>
426 <p><code>FileIoInstance::List</code> is called when the <code>List Directory</co de> button is
427 pressed. Like all other operations, it checks whether the FileSystem has been
428 opened and creates a new <code>FileRef</code>:</p>
429 <pre class="prettyprint">
430 if (!file_system_ready_) {
431 ShowErrorMessage(&quot;File system is not open&quot;, PP_ERROR_FAILED);
432 return;
433 }
434
435 pp::FileRef ref(file_system_, dir_name.c_str());
436 </pre>
437 <p>Unlike the other operations, it does not make a blocking call to
438 <code>pp::FileRef::ReadDirectoryEntries</code>. Since <code>ReadDirectoryEntries </code> returns
439 the resulting directory entries in its callback, a new callback object is
440 created pointing to <code>FileIoInstance::ListCallback</code>.</p>
441 <p>The <code>pp::CompletionCallbackFactory</code> template class is used to inst antiate a
442 new callback. Notice that the <code>FileRef</code> resource is passed as a param eter;
443 this will add a reference count to the callback object, to keep the <code>FileRe f</code>
444 resource from being destroyed when the function finishes.</p>
445 <pre class="prettyprint">
446 // Pass ref along to keep it alive.
447 ref.ReadDirectoryEntries(callback_factory_.NewCallbackWithOutput(
448 &amp;FileIoInstance::ListCallback, ref));
449 </pre>
450 <p><code>FileIoInstance::ListCallback</code> then gets the results passed as a
451 <code>std::vector</code> of <code>pp::DirectoryEntry</code> objects, and sends t hem to
452 JavaScript:</p>
453 <pre class="prettyprint">
454 void ListCallback(int32_t result,
455 const std::vector&lt;pp::DirectoryEntry&gt;&amp; entries,
456 pp::FileRef /*unused_ref*/) {
457 if (result != PP_OK) {
458 ShowErrorMessage(&quot;List failed&quot;, result);
459 return;
460 }
461
462 std::stringstream ss;
463 ss &lt;&lt; &quot;LIST&quot;;
464 for (size_t i = 0; i &lt; entries.size(); ++i) {
465 pp::Var name = entries[i].file_ref().GetName();
466 if (name.is_string()) {
467 ss &lt;&lt; &quot;|&quot; &lt;&lt; name.AsString();
468 }
469 }
470 PostMessage(ss.str());
471 ShowStatusMessage(&quot;List success&quot;);
472 }
473 </pre>
474 </section><section id="making-a-new-directory">
475 <h3 id="making-a-new-directory">Making a new directory</h3>
476 <p><code>FileIoInstance::MakeDir</code> is called when the <code>Make Directory< /code> button is
477 pressed. Like all other operations, it checks whether the FileSystem has been
478 opened and creates a new <code>FileRef</code>:</p>
479 <pre class="prettyprint">
480 if (!file_system_ready_) {
481 ShowErrorMessage(&quot;File system is not open&quot;, PP_ERROR_FAILED);
482 return;
483 }
484 pp::FileRef ref(file_system_, dir_name.c_str());
485 </pre>
486 <p>Then the <code>pp::FileRef::MakeDirectory</code> function is called.</p>
487 <pre class="prettyprint">
488 int32_t result = ref.MakeDirectory(
489 PP_MAKEDIRECTORYFLAG_NONE, pp::BlockUntilComplete());
490 if (result != PP_OK) {
491 ShowErrorMessage(&quot;Make directory failed&quot;, result);
492 return;
493 }
494 ShowStatusMessage(&quot;Make directory success&quot;);
495 </pre>
496 </section></section></section>
497
498 {{/partials.standard_nacl_article}}
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698