1 // Copyright 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/browser/renderer_host/pepper/pepper_file_system_browser_host.h" 6 7 #include "base/bind.h" 8 #include "base/callback.h" 9 #include "content/public/browser/browser_ppapi_host.h" 10 #include "content/public/browser/browser_thread.h" 11 #include "content/public/browser/render_process_host.h" 12 #include "content/public/browser/storage_partition.h" 13 #include "ppapi/c/pp_errors.h" 14 #include "ppapi/host/dispatch_host_message.h" 15 #include "ppapi/host/ppapi_host.h" 16 #include "ppapi/proxy/ppapi_messages.h" 17 #include "ppapi/shared_impl/file_type_conversion.h" 18 #include "webkit/browser/fileapi/file_system_context.h" 19 #include "webkit/browser/fileapi/file_system_operation_runner.h" 20 #include "webkit/common/fileapi/file_system_util.h" 21 22 namespace content { 23 24 namespace { 25 26 // TODO(teravest): Move this function to be shared and public in fileapi. 27 bool LooksLikeAGuid(const std::string& fsid) { 28 const size_t kExpectedFsIdSize = 32; 29 if (fsid.size() != kExpectedFsIdSize) 30 return false; 31 for (std::string::const_iterator it = fsid.begin(); it != fsid.end(); ++it) { 32 if (('A' <= *it && *it <= 'F') || ('0' <= *it && *it <= '9')) 33 continue; 34 return false; 35 } 36 return true; 37 } 38 39 scoped_refptr<fileapi::FileSystemContext> 40 GetFileSystemContextFromRenderId(int render_process_id) { 41 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 42 RenderProcessHost* render_process_host = 43 RenderProcessHost::FromID(render_process_id); 44 if (!render_process_host) 45 return NULL; 46 StoragePartition* storage_partition = 47 render_process_host->GetStoragePartition(); 48 if (!storage_partition) 49 return NULL; 50 return storage_partition->GetFileSystemContext(); 51 } 52 53 } // namespace 54 55 PepperFileSystemBrowserHost::PepperFileSystemBrowserHost(BrowserPpapiHost* host, 56 PP_Instance instance, 57 PP_Resource resource, 58 PP_FileSystemType type) 59 : ResourceHost(host->GetPpapiHost(), instance, resource), 60 browser_ppapi_host_(host), 61 weak_factory_(this), 62 type_(type), 63 opened_(false), 64 fs_context_(NULL), 65 called_open_(false) { 66 } 67 68 PepperFileSystemBrowserHost::~PepperFileSystemBrowserHost() { 69 if (fs_context_.get()) 70 fs_context_->operation_runner()->Shutdown(); 71 } 72 73 int32_t PepperFileSystemBrowserHost::OnResourceMessageReceived( 74 const IPC::Message& msg, 75 ppapi::host::HostMessageContext* context) { 76 IPC_BEGIN_MESSAGE_MAP(PepperFileSystemBrowserHost, msg) 77 PPAPI_DISPATCH_HOST_RESOURCE_CALL( 78 PpapiHostMsg_FileSystem_Open, 79 OnHostMsgOpen) 80 PPAPI_DISPATCH_HOST_RESOURCE_CALL( 81 PpapiHostMsg_FileSystem_InitIsolatedFileSystem, 82 OnHostMsgInitIsolatedFileSystem) 83 IPC_END_MESSAGE_MAP() 84 return PP_ERROR_FAILED; 85 } 86 87 bool PepperFileSystemBrowserHost::IsFileSystemHost() { 88 return true; 89 } 90 91 int32_t PepperFileSystemBrowserHost::OnHostMsgOpen( 92 ppapi::host::HostMessageContext* context, 93 int64_t /* unused */) { 94 // TODO(raymes): The file system size is now unused by FileSystemDispatcher. 95 // Figure out why. Why is the file system size signed? 96 97 // Not allow multiple opens. 98 if (called_open_) 99 return PP_ERROR_INPROGRESS; 100 called_open_ = true; 101 102 fileapi::FileSystemType file_system_type; 103 switch (type_) { 104 case PP_FILESYSTEMTYPE_LOCALTEMPORARY: 105 file_system_type = fileapi::kFileSystemTypeTemporary; 106 break; 107 case PP_FILESYSTEMTYPE_LOCALPERSISTENT: 108 file_system_type = fileapi::kFileSystemTypePersistent; 109 break; 110 case PP_FILESYSTEMTYPE_EXTERNAL: 111 file_system_type = fileapi::kFileSystemTypeExternal; 112 break; 113 default: 114 return PP_ERROR_FAILED; 115 } 116 117 int render_process_id = 0; 118 int unused; 119 if (!browser_ppapi_host_->GetRenderViewIDsForInstance(pp_instance(), 120 &render_process_id, 121 &unused)) { 122 return PP_ERROR_FAILED; 123 } 124 BrowserThread::PostTaskAndReplyWithResult( 125 BrowserThread::UI, 126 FROM_HERE, 127 base::Bind(&GetFileSystemContextFromRenderId, render_process_id), 128 base::Bind(&PepperFileSystemBrowserHost::GotFileSystemContext, 129 weak_factory_.GetWeakPtr(), 130 context->MakeReplyMessageContext(), 131 file_system_type)); 132 return PP_OK_COMPLETIONPENDING; 133 } 134 135 void PepperFileSystemBrowserHost::GotFileSystemContext( 136 ppapi::host::ReplyMessageContext reply_context, 137 fileapi::FileSystemType file_system_type, 138 scoped_refptr<fileapi::FileSystemContext> fs_context) { 139 if (!fs_context.get()) { 140 OpenFileSystemComplete( 141 reply_context, base::PLATFORM_FILE_ERROR_FAILED, std::string(), GURL()); 142 return; 143 } 144 GURL origin = browser_ppapi_host_->GetDocumentURLForInstance( 145 pp_instance()).GetOrigin(); 146 fs_context->OpenFileSystem(origin, file_system_type, 147 fileapi::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT, 148 base::Bind(&PepperFileSystemBrowserHost::OpenFileSystemComplete, 149 weak_factory_.GetWeakPtr(), 150 reply_context)); 151 fs_context_ = fs_context; 152 } 153 154 void PepperFileSystemBrowserHost::OpenFileSystemComplete( 155 ppapi::host::ReplyMessageContext reply_context, 156 base::PlatformFileError error, 157 const std::string& /* unused */, 158 const GURL& root) { 159 int32 pp_error = ppapi::PlatformFileErrorToPepperError(error); 160 if (pp_error == PP_OK) { 161 opened_ = true; 162 root_url_ = root; 163 } 164 reply_context.params.set_result(pp_error); 165 host()->SendReply(reply_context, PpapiPluginMsg_FileSystem_OpenReply()); 166 } 167 168 int32_t PepperFileSystemBrowserHost::OnHostMsgInitIsolatedFileSystem( 169 ppapi::host::HostMessageContext* context, 170 const std::string& fsid) { 171 called_open_ = true; 172 // Do a sanity check. 173 if (!LooksLikeAGuid(fsid)) 174 return PP_ERROR_BADARGUMENT; 175 const GURL& url = 176 browser_ppapi_host_->GetDocumentURLForInstance(pp_instance()); 177 root_url_ = GURL(fileapi::GetIsolatedFileSystemRootURIString( 178 url.GetOrigin(), fsid, "crxfs")); 179 opened_ = true; 180 return PP_OK; 181 } 182 183 } // namespace content 184