| 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 |