OLD | NEW |
---|---|
1 // Copyright (c) 2014 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2014 The Chromium 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 #include <pthread.h> | |
6 #include <unistd.h> | |
7 | |
8 #include <sstream> | |
9 #include <string> | |
10 | |
11 #include "native_client/src/untrusted/irt/irt.h" | |
12 #include "native_client/src/untrusted/nacl/nacl_irt.h" | |
13 | |
14 #include "ppapi/cpp/completion_callback.h" | |
5 #include "ppapi/cpp/instance.h" | 15 #include "ppapi/cpp/instance.h" |
6 #include "ppapi/cpp/module.h" | 16 #include "ppapi/cpp/module.h" |
7 #include "ppapi/cpp/var.h" | 17 #include "ppapi/cpp/var.h" |
8 | 18 |
9 namespace { | 19 namespace { |
10 | 20 |
21 std::string g_last_error; | |
22 pp::Instance* g_instance = NULL; | |
23 | |
24 // This should be the same as FileDescriptorSet::kMaxDescriptorsPerMessage in | |
25 // ipc/file_descriptor_set_posix.h. | |
26 const size_t kMaxDescriptorsPerMessage = 128; | |
27 | |
28 // Returns true if the resource file whose name is |key| exists and its content | |
29 // matches |content|. | |
30 bool LoadManifestInternal(TYPE_nacl_irt_query* query_func, | |
31 const std::string& key, | |
32 const std::string& content) { | |
33 struct nacl_irt_resource_open nacl_irt_resource_open; | |
34 if (sizeof(nacl_irt_resource_open) != | |
35 (*query_func)(NACL_IRT_RESOURCE_OPEN_v0_1, &nacl_irt_resource_open, | |
36 sizeof(nacl_irt_resource_open))) { | |
37 g_last_error = "irt manifest api not found"; | |
38 return false; | |
39 } | |
40 int desc; | |
41 int error; | |
42 error = nacl_irt_resource_open.open_resource(key.c_str(), &desc); | |
43 if (0 != error) { | |
44 g_last_error = "Can't open file " + key; | |
45 return false; | |
46 } | |
47 | |
48 std::string str; | |
49 | |
50 char buffer[4096]; | |
51 int len; | |
52 while ((len = read(desc, buffer, sizeof buffer - 1)) > 0) { | |
teravest
2014/11/26 21:24:04
nit: I'd prefer "sizeof(buffer) - 1" instead of "s
Yusuke Sato
2014/11/26 21:50:34
Done.
| |
53 // Null terminate. | |
54 buffer[len] = '\0'; | |
55 str += buffer; | |
56 } | |
57 // Do not call close(desc); so that LoadManifest calls the second | |
teravest
2014/11/26 21:24:04
You don't need the semicolon here.
Yusuke Sato
2014/11/26 21:50:34
Done.
| |
58 // open_resource without closing the first one. | |
59 | |
60 if (str != content) { | |
61 g_last_error = "Wrong file content: file=" + key + ", expected=" + content + | |
62 ", actual=" + str; | |
63 return false; | |
64 } | |
65 | |
66 return true; | |
67 } | |
68 | |
69 // Tests if open_resource works in a packaged app. This test is similar to | |
70 // NaClBrowserTest*.IrtManifestFile, but unlike the NaCl test, this one tests | |
71 // the "fast path" in DownloadNexe() in ppb_nacl_private_impl.cc which opens | |
72 // resource files without using URLLoader. | |
73 void LoadManifest(TYPE_nacl_irt_query* query_func) { | |
74 for (size_t i = 0; i <= kMaxDescriptorsPerMessage; ++i) { | |
75 std::stringstream key; | |
76 key << "test_file" << i; | |
77 std::string content = "Test File Content" + std::string(i % 2 ? "2" : ""); | |
78 if (!LoadManifestInternal(query_func, key.str(), content)) | |
79 break; | |
80 // Open the same resource file again to make sure each file descriptor | |
81 // returned from open_resource has its own file offset. | |
82 if (!LoadManifestInternal(query_func, key.str(), content)) | |
83 break; | |
84 } | |
85 } | |
86 | |
87 void PostReply(void* user_data, int32_t status) { | |
88 if (!g_last_error.empty()) | |
89 g_instance->PostMessage(g_last_error.c_str()); | |
90 else | |
91 g_instance->PostMessage("hello"); | |
92 } | |
93 | |
94 void* RunTestsOnBackgroundThread(void* thread_id) { | |
95 LoadManifest(&__nacl_irt_query); | |
96 pp::Module::Get()->core()->CallOnMainThread( | |
97 0, pp::CompletionCallback(&PostReply, NULL)); | |
98 return NULL; | |
99 } | |
100 | |
11 class MyInstance : public pp::Instance { | 101 class MyInstance : public pp::Instance { |
12 public: | 102 public: |
13 explicit MyInstance(PP_Instance instance) : pp::Instance(instance) { } | 103 explicit MyInstance(PP_Instance instance) : pp::Instance(instance) { |
104 g_instance = this; | |
105 } | |
14 virtual ~MyInstance() { } | 106 virtual ~MyInstance() { } |
15 | 107 |
16 virtual bool Init(uint32_t argc, const char* argn[], const char* argv[]) { | 108 virtual bool Init(uint32_t argc, const char* argn[], const char* argv[]) { |
17 PostMessage("hello"); | 109 pthread_t thread; |
110 pthread_create(&thread, NULL, &RunTestsOnBackgroundThread, NULL); | |
111 pthread_detach(thread); | |
18 return true; | 112 return true; |
19 } | 113 } |
20 }; | 114 }; |
21 | 115 |
22 class MyModule : public pp::Module { | 116 class MyModule : public pp::Module { |
23 public: | 117 public: |
24 MyModule() : pp::Module() { } | 118 MyModule() : pp::Module() { } |
25 virtual ~MyModule() { } | 119 virtual ~MyModule() { } |
26 | 120 |
27 virtual pp::Instance* CreateInstance(PP_Instance instance) { | 121 virtual pp::Instance* CreateInstance(PP_Instance instance) { |
28 return new MyInstance(instance); | 122 return new MyInstance(instance); |
29 } | 123 } |
30 }; | 124 }; |
31 | 125 |
32 } // namespace | 126 } // namespace |
33 | 127 |
34 namespace pp { | 128 namespace pp { |
35 | 129 |
36 Module* CreateModule() { | 130 Module* CreateModule() { |
37 return new MyModule(); | 131 return new MyModule(); |
38 } | 132 } |
39 | 133 |
40 } // namespace pp | 134 } // namespace pp |
OLD | NEW |