diff options
author | binji <binji@chromium.org> | 2015-01-22 10:50:53 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-01-22 18:52:19 +0000 |
commit | 9ec85756f3459c36957863e4c55bc40a8c2c8713 (patch) | |
tree | 7ec8acb9f644c48ca83ee15c906a38bb52aa146e /native_client_sdk | |
parent | 81322057a224333cb87afaed0aca693af0a690f4 (diff) | |
download | chromium_src-9ec85756f3459c36957863e4c55bc40a8c2c8713.zip chromium_src-9ec85756f3459c36957863e4c55bc40a8c2c8713.tar.gz chromium_src-9ec85756f3459c36957863e4c55bc40a8c2c8713.tar.bz2 |
[NaCl SDK] Change file_io example to use pp::VarArray.
Also add rename() command.
BUG=none
R=sbc@chromium.org
Review URL: https://codereview.chromium.org/829353004
Cr-Commit-Position: refs/heads/master@{#312645}
Diffstat (limited to 'native_client_sdk')
4 files changed, 154 insertions, 64 deletions
diff --git a/native_client_sdk/src/examples/api/file_io/example.js b/native_client_sdk/src/examples/api/file_io/example.js index 81a4717..14fcc10 100644 --- a/native_client_sdk/src/examples/api/file_io/example.js +++ b/native_client_sdk/src/examples/api/file_io/example.js @@ -8,7 +8,7 @@ function moduleDidLoad() { // Called by the common.js module. function domContentLoaded(name, tc, config, width, height) { - navigator.webkitPersistentStorage.requestQuota(1024 * 1024, + navigator.webkitPersistentStorage.requestQuota(5 * 1024 * 1024, function(bytes) { common.updateStatus( 'Allocated ' + bytes + ' bytes of persistant storage.'); @@ -35,6 +35,7 @@ function attachListeners() { addEventListenerToButton('delete', deleteFileOrDirectory); addEventListenerToButton('listDir', listDir); addEventListenerToButton('makeDir', makeDir); + addEventListenerToButton('rename', rename); } function onRadioClicked(e) { @@ -51,15 +52,10 @@ function onRadioClicked(e) { function makeMessage(command, path) { // Package a message using a simple protocol containing: - // command <path length> <path> <space-separated extra args> - var msg = command; - msg += ' '; - msg += path.length; - msg += ' '; - msg += path; - // Maybe add extra args + // [command, <path>, <extra args>...] + var msg = [command, path]; for (var i = 2; i < arguments.length; ++i) { - msg += ' ' + arguments[i]; + msg.push(arguments[i]); } return msg; } @@ -68,7 +64,7 @@ function saveFile() { if (common.naclModule) { var fileName = document.querySelector('#saveFile input').value; var fileText = document.querySelector('#saveFile textarea').value; - common.naclModule.postMessage(makeMessage('sv', fileName, fileText)); + common.naclModule.postMessage(makeMessage('save', fileName, fileText)); // clear the editor. fileText.value = ''; } @@ -80,37 +76,44 @@ function loadFile() { // clear the editor first (in case there is an error and there is no // output). document.querySelector('#loadFile textarea').value = ''; - common.naclModule.postMessage(makeMessage('ld', fileName)); + common.naclModule.postMessage(makeMessage('load', fileName)); } } function deleteFileOrDirectory() { if (common.naclModule) { var fileName = document.querySelector('#delete input').value; - common.naclModule.postMessage(makeMessage('de', fileName)); + common.naclModule.postMessage(makeMessage('delete', fileName)); } } function listDir() { if (common.naclModule) { var dirName = document.querySelector('#listDir input').value; - common.naclModule.postMessage(makeMessage('ls', dirName)); + common.naclModule.postMessage(makeMessage('list', dirName)); } } function makeDir() { if (common.naclModule) { var dirName = document.querySelector('#makeDir input').value; - common.naclModule.postMessage(makeMessage('md', dirName)); + common.naclModule.postMessage(makeMessage('makedir', dirName)); + } +} + +function rename() { + if (common.naclModule) { + var oldName = document.querySelector('#renameOld').value; + var newName = document.querySelector('#renameNew').value; + common.naclModule.postMessage(makeMessage('rename', oldName, newName)); } } // Called by the common.js module. function handleMessage(message_event) { var msg = message_event.data; - var parts = msg.split('|'); - var command = parts[0]; - var args = parts.slice(1); + var command = msg[0]; + var args = msg.slice(1); if (command == 'ERR') { common.logMessage('Error: ' + args[0]); diff --git a/native_client_sdk/src/examples/api/file_io/file_io.cc b/native_client_sdk/src/examples/api/file_io/file_io.cc index ae8df85..2f3eaae 100644 --- a/native_client_sdk/src/examples/api/file_io/file_io.cc +++ b/native_client_sdk/src/examples/api/file_io/file_io.cc @@ -6,8 +6,11 @@ /// This example demonstrates the use of persistent file I/O #define __STDC_LIMIT_MACROS +#include <stdio.h> + #include <sstream> #include <string> +#include <vector> #include "ppapi/c/pp_stdint.h" #include "ppapi/c/ppb_file_io.h" @@ -19,6 +22,7 @@ #include "ppapi/cpp/message_loop.h" #include "ppapi/cpp/module.h" #include "ppapi/cpp/var.h" +#include "ppapi/cpp/var_array.h" #include "ppapi/utility/completion_callback_factory.h" #include "ppapi/utility/threading/simple_thread.h" @@ -36,12 +40,7 @@ #endif namespace { -/// Used for our simple protocol to communicate with Javascript -const char* const kLoadPrefix = "ld"; -const char* const kSavePrefix = "sv"; -const char* const kDeletePrefix = "de"; -const char* const kListPrefix = "ls"; -const char* const kMakeDirPrefix = "md"; +typedef std::vector<std::string> StringVector; } /// The Instance class. One of these exists for each instance of your NaCl @@ -87,6 +86,26 @@ class FileIoInstance : public pp::Instance { // We do all our file operations on the file_thread_. pp::SimpleThread file_thread_; + void PostArrayMessage(const char* command, const StringVector& strings) { + pp::VarArray message; + message.Set(0, command); + for (size_t i = 0; i < strings.size(); ++i) { + message.Set(i + 1, strings[i]); + } + + PostMessage(message); + } + + void PostArrayMessage(const char* command) { + PostArrayMessage(command, StringVector()); + } + + void PostArrayMessage(const char* command, std::string s) { + StringVector sv; + sv.push_back(s); + PostArrayMessage(command, sv); + } + /// Handler for messages coming in from the browser via postMessage(). The /// @a var_message can contain anything: a JSON string; a string that encodes /// method names and arguments; etc. @@ -95,47 +114,44 @@ class FileIoInstance : public pp::Instance { /// /// @param[in] var_message The message posted by the browser. virtual void HandleMessage(const pp::Var& var_message) { - if (!var_message.is_string()) + if (!var_message.is_array()) return; - // Parse message into: instruction file_name_length file_name [file_text] - std::string message = var_message.AsString(); - std::string instruction; - std::string file_name; - std::stringstream reader(message); - int file_name_length; - - reader >> instruction >> file_name_length; - file_name.resize(file_name_length); - reader.ignore(1); // Eat the delimiter - reader.read(&file_name[0], file_name_length); + // Message should be an array with the following elements: + // [command, path, extra args] + pp::VarArray message(var_message); + std::string command = message.Get(0).AsString(); + std::string file_name = message.Get(1).AsString(); if (file_name.length() == 0 || file_name[0] != '/') { ShowStatusMessage("File name must begin with /"); return; } - // Dispatch the instruction - if (instruction == kLoadPrefix) { + printf("command: %s file_name: %s\n", command.c_str(), file_name.c_str()); + + if (command == "load") { file_thread_.message_loop().PostWork( callback_factory_.NewCallback(&FileIoInstance::Load, file_name)); - } else if (instruction == kSavePrefix) { - // Read the rest of the message as the file text - reader.ignore(1); // Eat the delimiter - std::string file_text = message.substr(reader.tellg()); + } else if (command == "save") { + std::string file_text = message.Get(2).AsString(); file_thread_.message_loop().PostWork(callback_factory_.NewCallback( &FileIoInstance::Save, file_name, file_text)); - } else if (instruction == kDeletePrefix) { + } else if (command == "delete") { file_thread_.message_loop().PostWork( callback_factory_.NewCallback(&FileIoInstance::Delete, file_name)); - } else if (instruction == kListPrefix) { + } else if (command == "list") { const std::string& dir_name = file_name; file_thread_.message_loop().PostWork( callback_factory_.NewCallback(&FileIoInstance::List, dir_name)); - } else if (instruction == kMakeDirPrefix) { + } else if (command == "makedir") { const std::string& dir_name = file_name; file_thread_.message_loop().PostWork( callback_factory_.NewCallback(&FileIoInstance::MakeDir, dir_name)); + } else if (command == "rename") { + const std::string new_name = message.Get(2).AsString(); + file_thread_.message_loop().PostWork(callback_factory_.NewCallback( + &FileIoInstance::Rename, file_name, new_name)); } } @@ -144,7 +160,7 @@ class FileIoInstance : public pp::Instance { if (rv == PP_OK) { file_system_ready_ = true; // Notify the user interface that we're ready - PostMessage("READY|"); + PostArrayMessage("READY"); } else { ShowErrorMessage("Failed to open file system", rv); } @@ -250,7 +266,7 @@ class FileIoInstance : public pp::Instance { } // Done reading, send content to the user interface std::string string_data(data.begin(), data.end()); - PostMessage("DISP|" + string_data); + PostArrayMessage("DISP", string_data); ShowStatusMessage("Load success"); } @@ -293,15 +309,14 @@ class FileIoInstance : public pp::Instance { return; } - std::stringstream ss; - ss << "LIST"; + StringVector sv; for (size_t i = 0; i < entries.size(); ++i) { pp::Var name = entries[i].file_ref().GetName(); if (name.is_string()) { - ss << "|" << name.AsString(); + sv.push_back(name.AsString()); } } - PostMessage(ss.str()); + PostArrayMessage("LIST", sv); ShowStatusMessage("List success"); } @@ -321,18 +336,34 @@ class FileIoInstance : public pp::Instance { ShowStatusMessage("Make directory success"); } + void Rename(int32_t /* result */, + const std::string& old_name, + const std::string& new_name) { + if (!file_system_ready_) { + ShowErrorMessage("File system is not open", PP_ERROR_FAILED); + return; + } + + pp::FileRef ref_old(file_system_, old_name.c_str()); + pp::FileRef ref_new(file_system_, new_name.c_str()); + + int32_t result = ref_old.Rename(ref_new, pp::BlockUntilComplete()); + if (result != PP_OK) { + ShowErrorMessage("Rename failed", result); + return; + } + ShowStatusMessage("Rename success"); + } + /// Encapsulates our simple javascript communication protocol void ShowErrorMessage(const std::string& message, int32_t result) { std::stringstream ss; - ss << "ERR|" << message << " -- Error #: " << result; - PostMessage(ss.str()); + ss << message << " -- Error #: " << result; + PostArrayMessage("ERR", ss.str()); } - /// Encapsulates our simple javascript communication protocol void ShowStatusMessage(const std::string& message) { - std::stringstream ss; - ss << "STAT|" << message; - PostMessage(ss.str()); + PostArrayMessage("STAT", message); } }; diff --git a/native_client_sdk/src/examples/api/file_io/index.html b/native_client_sdk/src/examples/api/file_io/index.html index f08a4d0..87e4f27 100644 --- a/native_client_sdk/src/examples/api/file_io/index.html +++ b/native_client_sdk/src/examples/api/file_io/index.html @@ -26,6 +26,7 @@ <input type="radio" id="radio_delete" name="group">Delete File/Directory <input type="radio" id="radio_listDir" name="group">List Directory <input type="radio" id="radio_makeDir" name="group">Make Directory + <input type="radio" id="radio_rename" name="group">Rename </span> </div> <div class="function" id="saveFile"> @@ -75,6 +76,17 @@ <button>Make Directory</button> </span> </div> + <div class="function" id="rename" hidden> + <div> + Old name: + <input id="renameOld" type="text" value="/filename.txt"> + </div> + <div> + New name: + <input id="renameNew" type="text" value="/filename2.txt"> + </div> + <button>Rename</button> + </div> <pre id="log" style="font-weight: bold"></pre> <!-- The NaCl plugin will be embedded inside the element with id "listener". diff --git a/native_client_sdk/src/examples/api/file_io/test.js b/native_client_sdk/src/examples/api/file_io/test.js index bcf2b0e..7ec3662 100644 --- a/native_client_sdk/src/examples/api/file_io/test.js +++ b/native_client_sdk/src/examples/api/file_io/test.js @@ -19,9 +19,13 @@ function addTests() { dispatchClick(document.getElementById('radio_' + name)); } - function setInputValue(value) { + function setInputValue(value, selector) { + if (!selector) { + selector = 'input'; + } + currentTest.log('Setting input box to "' + value + '".'); - getVisibleElementByTagName('input').value = value; + getVisibleElementByTagName(selector).value = value; } function setTextareaValue(value) { @@ -40,12 +44,6 @@ function addTests() { } function waitForLog(logMessage, onLogChanged, onError) { - // First see if the message we want is already there. - if (getLastLogMessage() === logMessage) { - onLogChanged(); - return; - } - // Clear the log. This prevents a previous failure from propagating to the // current check. (NOTE: the log is backed by an array, so as soon as a // message is logged it will be refilled with its previous data in addition @@ -132,6 +130,13 @@ function addTests() { onDirectoryMade, onError); } + function rename(oldname, newname, onRenamed, onError) { + clickRadio('rename'); + setInputValue(oldname, '#renameOld'); + setInputValue(newname, '#renameNew'); + clickExecuteButtonAndWaitForLog('Rename success', onRenamed, onError); + } + function expectEq(expected, actual, additionalInfo) { var message; if (expected !== actual) { @@ -173,6 +178,14 @@ function addTests() { // This is a bit fragile; we rely on this test being run first (and // completing) before we can run any of the other tests. currentTest = test; + var message = 'Filesystem ready!'; + + // This message may already be logged. + if (getLastLogMessage() == message) { + test.pass(); + return; + } + waitForLog('Filesystem ready!', function() { test.pass(); }, function() { @@ -250,4 +263,35 @@ function addTests() { }); }); }); + + common.tester.addAsyncTest('rename_file', function(test) { + currentTest = test; + var filename = '/rename_old.txt'; + var newFilename = '/rename_new.txt'; + var fileText = 'What\'s in a name? that which we call a rose ' + + 'by any other name would smell as sweet;'; + + // Save the file. + saveFile(filename, fileText, function() { + // Now rename it. + rename(filename, newFilename, function() { + // Now try to load it. + loadFile(newFilename, function() { + // Make sure the text matches. + expectEq(fileText, getTextareaValue(), 'Incorrect textarea'); + + // Make sure the old file no longer exists. + loadFile(filename, function() { + test.fail('Unexpected load success.'); + }, + function() { + expectEq('', getTextareaValue(), 'Unexpected data in file'); + expectContains('File not found', getLastLogMessage(), + 'Unexpected log message'); + test.pass(); + }); + }); + }); + }); + }); } |