Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / third_party / WebKit / Source / modules / filesystem / InspectorFileSystemAgent.cpp
blobefe12c6a1972ca30caca54324e1c7db7d525c088
1 /*
2 * Copyright (C) 2011, 2012 Google Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
13 * distribution.
14 * * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #include "config.h"
32 #include "modules/filesystem/InspectorFileSystemAgent.h"
34 #include "bindings/core/v8/ExceptionStatePlaceholder.h"
35 #include "bindings/core/v8/UnionTypesCore.h"
36 #include "core/dom/DOMArrayBuffer.h"
37 #include "core/dom/DOMImplementation.h"
38 #include "core/dom/Document.h"
39 #include "core/events/Event.h"
40 #include "core/fileapi/File.h"
41 #include "core/fileapi/FileCallback.h"
42 #include "core/fileapi/FileError.h"
43 #include "core/fileapi/FileReader.h"
44 #include "core/frame/LocalFrame.h"
45 #include "core/html/HTMLMediaElement.h"
46 #include "core/html/VoidCallback.h"
47 #include "core/html/parser/TextResourceDecoder.h"
48 #include "core/inspector/InspectorState.h"
49 #include "core/page/Page.h"
50 #include "modules/filesystem/DOMFileSystem.h"
51 #include "modules/filesystem/DirectoryEntry.h"
52 #include "modules/filesystem/DirectoryReader.h"
53 #include "modules/filesystem/EntriesCallback.h"
54 #include "modules/filesystem/Entry.h"
55 #include "modules/filesystem/EntryCallback.h"
56 #include "modules/filesystem/ErrorCallback.h"
57 #include "modules/filesystem/FileEntry.h"
58 #include "modules/filesystem/FileSystemCallbacks.h"
59 #include "modules/filesystem/LocalFileSystem.h"
60 #include "modules/filesystem/Metadata.h"
61 #include "modules/filesystem/MetadataCallback.h"
62 #include "platform/ContentType.h"
63 #include "platform/MIMETypeRegistry.h"
64 #include "platform/heap/Handle.h"
65 #include "platform/weborigin/KURL.h"
66 #include "platform/weborigin/SecurityOrigin.h"
67 #include "wtf/text/Base64.h"
68 #include "wtf/text/TextEncoding.h"
70 using blink::TypeBuilder::Array;
72 typedef blink::InspectorBackendDispatcher::FileSystemCommandHandler::RequestFileSystemRootCallback RequestFileSystemRootCallback;
73 typedef blink::InspectorBackendDispatcher::FileSystemCommandHandler::RequestDirectoryContentCallback RequestDirectoryContentCallback;
74 typedef blink::InspectorBackendDispatcher::FileSystemCommandHandler::RequestMetadataCallback RequestMetadataCallback;
75 typedef blink::InspectorBackendDispatcher::FileSystemCommandHandler::RequestFileContentCallback RequestFileContentCallback;
76 typedef blink::InspectorBackendDispatcher::FileSystemCommandHandler::DeleteEntryCallback DeleteEntryCallback;
78 namespace blink {
80 namespace FileSystemAgentState {
81 static const char fileSystemAgentEnabled[] = "fileSystemAgentEnabled";
84 namespace {
86 template<typename BaseCallback, typename Handler, typename Argument>
87 class GC_PLUGIN_IGNORE("crbug.com/513077") CallbackDispatcher final : public BaseCallback {
88 public:
89 typedef bool (Handler::*HandlingMethod)(Argument);
91 static CallbackDispatcher* create(PassRefPtrWillBeRawPtr<Handler> handler, HandlingMethod handlingMethod)
93 return new CallbackDispatcher(handler, handlingMethod);
96 void handleEvent(Argument argument) override
98 (m_handler.get()->*m_handlingMethod)(argument);
101 DEFINE_INLINE_TRACE()
103 visitor->trace(m_handler);
104 BaseCallback::trace(visitor);
107 private:
108 CallbackDispatcher(PassRefPtrWillBeRawPtr<Handler> handler, HandlingMethod handlingMethod)
109 : m_handler(handler)
110 , m_handlingMethod(handlingMethod) { }
112 RefPtrWillBeMember<Handler> m_handler;
113 HandlingMethod m_handlingMethod;
116 template<typename BaseCallback>
117 class CallbackDispatcherFactory {
118 public:
119 template<typename Handler, typename Argument>
120 static CallbackDispatcher<BaseCallback, Handler, Argument>* create(Handler* handler, bool (Handler::*handlingMethod)(Argument))
122 return CallbackDispatcher<BaseCallback, Handler, Argument>::create(PassRefPtrWillBeRawPtr<Handler>(handler), handlingMethod);
126 class FileSystemRootRequest final : public RefCountedWillBeGarbageCollectedFinalized<FileSystemRootRequest> {
127 WTF_MAKE_NONCOPYABLE(FileSystemRootRequest);
128 public:
129 static PassRefPtrWillBeRawPtr<FileSystemRootRequest> create(PassRefPtrWillBeRawPtr<RequestFileSystemRootCallback> requestCallback, const String& type)
131 return adoptRefWillBeNoop(new FileSystemRootRequest(requestCallback, type));
134 void start(ExecutionContext*);
136 DEFINE_INLINE_TRACE()
138 visitor->trace(m_requestCallback);
141 private:
142 bool didHitError(FileError* error)
144 reportResult(error->code());
145 return true;
148 bool didGetEntry(Entry*);
150 void reportResult(FileError::ErrorCode errorCode, PassRefPtr<TypeBuilder::FileSystem::Entry> entry = nullptr)
152 m_requestCallback->sendSuccess(static_cast<int>(errorCode), entry);
155 FileSystemRootRequest(PassRefPtrWillBeRawPtr<RequestFileSystemRootCallback> requestCallback, const String& type)
156 : m_requestCallback(requestCallback)
157 , m_type(type) { }
159 RefPtrWillBeMember<RequestFileSystemRootCallback> m_requestCallback;
160 String m_type;
163 void FileSystemRootRequest::start(ExecutionContext* executionContext)
165 ASSERT(executionContext);
167 ErrorCallback* errorCallback = CallbackDispatcherFactory<ErrorCallback>::create(this, &FileSystemRootRequest::didHitError);
169 FileSystemType type;
170 if (!DOMFileSystemBase::pathPrefixToFileSystemType(m_type, type)) {
171 errorCallback->handleEvent(FileError::create(FileError::SYNTAX_ERR));
172 return;
175 KURL rootURL = DOMFileSystemBase::createFileSystemRootURL(executionContext->securityOrigin()->toString(), type);
176 if (!rootURL.isValid()) {
177 errorCallback->handleEvent(FileError::create(FileError::SYNTAX_ERR));
178 return;
181 EntryCallback* successCallback = CallbackDispatcherFactory<EntryCallback>::create(this, &FileSystemRootRequest::didGetEntry);
182 OwnPtr<AsyncFileSystemCallbacks> fileSystemCallbacks = ResolveURICallbacks::create(successCallback, errorCallback, executionContext);
183 LocalFileSystem::from(*executionContext)->resolveURL(executionContext, rootURL, fileSystemCallbacks.release());
186 bool FileSystemRootRequest::didGetEntry(Entry* entry)
188 RefPtr<TypeBuilder::FileSystem::Entry> result = TypeBuilder::FileSystem::Entry::create()
189 .setUrl(entry->toURL())
190 .setName("/")
191 .setIsDirectory(true);
192 reportResult(static_cast<FileError::ErrorCode>(0), result);
193 return true;
196 class DirectoryContentRequest final : public RefCountedWillBeGarbageCollectedFinalized<DirectoryContentRequest> {
197 WTF_MAKE_NONCOPYABLE(DirectoryContentRequest);
198 public:
199 static PassRefPtrWillBeRawPtr<DirectoryContentRequest> create(PassRefPtrWillBeRawPtr<RequestDirectoryContentCallback> requestCallback, const String& url)
201 return adoptRefWillBeNoop(new DirectoryContentRequest(requestCallback, url));
204 ~DirectoryContentRequest()
208 void start(ExecutionContext*);
210 DEFINE_INLINE_VIRTUAL_TRACE()
212 visitor->trace(m_requestCallback);
213 visitor->trace(m_directoryReader);
216 private:
217 bool didHitError(FileError* error)
219 reportResult(error->code());
220 return true;
223 bool didGetEntry(Entry*);
224 bool didReadDirectoryEntries(const EntryHeapVector&);
226 void reportResult(FileError::ErrorCode errorCode, PassRefPtr<Array<TypeBuilder::FileSystem::Entry>> entries = nullptr)
228 m_requestCallback->sendSuccess(static_cast<int>(errorCode), entries);
231 DirectoryContentRequest(PassRefPtrWillBeRawPtr<RequestDirectoryContentCallback> requestCallback, const String& url)
232 : m_requestCallback(requestCallback)
233 , m_url(ParsedURLString, url) { }
235 void readDirectoryEntries();
237 RefPtrWillBeMember<RequestDirectoryContentCallback> m_requestCallback;
238 KURL m_url;
239 RefPtr<Array<TypeBuilder::FileSystem::Entry>> m_entries;
240 PersistentWillBeMember<DirectoryReader> m_directoryReader;
243 void DirectoryContentRequest::start(ExecutionContext* executionContext)
245 ASSERT(executionContext);
247 ErrorCallback* errorCallback = CallbackDispatcherFactory<ErrorCallback>::create(this, &DirectoryContentRequest::didHitError);
248 EntryCallback* successCallback = CallbackDispatcherFactory<EntryCallback>::create(this, &DirectoryContentRequest::didGetEntry);
250 OwnPtr<AsyncFileSystemCallbacks> fileSystemCallbacks = ResolveURICallbacks::create(successCallback, errorCallback, executionContext);
252 LocalFileSystem::from(*executionContext)->resolveURL(executionContext, m_url, fileSystemCallbacks.release());
255 bool DirectoryContentRequest::didGetEntry(Entry* entry)
257 if (!entry->isDirectory()) {
258 reportResult(FileError::TYPE_MISMATCH_ERR);
259 return true;
262 m_directoryReader = toDirectoryEntry(entry)->createReader();
263 m_entries = Array<TypeBuilder::FileSystem::Entry>::create();
264 readDirectoryEntries();
265 return true;
268 void DirectoryContentRequest::readDirectoryEntries()
270 if (!m_directoryReader->filesystem()->executionContext()) {
271 reportResult(FileError::ABORT_ERR);
272 return;
275 EntriesCallback* successCallback = CallbackDispatcherFactory<EntriesCallback>::create(this, &DirectoryContentRequest::didReadDirectoryEntries);
276 ErrorCallback* errorCallback = CallbackDispatcherFactory<ErrorCallback>::create(this, &DirectoryContentRequest::didHitError);
277 m_directoryReader->readEntries(successCallback, errorCallback);
280 bool DirectoryContentRequest::didReadDirectoryEntries(const EntryHeapVector& entries)
282 if (entries.isEmpty()) {
283 reportResult(static_cast<FileError::ErrorCode>(0), m_entries);
284 return true;
287 for (size_t i = 0; i < entries.size(); ++i) {
288 Entry* entry = entries[i];
289 RefPtr<TypeBuilder::FileSystem::Entry> entryForFrontend = TypeBuilder::FileSystem::Entry::create()
290 .setUrl(entry->toURL())
291 .setName(entry->name())
292 .setIsDirectory(entry->isDirectory());
294 using TypeBuilder::Page::ResourceType;
295 if (!entry->isDirectory()) {
296 String mimeType = MIMETypeRegistry::getMIMETypeForPath(entry->name());
297 ResourceType::Enum resourceType;
298 if (MIMETypeRegistry::isSupportedImageMIMEType(mimeType)) {
299 resourceType = ResourceType::Image;
300 entryForFrontend->setIsTextFile(false);
301 } else if (HTMLMediaElement::supportsType(ContentType(mimeType)) != WebMimeRegistry::IsNotSupported) {
302 resourceType = ResourceType::Media;
303 entryForFrontend->setIsTextFile(false);
304 } else if (MIMETypeRegistry::isSupportedJavaScriptMIMEType(mimeType)) {
305 resourceType = ResourceType::Script;
306 entryForFrontend->setIsTextFile(true);
307 } else if (MIMETypeRegistry::isSupportedNonImageMIMEType(mimeType)) {
308 resourceType = ResourceType::Document;
309 entryForFrontend->setIsTextFile(true);
310 } else {
311 resourceType = ResourceType::Other;
312 entryForFrontend->setIsTextFile(DOMImplementation::isXMLMIMEType(mimeType) || DOMImplementation::isTextMIMEType(mimeType));
315 entryForFrontend->setMimeType(mimeType);
316 entryForFrontend->setResourceType(resourceType);
319 m_entries->addItem(entryForFrontend);
321 readDirectoryEntries();
322 return true;
325 class MetadataRequest final : public RefCountedWillBeGarbageCollectedFinalized<MetadataRequest> {
326 WTF_MAKE_NONCOPYABLE(MetadataRequest);
327 public:
328 static PassRefPtrWillBeRawPtr<MetadataRequest> create(PassRefPtrWillBeRawPtr<RequestMetadataCallback> requestCallback, const String& url)
330 return adoptRefWillBeNoop(new MetadataRequest(requestCallback, url));
333 ~MetadataRequest()
337 void start(ExecutionContext*);
339 DEFINE_INLINE_VIRTUAL_TRACE()
341 visitor->trace(m_requestCallback);
344 private:
345 bool didHitError(FileError* error)
347 reportResult(error->code());
348 return true;
351 bool didGetEntry(Entry*);
352 bool didGetMetadata(Metadata*);
354 void reportResult(FileError::ErrorCode errorCode, PassRefPtr<TypeBuilder::FileSystem::Metadata> metadata = nullptr)
356 m_requestCallback->sendSuccess(static_cast<int>(errorCode), metadata);
359 MetadataRequest(PassRefPtrWillBeRawPtr<RequestMetadataCallback> requestCallback, const String& url)
360 : m_requestCallback(requestCallback)
361 , m_url(ParsedURLString, url) { }
363 RefPtrWillBeMember<RequestMetadataCallback> m_requestCallback;
364 KURL m_url;
365 bool m_isDirectory;
368 void MetadataRequest::start(ExecutionContext* executionContext)
370 ASSERT(executionContext);
372 ErrorCallback* errorCallback = CallbackDispatcherFactory<ErrorCallback>::create(this, &MetadataRequest::didHitError);
373 EntryCallback* successCallback = CallbackDispatcherFactory<EntryCallback>::create(this, &MetadataRequest::didGetEntry);
374 OwnPtr<AsyncFileSystemCallbacks> fileSystemCallbacks = ResolveURICallbacks::create(successCallback, errorCallback, executionContext);
375 LocalFileSystem::from(*executionContext)->resolveURL(executionContext, m_url, fileSystemCallbacks.release());
378 bool MetadataRequest::didGetEntry(Entry* entry)
380 if (!entry->filesystem()->executionContext()) {
381 reportResult(FileError::ABORT_ERR);
382 return true;
385 MetadataCallback* successCallback = CallbackDispatcherFactory<MetadataCallback>::create(this, &MetadataRequest::didGetMetadata);
386 ErrorCallback* errorCallback = CallbackDispatcherFactory<ErrorCallback>::create(this, &MetadataRequest::didHitError);
387 entry->getMetadata(successCallback, errorCallback);
388 m_isDirectory = entry->isDirectory();
389 return true;
392 bool MetadataRequest::didGetMetadata(Metadata* metadata)
394 using TypeBuilder::FileSystem::Metadata;
395 RefPtr<Metadata> result = Metadata::create()
396 .setModificationTime(metadata->modificationTime())
397 .setSize(metadata->size());
398 reportResult(static_cast<FileError::ErrorCode>(0), result);
399 return true;
402 class FileContentRequest final : public EventListener {
403 WTF_MAKE_NONCOPYABLE(FileContentRequest);
404 public:
405 static PassRefPtrWillBeRawPtr<FileContentRequest> create(PassRefPtrWillBeRawPtr<RequestFileContentCallback> requestCallback, const String& url, bool readAsText, long long start, long long end, const String& charset)
407 return adoptRefWillBeNoop(new FileContentRequest(requestCallback, url, readAsText, start, end, charset));
410 ~FileContentRequest() override
414 void start(ExecutionContext*);
416 bool operator==(const EventListener& other) override
418 return this == &other;
421 void handleEvent(ExecutionContext*, Event* event) override
423 if (event->type() == EventTypeNames::load)
424 didRead();
425 else if (event->type() == EventTypeNames::error)
426 didHitError(m_reader->error());
429 DEFINE_INLINE_VIRTUAL_TRACE()
431 visitor->trace(m_requestCallback);
432 visitor->trace(m_reader);
433 EventListener::trace(visitor);
436 private:
437 bool didHitError(FileError* error)
439 reportResult(error->code());
440 return true;
443 bool didGetEntry(Entry*);
444 bool didGetFile(File*);
445 void didRead();
447 void reportResult(FileError::ErrorCode errorCode, const String* result = 0, const String* charset = 0)
449 m_requestCallback->sendSuccess(static_cast<int>(errorCode), result, charset);
452 FileContentRequest(PassRefPtrWillBeRawPtr<RequestFileContentCallback> requestCallback, const String& url, bool readAsText, long long start, long long end, const String& charset)
453 : EventListener(EventListener::CPPEventListenerType)
454 , m_requestCallback(requestCallback)
455 , m_url(ParsedURLString, url)
456 , m_readAsText(readAsText)
457 , m_start(start)
458 , m_end(end)
459 , m_charset(charset) { }
461 RefPtrWillBeMember<RequestFileContentCallback> m_requestCallback;
462 KURL m_url;
463 bool m_readAsText;
464 int m_start;
465 long long m_end;
466 String m_mimeType;
467 String m_charset;
469 PersistentWillBeMember<FileReader> m_reader;
472 void FileContentRequest::start(ExecutionContext* executionContext)
474 ASSERT(executionContext);
476 ErrorCallback* errorCallback = CallbackDispatcherFactory<ErrorCallback>::create(this, &FileContentRequest::didHitError);
477 EntryCallback* successCallback = CallbackDispatcherFactory<EntryCallback>::create(this, &FileContentRequest::didGetEntry);
479 OwnPtr<AsyncFileSystemCallbacks> fileSystemCallbacks = ResolveURICallbacks::create(successCallback, errorCallback, executionContext);
480 LocalFileSystem::from(*executionContext)->resolveURL(executionContext, m_url, fileSystemCallbacks.release());
483 bool FileContentRequest::didGetEntry(Entry* entry)
485 if (entry->isDirectory()) {
486 reportResult(FileError::TYPE_MISMATCH_ERR);
487 return true;
490 if (!entry->filesystem()->executionContext()) {
491 reportResult(FileError::ABORT_ERR);
492 return true;
495 FileCallback* successCallback = CallbackDispatcherFactory<FileCallback>::create(this, &FileContentRequest::didGetFile);
496 ErrorCallback* errorCallback = CallbackDispatcherFactory<ErrorCallback>::create(this, &FileContentRequest::didHitError);
497 toFileEntry(entry)->file(successCallback, errorCallback);
499 m_reader = FileReader::create(entry->filesystem()->executionContext());
500 m_mimeType = MIMETypeRegistry::getMIMETypeForPath(entry->name());
502 return true;
505 bool FileContentRequest::didGetFile(File* file)
507 Blob* blob = file->Blob::slice(m_start, m_end, IGNORE_EXCEPTION);
508 m_reader->setOnload(this);
509 m_reader->setOnerror(this);
511 m_reader->readAsArrayBuffer(blob, IGNORE_EXCEPTION);
512 return true;
515 void FileContentRequest::didRead()
517 StringOrArrayBuffer resultAttribute;
518 m_reader->result(resultAttribute);
519 RefPtr<DOMArrayBuffer> buffer = resultAttribute.getAsArrayBuffer();
521 if (!m_readAsText) {
522 String result = base64Encode(static_cast<char*>(buffer->data()), buffer->byteLength());
523 reportResult(static_cast<FileError::ErrorCode>(0), &result, 0);
524 return;
527 OwnPtr<TextResourceDecoder> decoder = TextResourceDecoder::create(m_mimeType, m_charset, true);
528 String result = decoder->decode(static_cast<char*>(buffer->data()), buffer->byteLength());
529 result = result + decoder->flush();
530 m_charset = decoder->encoding().name();
531 reportResult(static_cast<FileError::ErrorCode>(0), &result, &m_charset);
534 class DeleteEntryRequest final : public RefCountedWillBeGarbageCollectedFinalized<DeleteEntryRequest> {
535 public:
536 static PassRefPtrWillBeRawPtr<DeleteEntryRequest> create(PassRefPtrWillBeRawPtr<DeleteEntryCallback> requestCallback, const KURL& url)
538 return adoptRefWillBeNoop(new DeleteEntryRequest(requestCallback, url));
541 ~DeleteEntryRequest()
545 void start(ExecutionContext*);
547 DEFINE_INLINE_TRACE()
549 visitor->trace(m_requestCallback);
552 private:
553 // CallbackDispatcherFactory doesn't handle 0-arg handleEvent methods
554 class VoidCallbackImpl final : public VoidCallback {
555 public:
556 explicit VoidCallbackImpl(PassRefPtrWillBeRawPtr<DeleteEntryRequest> handler)
557 : m_handler(handler)
561 void handleEvent() override
563 m_handler->didDeleteEntry();
566 DEFINE_INLINE_VIRTUAL_TRACE()
568 visitor->trace(m_handler);
569 VoidCallback::trace(visitor);
572 private:
573 RefPtrWillBeMember<DeleteEntryRequest> m_handler;
576 bool didHitError(FileError* error)
578 reportResult(error->code());
579 return true;
582 bool didGetEntry(Entry*);
583 bool didDeleteEntry();
585 void reportResult(FileError::ErrorCode errorCode)
587 m_requestCallback->sendSuccess(static_cast<int>(errorCode));
590 DeleteEntryRequest(PassRefPtrWillBeRawPtr<DeleteEntryCallback> requestCallback, const KURL& url)
591 : m_requestCallback(requestCallback)
592 , m_url(url) { }
594 RefPtrWillBeMember<DeleteEntryCallback> m_requestCallback;
595 KURL m_url;
598 void DeleteEntryRequest::start(ExecutionContext* executionContext)
600 ASSERT(executionContext);
602 ErrorCallback* errorCallback = CallbackDispatcherFactory<ErrorCallback>::create(this, &DeleteEntryRequest::didHitError);
604 FileSystemType type;
605 String path;
606 if (!DOMFileSystemBase::crackFileSystemURL(m_url, type, path)) {
607 errorCallback->handleEvent(FileError::create(FileError::SYNTAX_ERR));
608 return;
611 if (path == "/") {
612 VoidCallback* successCallback = new VoidCallbackImpl(this);
613 OwnPtr<AsyncFileSystemCallbacks> fileSystemCallbacks = VoidCallbacks::create(successCallback, errorCallback, executionContext, nullptr);
614 LocalFileSystem::from(*executionContext)->deleteFileSystem(executionContext, type, fileSystemCallbacks.release());
615 } else {
616 EntryCallback* successCallback = CallbackDispatcherFactory<EntryCallback>::create(this, &DeleteEntryRequest::didGetEntry);
617 OwnPtr<AsyncFileSystemCallbacks> fileSystemCallbacks = ResolveURICallbacks::create(successCallback, errorCallback, executionContext);
618 LocalFileSystem::from(*executionContext)->resolveURL(executionContext, m_url, fileSystemCallbacks.release());
622 bool DeleteEntryRequest::didGetEntry(Entry* entry)
624 VoidCallback* successCallback = new VoidCallbackImpl(this);
625 ErrorCallback* errorCallback = CallbackDispatcherFactory<ErrorCallback>::create(this, &DeleteEntryRequest::didHitError);
626 if (entry->isDirectory()) {
627 DirectoryEntry* directoryEntry = toDirectoryEntry(entry);
628 directoryEntry->removeRecursively(successCallback, errorCallback);
629 } else {
630 entry->remove(successCallback, errorCallback);
632 return true;
635 bool DeleteEntryRequest::didDeleteEntry()
637 reportResult(static_cast<FileError::ErrorCode>(0));
638 return true;
641 } // anonymous namespace
643 // static
644 PassOwnPtrWillBeRawPtr<InspectorFileSystemAgent> InspectorFileSystemAgent::create(Page* page)
646 return adoptPtrWillBeNoop(new InspectorFileSystemAgent(page));
649 InspectorFileSystemAgent::~InspectorFileSystemAgent()
653 void InspectorFileSystemAgent::enable(ErrorString*)
655 if (m_enabled)
656 return;
657 m_enabled = true;
658 m_state->setBoolean(FileSystemAgentState::fileSystemAgentEnabled, m_enabled);
661 void InspectorFileSystemAgent::disable(ErrorString*)
663 if (!m_enabled)
664 return;
665 m_enabled = false;
666 m_state->setBoolean(FileSystemAgentState::fileSystemAgentEnabled, m_enabled);
669 void InspectorFileSystemAgent::requestFileSystemRoot(ErrorString* error, const String& origin, const String& type, PassRefPtrWillBeRawPtr<RequestFileSystemRootCallback> requestCallback)
671 if (!assertEnabled(error))
672 return;
674 ExecutionContext* executionContext = assertExecutionContextForOrigin(error, SecurityOrigin::createFromString(origin).get());
675 if (!executionContext)
676 return;
678 FileSystemRootRequest::create(requestCallback, type)->start(executionContext);
681 void InspectorFileSystemAgent::requestDirectoryContent(ErrorString* error, const String& url, PassRefPtrWillBeRawPtr<RequestDirectoryContentCallback> requestCallback)
683 if (!assertEnabled(error))
684 return;
686 ExecutionContext* executionContext = assertExecutionContextForOrigin(error, SecurityOrigin::createFromString(url).get());
687 if (!executionContext)
688 return;
690 DirectoryContentRequest::create(requestCallback, url)->start(executionContext);
693 void InspectorFileSystemAgent::requestMetadata(ErrorString* error, const String& url, PassRefPtrWillBeRawPtr<RequestMetadataCallback> requestCallback)
695 if (!assertEnabled(error))
696 return;
698 ExecutionContext* executionContext = assertExecutionContextForOrigin(error, SecurityOrigin::createFromString(url).get());
699 if (!executionContext)
700 return;
702 MetadataRequest::create(requestCallback, url)->start(executionContext);
705 void InspectorFileSystemAgent::requestFileContent(ErrorString* error, const String& url, bool readAsText, const int* start, const int* end, const String* charset, PassRefPtrWillBeRawPtr<RequestFileContentCallback> requestCallback)
707 if (!assertEnabled(error))
708 return;
710 ExecutionContext* executionContext = assertExecutionContextForOrigin(error, SecurityOrigin::createFromString(url).get());
711 if (!executionContext)
712 return;
714 long long startPosition = start ? *start : 0;
715 long long endPosition = end ? *end : std::numeric_limits<long long>::max();
716 FileContentRequest::create(requestCallback, url, readAsText, startPosition, endPosition, charset ? *charset : "")->start(executionContext);
719 void InspectorFileSystemAgent::deleteEntry(ErrorString* error, const String& urlString, PassRefPtrWillBeRawPtr<DeleteEntryCallback> requestCallback)
721 if (!assertEnabled(error))
722 return;
724 KURL url(ParsedURLString, urlString);
726 ExecutionContext* executionContext = assertExecutionContextForOrigin(error, SecurityOrigin::create(url).get());
727 if (!executionContext)
728 return;
730 DeleteEntryRequest::create(requestCallback, url)->start(executionContext);
733 void InspectorFileSystemAgent::restore()
735 m_enabled = m_state->getBoolean(FileSystemAgentState::fileSystemAgentEnabled);
738 InspectorFileSystemAgent::InspectorFileSystemAgent(Page* page)
739 : InspectorBaseAgent<InspectorFileSystemAgent, InspectorFrontend::FileSystem>("FileSystem")
740 , m_page(page)
741 , m_enabled(false)
743 ASSERT(m_page);
746 bool InspectorFileSystemAgent::assertEnabled(ErrorString* error)
748 if (!m_enabled) {
749 *error = "FileSystem agent is not enabled.";
750 return false;
752 return true;
755 ExecutionContext* InspectorFileSystemAgent::assertExecutionContextForOrigin(ErrorString* error, SecurityOrigin* origin)
757 for (Frame* frame = m_page->mainFrame(); frame; frame = frame->tree().traverseNext()) {
758 if (!frame->isLocalFrame())
759 continue;
760 LocalFrame* localFrame = toLocalFrame(frame);
761 if (localFrame->document() && localFrame->document()->securityOrigin()->isSameSchemeHostPort(origin))
762 return localFrame->document();
765 *error = "No frame is available for the request";
766 return 0;
769 DEFINE_TRACE(InspectorFileSystemAgent)
771 visitor->trace(m_page);
772 InspectorBaseAgent::trace(visitor);
775 } // namespace blink