1c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved.
2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// found in the LICENSE file.
4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "content/renderer/pepper/pepper_file_system_host.h"
6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/bind.h"
8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/callback.h"
9868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/child/child_thread.h"
10868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/child/fileapi/file_system_dispatcher.h"
1158e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch#include "content/renderer/pepper/pepper_plugin_instance_impl.h"
12b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "content/public/renderer/render_view.h"
13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "content/public/renderer/renderer_ppapi_host.h"
14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ppapi/c/pp_errors.h"
15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ppapi/host/dispatch_host_message.h"
16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ppapi/host/ppapi_host.h"
17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ppapi/proxy/ppapi_messages.h"
18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ppapi/shared_impl/file_type_conversion.h"
197d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "third_party/WebKit/public/web/WebDocument.h"
207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "third_party/WebKit/public/web/WebElement.h"
217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "third_party/WebKit/public/web/WebFrame.h"
227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "third_party/WebKit/public/web/WebPluginContainer.h"
237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "third_party/WebKit/public/web/WebView.h"
2490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "webkit/common/fileapi/file_system_util.h"
25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace content {
27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace {
29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
30b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)bool LooksLikeAGuid(const std::string& fsid) {
31b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  const size_t kExpectedFsIdSize = 32;
32b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (fsid.size() != kExpectedFsIdSize)
33b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return false;
34b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  for (std::string::const_iterator it = fsid.begin(); it != fsid.end(); ++it) {
35b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    if (('A' <= *it && *it <= 'F') ||
36b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        ('0' <= *it && *it <= '9'))
37b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      continue;
38b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return false;
39b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
40b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  return true;
41b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
42b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace
44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)PepperFileSystemHost::PepperFileSystemHost(RendererPpapiHost* host,
46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                           PP_Instance instance,
47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                           PP_Resource resource,
48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                           PP_FileSystemType type)
49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    : ResourceHost(host->GetPpapiHost(), instance, resource),
50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      renderer_ppapi_host_(host),
51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      weak_factory_(this),
52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      type_(type),
53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      opened_(false),
54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      called_open_(false) {
55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)PepperFileSystemHost::~PepperFileSystemHost() {
58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)int32_t PepperFileSystemHost::OnResourceMessageReceived(
61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const IPC::Message& msg,
62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    ppapi::host::HostMessageContext* context) {
63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  IPC_BEGIN_MESSAGE_MAP(PepperFileSystemHost, msg)
64b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    PPAPI_DISPATCH_HOST_RESOURCE_CALL(
65b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        PpapiHostMsg_FileSystem_Open,
66b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        OnHostMsgOpen)
67b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    PPAPI_DISPATCH_HOST_RESOURCE_CALL(
68b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        PpapiHostMsg_FileSystem_InitIsolatedFileSystem,
69b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        OnHostMsgInitIsolatedFileSystem)
70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  IPC_END_MESSAGE_MAP()
71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return PP_ERROR_FAILED;
72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
74a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)bool PepperFileSystemHost::IsFileSystemHost() {
75a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return true;
76868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
77868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
7890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void PepperFileSystemHost::DidOpenFileSystem(
7990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const std::string& /* name_unused */,
8090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const GURL& root) {
8190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  opened_ = true;
82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  root_url_ = root;
8390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  reply_context_.params.set_result(PP_OK);
8490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  host()->SendReply(reply_context_, PpapiPluginMsg_FileSystem_OpenReply());
8590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  reply_context_ = ppapi::host::ReplyMessageContext();
8690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
8790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
8890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void PepperFileSystemHost::DidFailOpenFileSystem(
8990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    base::PlatformFileError error) {
9090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int32 pp_error = ppapi::PlatformFileErrorToPepperError(error);
9190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  opened_ = (pp_error == PP_OK);
92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  reply_context_.params.set_result(pp_error);
9390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  host()->SendReply(reply_context_, PpapiPluginMsg_FileSystem_OpenReply());
94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  reply_context_ = ppapi::host::ReplyMessageContext();
95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)int32_t PepperFileSystemHost::OnHostMsgOpen(
98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    ppapi::host::HostMessageContext* context,
99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    int64_t expected_size) {
100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Not allow multiple opens.
101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (called_open_)
102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return PP_ERROR_INPROGRESS;
103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  called_open_ = true;
104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  fileapi::FileSystemType file_system_type;
106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  switch (type_) {
107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case PP_FILESYSTEMTYPE_LOCALTEMPORARY:
108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      file_system_type = fileapi::kFileSystemTypeTemporary;
109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      break;
110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case PP_FILESYSTEMTYPE_LOCALPERSISTENT:
111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      file_system_type = fileapi::kFileSystemTypePersistent;
112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      break;
113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case PP_FILESYSTEMTYPE_EXTERNAL:
114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      file_system_type = fileapi::kFileSystemTypeExternal;
115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      break;
116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    default:
117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return PP_ERROR_FAILED;
118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
12058e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch  PepperPluginInstance* plugin_instance =
121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      renderer_ppapi_host_->GetPluginInstance(pp_instance());
122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!plugin_instance)
123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return PP_ERROR_FAILED;
124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  FileSystemDispatcher* file_system_dispatcher =
126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      ChildThread::current()->file_system_dispatcher();
127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  reply_context_ = context->MakeReplyMessageContext();
128eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  file_system_dispatcher->OpenFileSystem(
129bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      GURL(plugin_instance->GetContainer()->element().document().url()).
130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          GetOrigin(),
131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      file_system_type, expected_size, true /* create */,
13290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      base::Bind(&PepperFileSystemHost::DidOpenFileSystem,
13390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                 weak_factory_.GetWeakPtr()),
13490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      base::Bind(&PepperFileSystemHost::DidFailOpenFileSystem,
135eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                 weak_factory_.GetWeakPtr()));
136c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return PP_OK_COMPLETIONPENDING;
137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
139b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)int32_t PepperFileSystemHost::OnHostMsgInitIsolatedFileSystem(
140b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    ppapi::host::HostMessageContext* context,
141b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    const std::string& fsid) {
1427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  called_open_ = true;
143b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // Do a sanity check.
144b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (!LooksLikeAGuid(fsid))
145b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return PP_ERROR_BADARGUMENT;
146b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  RenderView* view =
147b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      renderer_ppapi_host_->GetRenderViewForInstance(pp_instance());
148b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (!view)
149b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return PP_ERROR_FAILED;
150b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  const GURL& url = view->GetWebView()->mainFrame()->document().url();
151b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  root_url_ = GURL(fileapi::GetIsolatedFileSystemRootURIString(
152b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      url.GetOrigin(), fsid, "crxfs"));
153b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  opened_ = true;
154b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  return PP_OK;
155b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
156b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace content
158