1 /*
2 * Copyright (C) 2008 Apple Inc. All Rights Reserved.
3 * Copyright (C) 2009, 2011 Google Inc. All Rights Reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 *
26 */
27
28 #include "third_party/blink/renderer/modules/filesystem/worker_global_scope_file_system.h"
29
30 #include <memory>
31
32 #include "third_party/blink/public/mojom/filesystem/file_system.mojom-blink.h"
33 #include "third_party/blink/renderer/core/fileapi/file_error.h"
34 #include "third_party/blink/renderer/core/workers/worker_global_scope.h"
35 #include "third_party/blink/renderer/modules/filesystem/async_callback_helper.h"
36 #include "third_party/blink/renderer/modules/filesystem/directory_entry_sync.h"
37 #include "third_party/blink/renderer/modules/filesystem/dom_file_system.h"
38 #include "third_party/blink/renderer/modules/filesystem/entry.h"
39 #include "third_party/blink/renderer/modules/filesystem/file_entry_sync.h"
40 #include "third_party/blink/renderer/modules/filesystem/file_system_callbacks.h"
41 #include "third_party/blink/renderer/modules/filesystem/local_file_system.h"
42 #include "third_party/blink/renderer/modules/filesystem/sync_callback_helper.h"
43 #include "third_party/blink/renderer/platform/bindings/exception_state.h"
44 #include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
45 #include "third_party/blink/renderer/platform/weborigin/security_origin.h"
46
47 namespace blink {
48
webkitRequestFileSystem(WorkerGlobalScope & worker,int type,int64_t size,V8FileSystemCallback * success_callback,V8ErrorCallback * error_callback)49 void WorkerGlobalScopeFileSystem::webkitRequestFileSystem(
50 WorkerGlobalScope& worker,
51 int type,
52 int64_t size,
53 V8FileSystemCallback* success_callback,
54 V8ErrorCallback* error_callback) {
55 ExecutionContext* secure_context = worker.GetExecutionContext();
56 auto error_callback_wrapper =
57 AsyncCallbackHelper::ErrorCallback(error_callback);
58
59 if (!secure_context->GetSecurityOrigin()->CanAccessFileSystem()) {
60 DOMFileSystem::ReportError(&worker, std::move(error_callback_wrapper),
61 base::File::FILE_ERROR_SECURITY);
62 return;
63 } else if (secure_context->GetSecurityOrigin()->IsLocal()) {
64 UseCounter::Count(secure_context, WebFeature::kFileAccessedFileSystem);
65 }
66
67 mojom::blink::FileSystemType file_system_type =
68 static_cast<mojom::blink::FileSystemType>(type);
69 if (!DOMFileSystemBase::IsValidType(file_system_type)) {
70 DOMFileSystem::ReportError(&worker, std::move(error_callback_wrapper),
71 base::File::FILE_ERROR_INVALID_OPERATION);
72 return;
73 }
74
75 auto success_callback_wrapper =
76 AsyncCallbackHelper::SuccessCallback<DOMFileSystem>(success_callback);
77
78 LocalFileSystem::From(worker)->RequestFileSystem(
79 file_system_type, size,
80 std::make_unique<FileSystemCallbacks>(std::move(success_callback_wrapper),
81 std::move(error_callback_wrapper),
82 &worker, file_system_type),
83 LocalFileSystem::kAsynchronous);
84 }
85
webkitRequestFileSystemSync(WorkerGlobalScope & worker,int type,int64_t size,ExceptionState & exception_state)86 DOMFileSystemSync* WorkerGlobalScopeFileSystem::webkitRequestFileSystemSync(
87 WorkerGlobalScope& worker,
88 int type,
89 int64_t size,
90 ExceptionState& exception_state) {
91 ExecutionContext* secure_context = worker.GetExecutionContext();
92 if (!secure_context->GetSecurityOrigin()->CanAccessFileSystem()) {
93 exception_state.ThrowSecurityError(file_error::kSecurityErrorMessage);
94 return nullptr;
95 } else if (secure_context->GetSecurityOrigin()->IsLocal()) {
96 UseCounter::Count(secure_context, WebFeature::kFileAccessedFileSystem);
97 }
98
99 mojom::blink::FileSystemType file_system_type =
100 static_cast<mojom::blink::FileSystemType>(type);
101 if (!DOMFileSystemBase::IsValidType(file_system_type)) {
102 exception_state.ThrowDOMException(
103 DOMExceptionCode::kInvalidModificationError,
104 "the type must be kTemporary or kPersistent.");
105 return nullptr;
106 }
107
108 auto* sync_helper = MakeGarbageCollected<FileSystemCallbacksSyncHelper>();
109
110 auto success_callback_wrapper =
111 WTF::Bind(&FileSystemCallbacksSyncHelper::OnSuccess,
112 WrapPersistentIfNeeded(sync_helper));
113 auto error_callback_wrapper =
114 WTF::Bind(&FileSystemCallbacksSyncHelper::OnError,
115 WrapPersistentIfNeeded(sync_helper));
116
117 auto callbacks = std::make_unique<FileSystemCallbacks>(
118 std::move(success_callback_wrapper), std::move(error_callback_wrapper),
119 &worker, file_system_type);
120
121 LocalFileSystem::From(worker)->RequestFileSystem(
122 file_system_type, size, std::move(callbacks),
123 LocalFileSystem::kSynchronous);
124 DOMFileSystem* file_system = sync_helper->GetResultOrThrow(exception_state);
125 return file_system ? MakeGarbageCollected<DOMFileSystemSync>(file_system)
126 : nullptr;
127 }
128
webkitResolveLocalFileSystemURL(WorkerGlobalScope & worker,const String & url,V8EntryCallback * success_callback,V8ErrorCallback * error_callback)129 void WorkerGlobalScopeFileSystem::webkitResolveLocalFileSystemURL(
130 WorkerGlobalScope& worker,
131 const String& url,
132 V8EntryCallback* success_callback,
133 V8ErrorCallback* error_callback) {
134 KURL completed_url = worker.CompleteURL(url);
135 ExecutionContext* secure_context = worker.GetExecutionContext();
136 auto error_callback_wrapper =
137 AsyncCallbackHelper::ErrorCallback(error_callback);
138
139 if (!secure_context->GetSecurityOrigin()->CanAccessFileSystem() ||
140 !secure_context->GetSecurityOrigin()->CanRequest(completed_url)) {
141 DOMFileSystem::ReportError(&worker, std::move(error_callback_wrapper),
142 base::File::FILE_ERROR_SECURITY);
143 return;
144 } else if (secure_context->GetSecurityOrigin()->IsLocal()) {
145 UseCounter::Count(secure_context, WebFeature::kFileAccessedFileSystem);
146 }
147
148 if (!completed_url.IsValid()) {
149 DOMFileSystem::ReportError(&worker, std::move(error_callback_wrapper),
150 base::File::FILE_ERROR_INVALID_URL);
151 return;
152 }
153
154 auto success_callback_wrapper =
155 AsyncCallbackHelper::SuccessCallback<Entry>(success_callback);
156
157 LocalFileSystem::From(worker)->ResolveURL(
158 completed_url,
159 std::make_unique<ResolveURICallbacks>(std::move(success_callback_wrapper),
160 std::move(error_callback_wrapper),
161 &worker),
162 LocalFileSystem::kAsynchronous);
163 }
164
webkitResolveLocalFileSystemSyncURL(WorkerGlobalScope & worker,const String & url,ExceptionState & exception_state)165 EntrySync* WorkerGlobalScopeFileSystem::webkitResolveLocalFileSystemSyncURL(
166 WorkerGlobalScope& worker,
167 const String& url,
168 ExceptionState& exception_state) {
169 KURL completed_url = worker.CompleteURL(url);
170 ExecutionContext* secure_context = worker.GetExecutionContext();
171 if (!secure_context->GetSecurityOrigin()->CanAccessFileSystem() ||
172 !secure_context->GetSecurityOrigin()->CanRequest(completed_url)) {
173 exception_state.ThrowSecurityError(file_error::kSecurityErrorMessage);
174 return nullptr;
175 } else if (secure_context->GetSecurityOrigin()->IsLocal()) {
176 UseCounter::Count(secure_context, WebFeature::kFileAccessedFileSystem);
177 }
178
179 if (!completed_url.IsValid()) {
180 exception_state.ThrowDOMException(DOMExceptionCode::kEncodingError,
181 "the URL '" + url + "' is invalid.");
182 return nullptr;
183 }
184
185 auto* sync_helper = MakeGarbageCollected<EntryCallbacksSyncHelper>();
186
187 auto success_callback_wrapper =
188 WTF::Bind(&EntryCallbacksSyncHelper::OnSuccess,
189 WrapPersistentIfNeeded(sync_helper));
190 auto error_callback_wrapper = WTF::Bind(&EntryCallbacksSyncHelper::OnError,
191 WrapPersistentIfNeeded(sync_helper));
192
193 std::unique_ptr<ResolveURICallbacks> callbacks =
194 std::make_unique<ResolveURICallbacks>(std::move(success_callback_wrapper),
195 std::move(error_callback_wrapper),
196 &worker);
197
198 LocalFileSystem::From(worker)->ResolveURL(completed_url, std::move(callbacks),
199 LocalFileSystem::kSynchronous);
200
201 Entry* entry = sync_helper->GetResultOrThrow(exception_state);
202 return entry ? EntrySync::Create(entry) : nullptr;
203 }
204
205 static_assert(static_cast<int>(WorkerGlobalScopeFileSystem::kTemporary) ==
206 static_cast<int>(mojom::blink::FileSystemType::kTemporary),
207 "WorkerGlobalScopeFileSystem::kTemporary should match "
208 "FileSystemTypeTemporary");
209 static_assert(static_cast<int>(WorkerGlobalScopeFileSystem::kPersistent) ==
210 static_cast<int>(mojom::blink::FileSystemType::kPersistent),
211 "WorkerGlobalScopeFileSystem::kPersistent should match "
212 "FileSystemTypePersistent");
213
214 } // namespace blink
215