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
3 // found in the LICENSE file.
11 #include "native_client/src/untrusted/irt/irt.h"
13 #include "ppapi/cpp/completion_callback.h"
14 #include "ppapi/cpp/instance.h"
15 #include "ppapi/cpp/module.h"
16 #include "ppapi/cpp/tcp_socket.h"
17 #include "ppapi/cpp/var.h"
18 #include "ppapi/utility/completion_callback_factory.h"
20 #if defined(__clang__)
21 // ipc_message_attachment_set.h depends on C++11 which nacl-g++ does not
23 #include "ipc/ipc_message_attachment_set.h"
28 std::string g_last_error
;
29 pp::Instance
* g_instance
= NULL
;
31 // This should be larger than or equal to
32 // MessageAttachmentSet::kMaxDescriptorsPerMessage in
33 // ipc/ipc_message_attachment_set.h.
34 const size_t kMaxDescriptorsPerMessage
= 128;
36 #if defined(__clang__)
37 static_assert(kMaxDescriptorsPerMessage
>=
38 IPC::MessageAttachmentSet::kMaxDescriptorsPerMessage
,
39 "kMaxDescriptorsPerMessage is not up to date");
42 // Returns true if the resource file whose name is |key| exists and its content
44 bool LoadManifestInternal(nacl_irt_resource_open
* nacl_irt_resource_open
,
45 const std::string
& key
,
46 const std::string
& content
) {
49 error
= nacl_irt_resource_open
->open_resource(key
.c_str(), &desc
);
51 g_last_error
= "Can't open file " + key
;
59 while ((len
= read(desc
, buffer
, sizeof(buffer
) - 1)) > 0) {
65 g_last_error
= "Close failed: file=" + key
;
70 g_last_error
= "Wrong file content: file=" + key
+ ", expected=" + content
+
78 // Tests if open_resource works in a packaged app. This test is similar to
79 // NaClBrowserTest*.IrtManifestFile, but unlike the NaCl test, this one tests
80 // the "fast path" in DownloadNexe() in ppb_nacl_private_impl.cc which opens
81 // resource files without using URLLoader.
83 if (pthread_detach(pthread_self())) {
84 g_last_error
= "pthread_detach failed";
88 struct nacl_irt_resource_open nacl_irt_resource_open
;
89 if (sizeof(nacl_irt_resource_open
) !=
90 nacl_interface_query(NACL_IRT_RESOURCE_OPEN_v0_1
,
91 &nacl_irt_resource_open
,
92 sizeof(nacl_irt_resource_open
))) {
93 g_last_error
= "NACL_IRT_RESOURCE_OPEN_v0_1 not found";
97 for (size_t i
= 0; i
<= kMaxDescriptorsPerMessage
; ++i
) {
98 std::stringstream key
;
99 key
<< "test_file" << i
;
100 std::string content
= "Example contents for open_resource test" +
101 std::string(i
% 2 ? "2" : "");
102 if (!LoadManifestInternal(&nacl_irt_resource_open
, key
.str(), content
))
104 // Open the same resource file again to make sure each file descriptor
105 // returned from open_resource has its own file offset.
106 if (!LoadManifestInternal(&nacl_irt_resource_open
, key
.str(), content
))
111 void PostReply(void* user_data
, int32_t status
) {
112 if (!g_last_error
.empty())
113 g_instance
->PostMessage(g_last_error
.c_str());
115 g_instance
->PostMessage("PASS");
118 void* RunTestsOnBackgroundThread(void* thread_id
) {
120 pp::Module::Get()->core()->CallOnMainThread(
121 0, pp::CompletionCallback(&PostReply
, NULL
));
125 class MyInstance
: public pp::Instance
{
127 explicit MyInstance(PP_Instance instance
)
128 : pp::Instance(instance
), socket_(this), factory_(this) {
131 virtual ~MyInstance() { }
133 void DidBindSocket(int32_t result
) {
134 // We didn't ask for socket permission in our manifest, so it should fail.
135 if (result
== PP_ERROR_NOACCESS
)
141 virtual bool Init(uint32_t argc
, const char* argn
[], const char* argv
[]) {
143 // irt_open_resource() isn't allowed to be called on the main thread once
144 // Pepper starts, so the test must happen on a background thread.
145 if (pthread_create(&thread
, NULL
, &RunTestsOnBackgroundThread
, NULL
)) {
146 g_last_error
= "pthread_create failed";
149 // Attempt to bind a socket. We don't have permissions, so it should fail.
150 PP_NetAddress_IPv4 ipv4_address
= {80, {127, 0, 0, 1} };
151 pp::NetAddress
address(this, ipv4_address
);
152 socket_
.Bind(address
, factory_
.NewCallback(&MyInstance::DidBindSocket
));
157 pp::TCPSocket socket_
;
158 pp::CompletionCallbackFactory
<MyInstance
> factory_
;
161 class MyModule
: public pp::Module
{
163 MyModule() : pp::Module() { }
164 virtual ~MyModule() { }
166 virtual pp::Instance
* CreateInstance(PP_Instance instance
) {
167 return new MyInstance(instance
);
175 Module
* CreateModule() {
176 return new MyModule();