OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright 2013 The Chromium Authors. All rights reserved. | |
3 * Use of this source code is governed by a BSD-style license that can be | |
4 * found in the LICENSE file. | |
5 */ | |
6 | |
7 // | |
8 // Post-message based test for simple rpc based access to name services. | |
9 // | |
10 | |
11 #include <string> | |
12 | |
13 #include <assert.h> | |
14 #include <stdio.h> | |
15 #include <stdlib.h> | |
16 #include <inttypes.h> | |
17 #include <sys/fcntl.h> | |
18 #include <string.h> | |
19 #include <unistd.h> | |
20 #include <pthread.h> | |
21 | |
22 #include "native_client/src/include/nacl_base.h" | |
23 | |
24 #include "ppapi/cpp/instance.h" | |
25 #include "ppapi/cpp/module.h" | |
26 #include "ppapi/cpp/var.h" | |
27 | |
28 | |
29 class MyInstance : public pp::Instance { | |
30 public: | |
31 explicit MyInstance(PP_Instance instance); | |
32 virtual ~MyInstance(); | |
33 virtual void HandleMessage(const pp::Var& message_data); | |
34 | |
35 private: | |
36 DISALLOW_COPY_AND_ASSIGN(MyInstance); | |
37 }; | |
38 | |
39 // --------------------------------------------------------------------------- | |
40 | |
41 MyInstance::MyInstance(PP_Instance instance) | |
42 : pp::Instance(instance) { | |
43 } | |
44 | |
45 MyInstance::~MyInstance() { | |
46 } | |
47 | |
48 typedef std::map<std::string, std::string> KeyValueMap; | |
49 | |
50 static void ParseMapEntry(KeyValueMap* map, | |
51 std::string const& entry) { | |
52 std::string::size_type eq = entry.find('='); | |
53 std::string key; | |
54 std::string val = ""; | |
55 if (std::string::npos != eq) { | |
56 key = entry.substr(0, eq); | |
57 val = entry.substr(eq+1); | |
58 } else { | |
59 key = entry; | |
60 } | |
61 (*map)[key] = val; | |
62 } | |
63 | |
64 // | |
65 // parse a name1=value1,name2=value2 string into a map, using NRVO. spaces | |
66 // are significant (!). | |
67 // | |
68 static KeyValueMap ParseMap(std::string const& str_map) { | |
69 KeyValueMap nrvo; | |
70 std::string::size_type s = 0; | |
71 std::string::size_type comma; | |
72 | |
73 while (std::string::npos != (comma = str_map.find(',', s))) { | |
74 std::string sub = str_map.substr(s, comma - s); | |
75 s = comma + 1; | |
76 ParseMapEntry(&nrvo, sub); | |
77 } | |
78 if (s != str_map.size()) { | |
79 std::string sub = str_map.substr(s); | |
80 ParseMapEntry(&nrvo, sub); | |
81 } | |
82 return nrvo; | |
83 } | |
84 | |
85 | |
86 static std::string quotes[] = { | |
87 "In the year 1878 I took my degree of Doctor of Medicine...\n", | |
88 "A merry little surge of electricity piped by automatic alarm...\n", | |
89 "Squire Trelawney, Dr. Livesey, and the rest of these gentlemen...\n", | |
90 ("It is a truth universally acknowledged," | |
91 " that a single man in possession...\n"), | |
92 }; | |
93 | |
94 void output_quote(int desc, size_t ix) { | |
95 const char* out = quotes[ix].c_str(); | |
96 size_t len = strlen(out); | |
97 (void) write(desc, out, len); /* assumes no partial writes! */ | |
98 } | |
99 | |
100 // | |
101 // thread start function -- output asynchronously. | |
102 // | |
103 /* calling conv */ extern "C" { | |
104 static void* bg_thread(void* state) { | |
105 KeyValueMap* kvm(reinterpret_cast<KeyValueMap*>(state)); | |
106 | |
107 std::string out = (*kvm)["stream"]; | |
108 std::string sleep_str; | |
109 int sleep_us = 0; | |
110 | |
111 if ((*kvm).find("delay_us") != (*kvm).end()) { | |
112 sleep_str = (*kvm)["delay_us"]; | |
113 if (sleep_str.length() > 0) { | |
114 sleep_us = strtoul(sleep_str.c_str(), 0, 0); | |
115 } | |
116 } | |
117 // Try to check that output works when the event handler thread has | |
118 // already returned back to JavaScript, as opposed to output | |
119 // occuring while the plugin is still executing the event handler | |
120 // and blocking the JavaScript main thread. | |
121 if (sleep_us > 0) { | |
122 usleep(sleep_us); | |
123 } | |
124 if (out == "stdout") { | |
125 output_quote(1, 2); | |
126 } else if (out == "stderr") { | |
127 output_quote(2, 3); | |
128 } else { | |
129 fprintf(stderr, "bg_thread: unrecognized output stream %s\n", | |
130 out.c_str()); | |
131 } | |
132 return NULL; | |
133 } | |
134 } // extern "C" | |
135 | |
136 // HandleMessage gets invoked when postMessage is called on the DOM | |
137 // element associated with this plugin instance. In this case, if we | |
138 // are given a string, we'll post a message back to JavaScript with a | |
139 // reply -- essentially treating this as a string-based RPC. | |
140 void MyInstance::HandleMessage(const pp::Var& message) { | |
141 std::string msg = "None"; | |
142 if (message.is_string()) { | |
143 msg = message.AsString(); | |
144 KeyValueMap test_arg(ParseMap(msg)); | |
145 if (test_arg["thread"] == "fg") { | |
146 std::string out = test_arg["stream"]; | |
147 if (out == "stdout") { | |
148 output_quote(1, 0); | |
149 } else if (out == "stderr") { | |
150 output_quote(2, 1); | |
151 } else { | |
152 fprintf(stderr, "HandleMessage: unrecognized output stream %s\n", | |
153 out.c_str()); | |
154 } | |
155 } else { | |
156 /* spawn thread to do output */ | |
157 pthread_t tid; | |
158 | |
159 pthread_create(&tid, | |
160 reinterpret_cast<const pthread_attr_t *>(NULL), | |
161 bg_thread, | |
162 reinterpret_cast<void *>(new KeyValueMap(test_arg))); | |
163 pthread_detach(tid); | |
164 } | |
165 } else { | |
166 fprintf(stderr, "HandleMessage: message is not a string\n"); | |
167 fflush(NULL); | |
168 } | |
169 } | |
170 | |
171 // This object is the global object representing this plugin library as long | |
172 // as it is loaded. | |
173 class MyModule : public pp::Module { | |
174 public: | |
175 MyModule() : pp::Module() {} | |
176 virtual ~MyModule() {} | |
177 | |
178 // Override CreateInstance to create your customized Instance object. | |
179 virtual pp::Instance *CreateInstance(PP_Instance instance); | |
180 | |
181 DISALLOW_COPY_AND_ASSIGN(MyModule); | |
182 }; | |
183 | |
184 pp::Instance *MyModule::CreateInstance(PP_Instance pp_instance) { | |
185 return new MyInstance(pp_instance); | |
186 } | |
187 | |
188 namespace pp { | |
189 | |
190 // Factory function for your specialization of the Module object. | |
191 Module* CreateModule() { | |
192 return new MyModule(); | |
193 } | |
194 | |
195 } // namespace pp | |
OLD | NEW |