summaryrefslogtreecommitdiffstats
path: root/native_client_sdk
diff options
context:
space:
mode:
authorbinji <binji@chromium.org>2015-01-22 10:50:53 -0800
committerCommit bot <commit-bot@chromium.org>2015-01-22 18:52:19 +0000
commit9ec85756f3459c36957863e4c55bc40a8c2c8713 (patch)
tree7ec8acb9f644c48ca83ee15c906a38bb52aa146e /native_client_sdk
parent81322057a224333cb87afaed0aca693af0a690f4 (diff)
downloadchromium_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')
-rw-r--r--native_client_sdk/src/examples/api/file_io/example.js37
-rw-r--r--native_client_sdk/src/examples/api/file_io/file_io.cc109
-rw-r--r--native_client_sdk/src/examples/api/file_io/index.html12
-rw-r--r--native_client_sdk/src/examples/api/file_io/test.js60
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();
+ });
+ });
+ });
+ });
+ });
}