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

Side by Side Diff: examples/hello_world/hello_world.cc

Issue 7029032: Port hello_world (C++) to use postMessage. (Closed) Base URL: http://nativeclient-sdk.googlecode.com/svn/trunk/src/
Patch Set: Created 9 years, 7 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
1 // Copyright (c) 2011 The Native Client Authors. All rights reserved. 1 // Copyright (c) 2011 The Native Client Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 /// @file 5 /// @file
6 /// This example demonstrates loading, running and scripting a very simple NaCl 6 /// This example demonstrates loading, running and scripting a very simple NaCl
7 /// module. To load the NaCl module, the browser first looks for the 7 /// module. To load the NaCl module, the browser first looks for the
8 /// CreateModule() factory method (at the end of this file). It calls 8 /// CreateModule() factory method (at the end of this file). It calls
9 /// CreateModule() once to load the module code from your .nexe. After the 9 /// CreateModule() once to load the module code from your .nexe. After the
10 /// .nexe code is loaded, CreateModule() is not called again. 10 /// .nexe code is loaded, CreateModule() is not called again.
11 /// 11 ///
12 /// Once the .nexe code is loaded, the browser then calls the 12 /// Once the .nexe code is loaded, the browser then calls the
13 /// HelloWorldModule::CreateInstance() 13 /// HelloWorldModule::CreateInstance()
14 /// method on the object returned by CreateModule(). It calls CreateInstance() 14 /// method on the object returned by CreateModule(). It calls CreateInstance()
15 /// each time it encounters an <embed> tag that references your NaCl module. 15 /// each time it encounters an <embed> tag that references your NaCl module.
16 /// 16 ///
17 /// When the browser encounters JavaScript that references your NaCl module, it 17 /// When the browser encounters JavaScript that references your NaCl module, it
18 /// calls the GetInstanceObject() method on the object returned from 18 /// calls the GetInstanceObject() method on the object returned from
19 /// CreateInstance(). In this example, the returned object is a subclass of 19 /// CreateInstance(). In this example, the returned object is a subclass of
20 /// ScriptableObject, which handles the scripting support. 20 /// ScriptableObject, which handles the scripting support.
21 21
22 #include <ppapi/cpp/instance.h> 22 #include <ppapi/cpp/instance.h>
23 #include <ppapi/cpp/module.h> 23 #include <ppapi/cpp/module.h>
24 #include <ppapi/cpp/dev/scriptable_object_deprecated.h> 24 #include <ppapi/cpp/dev/scriptable_object_deprecated.h>
garianov 2011/05/18 15:45:19 Do we need this header?
David Springer 2011/05/18 18:01:42 Uh no. Gone.
25 #include <ppapi/cpp/var.h> 25 #include <ppapi/cpp/var.h>
dmichael(do not use this one) 2011/05/18 18:46:10 Whoops, just noticed... if we're using "" for ppa
26 #include <cstdio> 26 #include <cstdio>
27 #include <cstring>
27 #include <string> 28 #include <string>
28 #include <algorithm> // for reverse 29 #include <algorithm> // for reverse
29 30
30 #include "examples/hello_world/helper_functions.h" 31 #include "examples/hello_world/helper_functions.h"
31 32
32 namespace {
33 // Helper function to set the scripting exception. Both |exception| and
34 // |except_string| can be NULL. If |exception| is NULL, this function does
35 // nothing.
36 void SetExceptionString(pp::Var* exception, const std::string& except_string) {
37 if (exception) {
38 *exception = except_string;
39 }
40 }
41
42 // Exception strings. These are passed back to the browser when errors
43 // happen during property accesses or method calls.
44 const char* const kExceptionMethodNotAString = "Method name is not a string";
45 const char* const kExceptionNoMethodName = "No method named ";
46 } // namespace
47
48 namespace hello_world { 33 namespace hello_world {
49 /// method name for ReverseText, as seen by JavaScript code. 34 /// Method name for ReverseText, as seen by JavaScript code.
50 const char* const kReverseTextMethodId = "reverseText"; 35 const char* const kReverseTextMethodId = "reverseText";
51 36
52 /// method name for FortyTwo, as seen by Javascript code. @see FortyTwo() 37 /// Method name for FortyTwo, as seen by Javascript code. @see FortyTwo()
53 const char* const kFortyTwoMethodId = "fortyTwo"; 38 const char* const kFortyTwoMethodId = "fortyTwo";
54 39
40 /// Separator charater for the reverseText method.
dmichael (off chromium) 2011/05/18 15:43:56 charater->character
David Springer 2011/05/18 18:01:42 Done.
41 static const char kMessageArgumentSeparator = ':';
42
55 /// This is the module's function that invokes FortyTwo and converts the return 43 /// This is the module's function that invokes FortyTwo and converts the return
56 /// value from an int32_t to a pp::Var for return. 44 /// value from an int32_t to a pp::Var for return.
57 pp::Var MarshallFortyTwo() { 45 pp::Var MarshallFortyTwo() {
58 return pp::Var(FortyTwo()); 46 return pp::Var(FortyTwo());
59 } 47 }
60 48
61 /// This function is passed the arg list from the JavaScript call to 49 /// This function is passed the arg list from the JavaScript call to
62 /// @a reverseText. 50 /// @a reverseText.
63 /// It makes sure that there is one argument and that it is a string, returning 51 /// It makes sure that there is one argument and that it is a string, returning
64 /// an error message if it is not. 52 /// an error message if it is not.
65 /// On good input, it calls ReverseText and returns the result. The 53 /// On good input, it calls ReverseText and returns the result. The
66 /// ScriptableObject that called this function returns this string back to the 54 /// ScriptableObject that called this function returns this string back to the
67 /// browser as a JavaScript value. 55 /// browser as a JavaScript value.
68 pp::Var MarshallReverseText(const std::vector<pp::Var>& args) { 56 pp::Var MarshallReverseText(const std::string& text) {
dmichael (off chromium) 2011/05/18 15:43:56 Did you update the unit test? For what it's worth
David Springer 2011/05/18 18:01:42 Oh - whoops. I spaced that. Done.
dmichael(do not use this one) 2011/05/18 18:46:10 Could you add it to the CL please? And... did th
69 // There should be exactly one arg, which should be an object 57 return pp::Var(ReverseText(text));
70 if (args.size() != 1) {
71 printf("Unexpected number of args\n");
72 return "Unexpected number of args";
73 }
74 if (!args[0].is_string()) {
75 printf("Arg %s is NOT a string\n", args[0].DebugString().c_str());
76 return "Arg from Javascript is not a string!";
77 }
78 return pp::Var(ReverseText(args[0].AsString()));
79 }
80
81 /// This class exposes the scripting interface for this NaCl module. The
82 /// HasMethod() method is called by the browser when executing a method call on
83 /// the @a helloWorldModule object (see the reverseText() function in
84 /// hello_world.html). The name of the JavaScript function (e.g. "fortyTwo") is
85 /// passed in the @a method parameter as a string pp::Var. If HasMethod()
86 /// returns @a true, then the browser will call the Call() method to actually
87 /// invoke the method.
88 class HelloWorldScriptableObject : public pp::deprecated::ScriptableObject {
89 public:
90 /// Determines whether a given method is implemented in this object.
91 /// @param[in] method A JavaScript string containing the method name to check
92 /// @param exception Unused
93 /// @return @a true if @a method is one of the exposed method names.
94 virtual bool HasMethod(const pp::Var& method, pp::Var* exception);
95
96 /// Invoke the function associated with @a method. The argument list passed
97 /// via JavaScript is marshaled into a vector of pp::Vars. None of the
98 /// functions in this example take arguments, so this vector is always empty.
99 /// @param[in] method A JavaScript string with the name of the method to call
100 /// @param[in] args A list of the JavaScript parameters passed to this method
101 /// @param exception unused
102 /// @return the return value of the invoked method
103 virtual pp::Var Call(const pp::Var& method,
104 const std::vector<pp::Var>& args,
105 pp::Var* exception);
106 };
107
108 bool HelloWorldScriptableObject::HasMethod(const pp::Var& method,
109 pp::Var* exception) {
110 if (!method.is_string()) {
111 SetExceptionString(exception, kExceptionMethodNotAString);
112 return false;
113 }
114 std::string method_name = method.AsString();
115 return method_name == kReverseTextMethodId ||
116 method_name == kFortyTwoMethodId;
117 }
118
119 pp::Var HelloWorldScriptableObject::Call(const pp::Var& method,
120 const std::vector<pp::Var>& args,
121 pp::Var* exception) {
122 if (!method.is_string()) {
123 SetExceptionString(exception, kExceptionMethodNotAString);
124 return pp::Var();
125 }
126 std::string method_name = method.AsString();
127 if (method_name == kReverseTextMethodId) {
128 // note that the vector of pp::Var |args| is passed to ReverseText
129 return MarshallReverseText(args);
130 } else if (method_name == kFortyTwoMethodId) {
131 // note that no arguments are passed in to FortyTwo.
132 return MarshallFortyTwo();
133 } else {
134 SetExceptionString(exception,
135 std::string(kExceptionNoMethodName) + method_name);
136 }
137 return pp::Var();
138 } 58 }
139 59
140 /// The Instance class. One of these exists for each instance of your NaCl 60 /// The Instance class. One of these exists for each instance of your NaCl
141 /// module on the web page. The browser will ask the Module object to create 61 /// module on the web page. The browser will ask the Module object to create
142 /// a new Instance for each occurrence of the <embed> tag that has these 62 /// a new Instance for each occurrence of the <embed> tag that has these
143 /// attributes: 63 /// attributes:
144 /// <pre> 64 /// <pre>
145 /// type="application/x-nacl" 65 /// type="application/x-nacl"
146 /// nacl="hello_world.nmf" 66 /// nacl="hello_world.nmf"
147 /// </pre> 67 /// </pre>
148 /// The Instance can return a ScriptableObject representing itself. When the 68 /// The Instance can return a ScriptableObject representing itself. When the
149 /// browser encounters JavaScript that wants to access the Instance, it calls 69 /// browser encounters JavaScript that wants to access the Instance, it calls
150 /// the GetInstanceObject() method. All the scripting work is done through 70 /// the GetInstanceObject() method. All the scripting work is done through
151 /// the returned ScriptableObject. 71 /// the returned ScriptableObject.
152 class HelloWorldInstance : public pp::Instance { 72 class HelloWorldInstance : public pp::Instance {
153 public: 73 public:
154 explicit HelloWorldInstance(PP_Instance instance) : pp::Instance(instance) {} 74 explicit HelloWorldInstance(PP_Instance instance) : pp::Instance(instance) {}
155 virtual ~HelloWorldInstance() {} 75 virtual ~HelloWorldInstance() {}
156 76
157 /// @return a new pp::deprecated::ScriptableObject as a JavaScript @a Var 77 /// Called by the browser to handle the postMessage() call in Javascript.
158 /// @note The pp::Var takes over ownership of the HelloWorldScriptableObject 78 /// Detects which method is being called from the message contents, and
159 /// and is responsible for deallocating memory. 79 /// calls the appropriate function. Posts the resutl back to the browser
dmichael (off chromium) 2011/05/18 15:43:56 resutl->result
David Springer 2011/05/18 18:01:42 Done.
160 virtual pp::Var GetInstanceObject() { 80 /// asynchronously.
161 HelloWorldScriptableObject* hw_object = new HelloWorldScriptableObject(); 81 /// @param[in] var_message The message posted by the browser.
garianov 2011/05/18 15:45:19 It would be nice to provide example of the possibl
David Springer 2011/05/18 18:01:42 Done.
162 return pp::Var(this, hw_object); 82 virtual void HandleMessage(const pp::Var& var_message);
83 };
84
85 void HelloWorldInstance::HandleMessage(const pp::Var& var_message) {
86 if (!var_message.is_string()) {
87 return;
163 } 88 }
164 }; 89 std::string message = var_message.AsString();
90 pp::Var return_var;
91 if (message == kFortyTwoMethodId) {
92 // Note that no arguments are passed in to FortyTwo.
93 return_var = MarshallFortyTwo();
94 } else if (message.find(kReverseTextMethodId,
95 0,
96 strlen(kReverseTextMethodId)) != std::string::npos) {
dmichael (off chromium) 2011/05/18 15:43:56 You don't really need the latter 2 arguments, sinc
David Springer 2011/05/18 18:01:42 Done.
97 // The argument to reverseText is everything after the first ':'.
98 size_t sep_pos = message.find_first_of(kMessageArgumentSeparator);
99 if (sep_pos != std::string::npos) {
100 std::string string_arg = message.substr(sep_pos + 1);
101 return_var = MarshallReverseText(string_arg);
102 }
103 }
104 // Post the return result back to the browser. Note that HandleMessage() is
105 // always called on the main thread, so it's OK to post the return message
106 // directly from here. The return post is asynhronous: PostMessage returns
107 // immediately.
108 PostMessage(return_var);
109 }
165 110
166 /// The Module class. The browser calls the CreateInstance() method to create 111 /// The Module class. The browser calls the CreateInstance() method to create
167 /// an instance of you NaCl module on the web page. The browser creates a new 112 /// an instance of you NaCl module on the web page. The browser creates a new
168 /// instance for each <embed> tag with 113 /// instance for each <embed> tag with
169 /// <code>type="application/x-ppapi-nacl-srpc"</code>. 114 /// <code>type="application/x-ppapi-nacl-srpc"</code>.
170 class HelloWorldModule : public pp::Module { 115 class HelloWorldModule : public pp::Module {
171 public: 116 public:
172 HelloWorldModule() : pp::Module() {} 117 HelloWorldModule() : pp::Module() {}
173 virtual ~HelloWorldModule() {} 118 virtual ~HelloWorldModule() {}
174 119
(...skipping 13 matching lines...) Expand all
188 /// The browser keeps a singleton of this module. It calls the 133 /// The browser keeps a singleton of this module. It calls the
189 /// CreateInstance() method on the object you return to make instances. There 134 /// CreateInstance() method on the object you return to make instances. There
190 /// is one instance per <embed> tag on the page. This is the main binding 135 /// is one instance per <embed> tag on the page. This is the main binding
191 /// point for your NaCl module with the browser. 136 /// point for your NaCl module with the browser.
192 /// @return new HelloWorldModule. 137 /// @return new HelloWorldModule.
193 /// @note The browser is responsible for deleting returned @a Module. 138 /// @note The browser is responsible for deleting returned @a Module.
194 Module* CreateModule() { 139 Module* CreateModule() {
195 return new hello_world::HelloWorldModule(); 140 return new hello_world::HelloWorldModule();
196 } 141 }
197 } // namespace pp 142 } // namespace pp
OLDNEW
« no previous file with comments | « no previous file | examples/hello_world/hello_world.html » ('j') | examples/hello_world/hello_world.html » ('J')

Powered by Google App Engine
This is Rietveld 408576698