15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
59ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/c/dev/ppb_file_chooser_dev.h"
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/c/pp_errors.h"
8d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "ppapi/c/ppb_file_ref.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/proxy/file_chooser_resource.h"
10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ppapi/proxy/locking_resource_releaser.h"
115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ppapi/proxy/plugin_message_filter.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/proxy/ppapi_messages.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/proxy/ppapi_proxy_test.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ppapi/shared_impl/proxy_lock.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/shared_impl/scoped_pp_var.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/shared_impl/var.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ppapi/thunk/thunk.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace ppapi {
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace proxy {
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef PluginProxyTest FileChooserResourceTest;
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void* GetFileRefDataBuffer(void* user_data,
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           uint32_t element_count,
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           uint32_t element_size) {
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(element_size == sizeof(PP_Resource));
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<PP_Resource>* output =
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      static_cast<std::vector<PP_Resource>*>(user_data);
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  output->resize(element_count);
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (element_count > 0)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return &(*output)[0];
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NULL;
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DoNothingCallback(void* user_data, int32_t result) {
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Calls PopulateAcceptTypes and verifies that the resulting array contains
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the given values. The values may be NULL if there aren't expected to be
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// that many results.
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CheckParseAcceptType(const std::string& input,
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          const char* expected1,
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          const char* expected2) {
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<std::string> output;
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FileChooserResource::PopulateAcceptTypes(input, &output);
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const size_t kCount = 2;
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* expected[kCount] = { expected1, expected2 };
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < kCount; i++) {
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!expected[i])
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return i == output.size();
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (output.size() <= i)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (output[i] != expected[i])
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return output.size() == kCount;
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Does a full test of Show() and reply functionality in the plugin side using
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the public C interfaces.
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(FileChooserResourceTest, Show) {
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const PPB_FileChooser_Dev_0_6* chooser_iface =
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      thunk::GetPPB_FileChooser_Dev_0_6_Thunk();
72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  LockingResourceReleaser res(
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      chooser_iface->Create(pp_instance(), PP_FILECHOOSERMODE_OPEN,
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            PP_MakeUndefined()));
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<PP_Resource> dest;
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_ArrayOutput output;
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  output.GetDataBuffer = &GetFileRefDataBuffer;
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  output.user_data = &dest;
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32_t result = chooser_iface->Show(
82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      res.get(), output, PP_MakeCompletionCallback(&DoNothingCallback, NULL));
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Should have sent a "show" message.
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ResourceMessageCallParams params;
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IPC::Message msg;
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(sink().GetFirstResourceCallMatching(
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PpapiHostMsg_FileChooser_Show::ID, &params, &msg));
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ResourceMessageReplyParams reply_params(params.pp_resource(),
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          params.sequence());
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  reply_params.set_result(PP_OK);
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Synthesize a response with one file ref in it. Note that it must have a
96d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // pending_host_resource_id set. Since there isn't actually a host, this can
97d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // be whatever we want.
98d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  std::vector<FileRefCreateInfo> create_info_array;
99d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  FileRefCreateInfo create_info;
100d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  create_info.file_system_type = PP_FILESYSTEMTYPE_EXTERNAL;
101d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  create_info.display_name = "bar";
102d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  create_info.browser_pending_host_resource_id = 12;
103d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  create_info.renderer_pending_host_resource_id = 15;
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  create_info_array.push_back(create_info);
1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  PluginMessageFilter::DispatchResourceReplyForTest(
1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      reply_params, PpapiPluginMsg_FileChooser_ShowReply(create_info_array));
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Should have populated our vector.
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(1u, dest.size());
110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  LockingResourceReleaser dest_deletor(dest[0]);  // Ensure it's cleaned up.
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const PPB_FileRef_1_0* file_ref_iface = thunk::GetPPB_FileRef_1_0_Thunk();
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(PP_FILESYSTEMTYPE_EXTERNAL,
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            file_ref_iface->GetFileSystemType(dest[0]));
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PP_Var name_var(file_ref_iface->GetName(dest[0]));
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ProxyAutoLock lock;
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ScopedPPVar release_name_var(ScopedPPVar::PassRef(), name_var);
120d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    EXPECT_VAR_IS_STRING("bar", name_var);
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PP_Var path_var(file_ref_iface->GetPath(dest[0]));
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ProxyAutoLock lock;
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ScopedPPVar release_path_var(ScopedPPVar::PassRef(), path_var);
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_EQ(PP_VARTYPE_UNDEFINED, path_var.type);
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(FileChooserResourceTest, PopulateAcceptTypes) {
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(CheckParseAcceptType(std::string(), NULL, NULL));
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(CheckParseAcceptType("/", NULL, NULL));
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(CheckParseAcceptType(".", NULL, NULL));
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(CheckParseAcceptType(",, , ", NULL, NULL));
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(CheckParseAcceptType("app/txt", "app/txt", NULL));
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(CheckParseAcceptType("app/txt,app/pdf", "app/txt", "app/pdf"));
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(CheckParseAcceptType(" app/txt , app/pdf ",
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   "app/txt", "app/pdf"));
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // No dot or slash ones should be skipped.
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(CheckParseAcceptType("foo", NULL, NULL));
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(CheckParseAcceptType("foo,.txt", ".txt", NULL));
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace proxy
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace ppapi
148