| OLD | NEW |
| (Empty) | |
| 1 /* |
| 2 * Copyright (c) 2011 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 |