1// Copyright (c) 2013 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. 4 5#include "content/renderer/pepper/pepper_file_system_host.h" 6 7#include "base/bind.h" 8#include "base/callback.h" 9#include "content/child/child_thread.h" 10#include "content/child/fileapi/file_system_dispatcher.h" 11#include "content/renderer/pepper/pepper_plugin_instance_impl.h" 12#include "content/public/renderer/render_view.h" 13#include "content/public/renderer/renderer_ppapi_host.h" 14#include "ppapi/c/pp_errors.h" 15#include "ppapi/host/dispatch_host_message.h" 16#include "ppapi/host/ppapi_host.h" 17#include "ppapi/proxy/ppapi_messages.h" 18#include "ppapi/shared_impl/file_type_conversion.h" 19#include "third_party/WebKit/public/web/WebDocument.h" 20#include "third_party/WebKit/public/web/WebElement.h" 21#include "third_party/WebKit/public/web/WebFrame.h" 22#include "third_party/WebKit/public/web/WebPluginContainer.h" 23#include "third_party/WebKit/public/web/WebView.h" 24#include "webkit/common/fileapi/file_system_util.h" 25 26namespace content { 27 28namespace { 29 30bool LooksLikeAGuid(const std::string& fsid) { 31 const size_t kExpectedFsIdSize = 32; 32 if (fsid.size() != kExpectedFsIdSize) 33 return false; 34 for (std::string::const_iterator it = fsid.begin(); it != fsid.end(); ++it) { 35 if (('A' <= *it && *it <= 'F') || 36 ('0' <= *it && *it <= '9')) 37 continue; 38 return false; 39 } 40 return true; 41} 42 43} // namespace 44 45PepperFileSystemHost::PepperFileSystemHost(RendererPpapiHost* host, 46 PP_Instance instance, 47 PP_Resource resource, 48 PP_FileSystemType type) 49 : ResourceHost(host->GetPpapiHost(), instance, resource), 50 renderer_ppapi_host_(host), 51 weak_factory_(this), 52 type_(type), 53 opened_(false), 54 called_open_(false) { 55} 56 57PepperFileSystemHost::~PepperFileSystemHost() { 58} 59 60int32_t PepperFileSystemHost::OnResourceMessageReceived( 61 const IPC::Message& msg, 62 ppapi::host::HostMessageContext* context) { 63 IPC_BEGIN_MESSAGE_MAP(PepperFileSystemHost, msg) 64 PPAPI_DISPATCH_HOST_RESOURCE_CALL( 65 PpapiHostMsg_FileSystem_Open, 66 OnHostMsgOpen) 67 PPAPI_DISPATCH_HOST_RESOURCE_CALL( 68 PpapiHostMsg_FileSystem_InitIsolatedFileSystem, 69 OnHostMsgInitIsolatedFileSystem) 70 IPC_END_MESSAGE_MAP() 71 return PP_ERROR_FAILED; 72} 73 74bool PepperFileSystemHost::IsFileSystemHost() { 75 return true; 76} 77 78void PepperFileSystemHost::DidOpenFileSystem( 79 const std::string& /* name_unused */, 80 const GURL& root) { 81 opened_ = true; 82 root_url_ = root; 83 reply_context_.params.set_result(PP_OK); 84 host()->SendReply(reply_context_, PpapiPluginMsg_FileSystem_OpenReply()); 85 reply_context_ = ppapi::host::ReplyMessageContext(); 86} 87 88void PepperFileSystemHost::DidFailOpenFileSystem( 89 base::PlatformFileError error) { 90 int32 pp_error = ppapi::PlatformFileErrorToPepperError(error); 91 opened_ = (pp_error == PP_OK); 92 reply_context_.params.set_result(pp_error); 93 host()->SendReply(reply_context_, PpapiPluginMsg_FileSystem_OpenReply()); 94 reply_context_ = ppapi::host::ReplyMessageContext(); 95} 96 97int32_t PepperFileSystemHost::OnHostMsgOpen( 98 ppapi::host::HostMessageContext* context, 99 int64_t expected_size) { 100 // Not allow multiple opens. 101 if (called_open_) 102 return PP_ERROR_INPROGRESS; 103 called_open_ = true; 104 105 fileapi::FileSystemType file_system_type; 106 switch (type_) { 107 case PP_FILESYSTEMTYPE_LOCALTEMPORARY: 108 file_system_type = fileapi::kFileSystemTypeTemporary; 109 break; 110 case PP_FILESYSTEMTYPE_LOCALPERSISTENT: 111 file_system_type = fileapi::kFileSystemTypePersistent; 112 break; 113 case PP_FILESYSTEMTYPE_EXTERNAL: 114 file_system_type = fileapi::kFileSystemTypeExternal; 115 break; 116 default: 117 return PP_ERROR_FAILED; 118 } 119 120 PepperPluginInstance* plugin_instance = 121 renderer_ppapi_host_->GetPluginInstance(pp_instance()); 122 if (!plugin_instance) 123 return PP_ERROR_FAILED; 124 125 FileSystemDispatcher* file_system_dispatcher = 126 ChildThread::current()->file_system_dispatcher(); 127 reply_context_ = context->MakeReplyMessageContext(); 128 file_system_dispatcher->OpenFileSystem( 129 GURL(plugin_instance->GetContainer()->element().document().url()). 130 GetOrigin(), 131 file_system_type, expected_size, true /* create */, 132 base::Bind(&PepperFileSystemHost::DidOpenFileSystem, 133 weak_factory_.GetWeakPtr()), 134 base::Bind(&PepperFileSystemHost::DidFailOpenFileSystem, 135 weak_factory_.GetWeakPtr())); 136 return PP_OK_COMPLETIONPENDING; 137} 138 139int32_t PepperFileSystemHost::OnHostMsgInitIsolatedFileSystem( 140 ppapi::host::HostMessageContext* context, 141 const std::string& fsid) { 142 called_open_ = true; 143 // Do a sanity check. 144 if (!LooksLikeAGuid(fsid)) 145 return PP_ERROR_BADARGUMENT; 146 RenderView* view = 147 renderer_ppapi_host_->GetRenderViewForInstance(pp_instance()); 148 if (!view) 149 return PP_ERROR_FAILED; 150 const GURL& url = view->GetWebView()->mainFrame()->document().url(); 151 root_url_ = GURL(fileapi::GetIsolatedFileSystemRootURIString( 152 url.GetOrigin(), fsid, "crxfs")); 153 opened_ = true; 154 return PP_OK; 155} 156 157} // namespace content 158