Upstream version 5.34.98.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / inspector / InspectorFileSystemAgent.cpp
1 /*
2  * Copyright (C) 2011, 2012 Google Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
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.
17  *
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.
29  */
30
31 #include "config.h"
32 #include "core/inspector/InspectorFileSystemAgent.h"
33
34 #include "bindings/v8/ExceptionStatePlaceholder.h"
35 #include "core/dom/DOMImplementation.h"
36 #include "core/dom/Document.h"
37 #include "core/events/Event.h"
38 #include "core/fileapi/File.h"
39 #include "core/fileapi/FileError.h"
40 #include "core/fileapi/FileReader.h"
41 #include "core/frame/Frame.h"
42 #include "core/html/VoidCallback.h"
43 #include "core/html/parser/TextResourceDecoder.h"
44 #include "core/inspector/InspectorPageAgent.h"
45 #include "core/inspector/InspectorState.h"
46 #include "modules/filesystem/DOMFileSystem.h"
47 #include "modules/filesystem/DirectoryEntry.h"
48 #include "modules/filesystem/DirectoryReader.h"
49 #include "modules/filesystem/EntriesCallback.h"
50 #include "modules/filesystem/Entry.h"
51 #include "modules/filesystem/EntryCallback.h"
52 #include "modules/filesystem/ErrorCallback.h"
53 #include "modules/filesystem/FileCallback.h"
54 #include "modules/filesystem/FileEntry.h"
55 #include "modules/filesystem/FileSystemCallbacks.h"
56 #include "modules/filesystem/LocalFileSystem.h"
57 #include "modules/filesystem/Metadata.h"
58 #include "modules/filesystem/MetadataCallback.h"
59 #include "platform/MIMETypeRegistry.h"
60 #include "platform/weborigin/KURL.h"
61 #include "platform/weborigin/SecurityOrigin.h"
62 #include "wtf/ArrayBuffer.h"
63 #include "wtf/text/Base64.h"
64 #include "wtf/text/TextEncoding.h"
65
66 using WebCore::TypeBuilder::Array;
67
68 typedef WebCore::InspectorBackendDispatcher::FileSystemCommandHandler::RequestFileSystemRootCallback RequestFileSystemRootCallback;
69 typedef WebCore::InspectorBackendDispatcher::FileSystemCommandHandler::RequestDirectoryContentCallback RequestDirectoryContentCallback;
70 typedef WebCore::InspectorBackendDispatcher::FileSystemCommandHandler::RequestMetadataCallback RequestMetadataCallback;
71 typedef WebCore::InspectorBackendDispatcher::FileSystemCommandHandler::RequestFileContentCallback RequestFileContentCallback;
72 typedef WebCore::InspectorBackendDispatcher::FileSystemCommandHandler::DeleteEntryCallback DeleteEntryCallback;
73
74 namespace WebCore {
75
76 namespace FileSystemAgentState {
77 static const char fileSystemAgentEnabled[] = "fileSystemAgentEnabled";
78 }
79
80 namespace {
81
82 template<typename BaseCallback, typename Handler, typename Argument>
83 class CallbackDispatcher FINAL : public BaseCallback {
84 public:
85     typedef bool (Handler::*HandlingMethod)(Argument);
86
87     static PassOwnPtr<CallbackDispatcher> create(PassRefPtr<Handler> handler, HandlingMethod handlingMethod)
88     {
89         return adoptPtr(new CallbackDispatcher(handler, handlingMethod));
90     }
91
92     virtual void handleEvent(Argument argument) OVERRIDE
93     {
94         (m_handler.get()->*m_handlingMethod)(argument);
95     }
96
97 private:
98     CallbackDispatcher(PassRefPtr<Handler> handler, HandlingMethod handlingMethod)
99         : m_handler(handler)
100         , m_handlingMethod(handlingMethod) { }
101
102     RefPtr<Handler> m_handler;
103     HandlingMethod m_handlingMethod;
104 };
105
106 template<typename BaseCallback>
107 class CallbackDispatcherFactory {
108 public:
109     template<typename Handler, typename Argument>
110     static PassOwnPtr<CallbackDispatcher<BaseCallback, Handler, Argument> > create(Handler* handler, bool (Handler::*handlingMethod)(Argument))
111     {
112         return CallbackDispatcher<BaseCallback, Handler, Argument>::create(PassRefPtr<Handler>(handler), handlingMethod);
113     }
114 };
115
116 class FileSystemRootRequest : public RefCounted<FileSystemRootRequest> {
117     WTF_MAKE_NONCOPYABLE(FileSystemRootRequest);
118 public:
119     static PassRefPtr<FileSystemRootRequest> create(PassRefPtr<RequestFileSystemRootCallback> requestCallback, const String& type)
120     {
121         return adoptRef(new FileSystemRootRequest(requestCallback, type));
122     }
123
124     void start(ExecutionContext*);
125
126 private:
127     bool didHitError(FileError* error)
128     {
129         reportResult(error->code());
130         return true;
131     }
132
133     bool didGetEntry(Entry*);
134
135     void reportResult(FileError::ErrorCode errorCode, PassRefPtr<TypeBuilder::FileSystem::Entry> entry = 0)
136     {
137         m_requestCallback->sendSuccess(static_cast<int>(errorCode), entry);
138     }
139
140     FileSystemRootRequest(PassRefPtr<RequestFileSystemRootCallback> requestCallback, const String& type)
141         : m_requestCallback(requestCallback)
142         , m_type(type) { }
143
144     RefPtr<RequestFileSystemRootCallback> m_requestCallback;
145     String m_type;
146 };
147
148 void FileSystemRootRequest::start(ExecutionContext* executionContext)
149 {
150     ASSERT(executionContext);
151
152     OwnPtr<ErrorCallback> errorCallback = CallbackDispatcherFactory<ErrorCallback>::create(this, &FileSystemRootRequest::didHitError);
153
154     FileSystemType type;
155     if (!DOMFileSystemBase::pathPrefixToFileSystemType(m_type, type)) {
156         errorCallback->handleEvent(FileError::create(FileError::SYNTAX_ERR).get());
157         return;
158     }
159
160     KURL rootURL = DOMFileSystemBase::createFileSystemRootURL(executionContext->securityOrigin()->toString(), type);
161     if (!rootURL.isValid()) {
162         errorCallback->handleEvent(FileError::create(FileError::SYNTAX_ERR).get());
163         return;
164     }
165
166     OwnPtr<EntryCallback> successCallback = CallbackDispatcherFactory<EntryCallback>::create(this, &FileSystemRootRequest::didGetEntry);
167     OwnPtr<AsyncFileSystemCallbacks> fileSystemCallbacks = ResolveURICallbacks::create(successCallback.release(), errorCallback.release(), executionContext);
168     LocalFileSystem::from(executionContext)->resolveURL(executionContext, rootURL, fileSystemCallbacks.release());
169 }
170
171 bool FileSystemRootRequest::didGetEntry(Entry* entry)
172 {
173     RefPtr<TypeBuilder::FileSystem::Entry> result = TypeBuilder::FileSystem::Entry::create()
174         .setUrl(entry->toURL())
175         .setName("/")
176         .setIsDirectory(true);
177     reportResult(static_cast<FileError::ErrorCode>(0), result);
178     return true;
179 }
180
181 class DirectoryContentRequest FINAL : public RefCounted<DirectoryContentRequest> {
182     WTF_MAKE_NONCOPYABLE(DirectoryContentRequest);
183 public:
184     static PassRefPtr<DirectoryContentRequest> create(PassRefPtr<RequestDirectoryContentCallback> requestCallback, const String& url)
185     {
186         return adoptRef(new DirectoryContentRequest(requestCallback, url));
187     }
188
189     ~DirectoryContentRequest()
190     {
191         reportResult(FileError::ABORT_ERR);
192     }
193
194     void start(ExecutionContext*);
195
196 private:
197     bool didHitError(FileError* error)
198     {
199         reportResult(error->code());
200         return true;
201     }
202
203     bool didGetEntry(Entry*);
204     bool didReadDirectoryEntries(const EntryVector&);
205
206     void reportResult(FileError::ErrorCode errorCode, PassRefPtr<Array<TypeBuilder::FileSystem::Entry> > entries = 0)
207     {
208         m_requestCallback->sendSuccess(static_cast<int>(errorCode), entries);
209     }
210
211     DirectoryContentRequest(PassRefPtr<RequestDirectoryContentCallback> requestCallback, const String& url)
212         : m_requestCallback(requestCallback)
213         , m_url(ParsedURLString, url) { }
214
215     void readDirectoryEntries();
216
217     RefPtr<RequestDirectoryContentCallback> m_requestCallback;
218     KURL m_url;
219     RefPtr<Array<TypeBuilder::FileSystem::Entry> > m_entries;
220     RefPtr<DirectoryReader> m_directoryReader;
221 };
222
223 void DirectoryContentRequest::start(ExecutionContext* executionContext)
224 {
225     ASSERT(executionContext);
226
227     OwnPtr<ErrorCallback> errorCallback = CallbackDispatcherFactory<ErrorCallback>::create(this, &DirectoryContentRequest::didHitError);
228     OwnPtr<EntryCallback> successCallback = CallbackDispatcherFactory<EntryCallback>::create(this, &DirectoryContentRequest::didGetEntry);
229
230     OwnPtr<AsyncFileSystemCallbacks> fileSystemCallbacks = ResolveURICallbacks::create(successCallback.release(), errorCallback.release(), executionContext);
231
232     LocalFileSystem::from(executionContext)->resolveURL(executionContext, m_url, fileSystemCallbacks.release());
233 }
234
235 bool DirectoryContentRequest::didGetEntry(Entry* entry)
236 {
237     if (!entry->isDirectory()) {
238         reportResult(FileError::TYPE_MISMATCH_ERR);
239         return true;
240     }
241
242     m_directoryReader = toDirectoryEntry(entry)->createReader();
243     m_entries = Array<TypeBuilder::FileSystem::Entry>::create();
244     readDirectoryEntries();
245     return true;
246 }
247
248 void DirectoryContentRequest::readDirectoryEntries()
249 {
250     if (!m_directoryReader->filesystem()->executionContext()) {
251         reportResult(FileError::ABORT_ERR);
252         return;
253     }
254
255     OwnPtr<EntriesCallback> successCallback = CallbackDispatcherFactory<EntriesCallback>::create(this, &DirectoryContentRequest::didReadDirectoryEntries);
256     OwnPtr<ErrorCallback> errorCallback = CallbackDispatcherFactory<ErrorCallback>::create(this, &DirectoryContentRequest::didHitError);
257     m_directoryReader->readEntries(successCallback.release(), errorCallback.release());
258 }
259
260 bool DirectoryContentRequest::didReadDirectoryEntries(const EntryVector& entries)
261 {
262     if (entries.isEmpty()) {
263         reportResult(static_cast<FileError::ErrorCode>(0), m_entries);
264         return true;
265     }
266
267     for (size_t i = 0; i < entries.size(); ++i) {
268         RefPtr<Entry> entry = entries[i];
269         RefPtr<TypeBuilder::FileSystem::Entry> entryForFrontend = TypeBuilder::FileSystem::Entry::create()
270             .setUrl(entry->toURL())
271             .setName(entry->name())
272             .setIsDirectory(entry->isDirectory());
273
274         using TypeBuilder::Page::ResourceType;
275         if (!entry->isDirectory()) {
276             String mimeType = MIMETypeRegistry::getMIMETypeForPath(entry->name());
277             ResourceType::Enum resourceType;
278             if (MIMETypeRegistry::isSupportedImageMIMEType(mimeType)) {
279                 resourceType = ResourceType::Image;
280                 entryForFrontend->setIsTextFile(false);
281             } else if (MIMETypeRegistry::isSupportedJavaScriptMIMEType(mimeType)) {
282                 resourceType = ResourceType::Script;
283                 entryForFrontend->setIsTextFile(true);
284             } else if (MIMETypeRegistry::isSupportedNonImageMIMEType(mimeType)) {
285                 resourceType = ResourceType::Document;
286                 entryForFrontend->setIsTextFile(true);
287             } else {
288                 resourceType = ResourceType::Other;
289                 entryForFrontend->setIsTextFile(DOMImplementation::isXMLMIMEType(mimeType) || DOMImplementation::isTextMIMEType(mimeType));
290             }
291
292             entryForFrontend->setMimeType(mimeType);
293             entryForFrontend->setResourceType(resourceType);
294         }
295
296         m_entries->addItem(entryForFrontend);
297     }
298     readDirectoryEntries();
299     return true;
300 }
301
302 class MetadataRequest FINAL : public RefCounted<MetadataRequest> {
303     WTF_MAKE_NONCOPYABLE(MetadataRequest);
304 public:
305     static PassRefPtr<MetadataRequest> create(PassRefPtr<RequestMetadataCallback> requestCallback, const String& url)
306     {
307         return adoptRef(new MetadataRequest(requestCallback, url));
308     }
309
310     ~MetadataRequest()
311     {
312         reportResult(FileError::ABORT_ERR);
313     }
314
315     void start(ExecutionContext*);
316
317 private:
318     bool didHitError(FileError* error)
319     {
320         reportResult(error->code());
321         return true;
322     }
323
324     bool didGetEntry(Entry*);
325     bool didGetMetadata(Metadata*);
326
327     void reportResult(FileError::ErrorCode errorCode, PassRefPtr<TypeBuilder::FileSystem::Metadata> metadata = 0)
328     {
329         m_requestCallback->sendSuccess(static_cast<int>(errorCode), metadata);
330     }
331
332     MetadataRequest(PassRefPtr<RequestMetadataCallback> requestCallback, const String& url)
333         : m_requestCallback(requestCallback)
334         , m_url(ParsedURLString, url) { }
335
336     RefPtr<RequestMetadataCallback> m_requestCallback;
337     KURL m_url;
338     bool m_isDirectory;
339 };
340
341 void MetadataRequest::start(ExecutionContext* executionContext)
342 {
343     ASSERT(executionContext);
344
345     OwnPtr<ErrorCallback> errorCallback = CallbackDispatcherFactory<ErrorCallback>::create(this, &MetadataRequest::didHitError);
346     OwnPtr<EntryCallback> successCallback = CallbackDispatcherFactory<EntryCallback>::create(this, &MetadataRequest::didGetEntry);
347     OwnPtr<AsyncFileSystemCallbacks> fileSystemCallbacks = ResolveURICallbacks::create(successCallback.release(), errorCallback.release(), executionContext);
348     LocalFileSystem::from(executionContext)->resolveURL(executionContext, m_url, fileSystemCallbacks.release());
349 }
350
351 bool MetadataRequest::didGetEntry(Entry* entry)
352 {
353     if (!entry->filesystem()->executionContext()) {
354         reportResult(FileError::ABORT_ERR);
355         return true;
356     }
357
358     OwnPtr<MetadataCallback> successCallback = CallbackDispatcherFactory<MetadataCallback>::create(this, &MetadataRequest::didGetMetadata);
359     OwnPtr<ErrorCallback> errorCallback = CallbackDispatcherFactory<ErrorCallback>::create(this, &MetadataRequest::didHitError);
360     entry->getMetadata(successCallback.release(), errorCallback.release());
361     m_isDirectory = entry->isDirectory();
362     return true;
363 }
364
365 bool MetadataRequest::didGetMetadata(Metadata* metadata)
366 {
367     using TypeBuilder::FileSystem::Metadata;
368     RefPtr<Metadata> result = Metadata::create()
369         .setModificationTime(metadata->modificationTime())
370         .setSize(metadata->size());
371     reportResult(static_cast<FileError::ErrorCode>(0), result);
372     return true;
373 }
374
375 class FileContentRequest FINAL : public EventListener {
376     WTF_MAKE_NONCOPYABLE(FileContentRequest);
377 public:
378     static PassRefPtr<FileContentRequest> create(PassRefPtr<RequestFileContentCallback> requestCallback, const String& url, bool readAsText, long long start, long long end, const String& charset)
379     {
380         return adoptRef(new FileContentRequest(requestCallback, url, readAsText, start, end, charset));
381     }
382
383     virtual ~FileContentRequest()
384     {
385         reportResult(FileError::ABORT_ERR);
386     }
387
388     void start(ExecutionContext*);
389
390     virtual bool operator==(const EventListener& other) OVERRIDE
391     {
392         return this == &other;
393     }
394
395     virtual void handleEvent(ExecutionContext*, Event* event) OVERRIDE
396     {
397         if (event->type() == EventTypeNames::load)
398             didRead();
399         else if (event->type() == EventTypeNames::error)
400             didHitError(m_reader->error().get());
401     }
402
403 private:
404     bool didHitError(FileError* error)
405     {
406         reportResult(error->code());
407         return true;
408     }
409
410     bool didGetEntry(Entry*);
411     bool didGetFile(File*);
412     void didRead();
413
414     void reportResult(FileError::ErrorCode errorCode, const String* result = 0, const String* charset = 0)
415     {
416         m_requestCallback->sendSuccess(static_cast<int>(errorCode), result, charset);
417     }
418
419     FileContentRequest(PassRefPtr<RequestFileContentCallback> requestCallback, const String& url, bool readAsText, long long start, long long end, const String& charset)
420         : EventListener(EventListener::CPPEventListenerType)
421         , m_requestCallback(requestCallback)
422         , m_url(ParsedURLString, url)
423         , m_readAsText(readAsText)
424         , m_start(start)
425         , m_end(end)
426         , m_charset(charset) { }
427
428     RefPtr<RequestFileContentCallback> m_requestCallback;
429     KURL m_url;
430     bool m_readAsText;
431     int m_start;
432     long long m_end;
433     String m_mimeType;
434     String m_charset;
435
436     RefPtr<FileReader> m_reader;
437 };
438
439 void FileContentRequest::start(ExecutionContext* executionContext)
440 {
441     ASSERT(executionContext);
442
443     OwnPtr<ErrorCallback> errorCallback = CallbackDispatcherFactory<ErrorCallback>::create(this, &FileContentRequest::didHitError);
444     OwnPtr<EntryCallback> successCallback = CallbackDispatcherFactory<EntryCallback>::create(this, &FileContentRequest::didGetEntry);
445
446     OwnPtr<AsyncFileSystemCallbacks> fileSystemCallbacks = ResolveURICallbacks::create(successCallback.release(), errorCallback.release(), executionContext);
447     LocalFileSystem::from(executionContext)->resolveURL(executionContext, m_url, fileSystemCallbacks.release());
448 }
449
450 bool FileContentRequest::didGetEntry(Entry* entry)
451 {
452     if (entry->isDirectory()) {
453         reportResult(FileError::TYPE_MISMATCH_ERR);
454         return true;
455     }
456
457     if (!entry->filesystem()->executionContext()) {
458         reportResult(FileError::ABORT_ERR);
459         return true;
460     }
461
462     OwnPtr<FileCallback> successCallback = CallbackDispatcherFactory<FileCallback>::create(this, &FileContentRequest::didGetFile);
463     OwnPtr<ErrorCallback> errorCallback = CallbackDispatcherFactory<ErrorCallback>::create(this, &FileContentRequest::didHitError);
464     toFileEntry(entry)->file(successCallback.release(), errorCallback.release());
465
466     m_reader = FileReader::create(entry->filesystem()->executionContext());
467     m_mimeType = MIMETypeRegistry::getMIMETypeForPath(entry->name());
468
469     return true;
470 }
471
472 bool FileContentRequest::didGetFile(File* file)
473 {
474     RefPtr<Blob> blob = file->slice(m_start, m_end);
475     m_reader->setOnload(this);
476     m_reader->setOnerror(this);
477
478     m_reader->readAsArrayBuffer(blob.get(), IGNORE_EXCEPTION);
479     return true;
480 }
481
482 void FileContentRequest::didRead()
483 {
484     RefPtr<ArrayBuffer> buffer = m_reader->arrayBufferResult();
485
486     if (!m_readAsText) {
487         String result = base64Encode(static_cast<char*>(buffer->data()), buffer->byteLength());
488         reportResult(static_cast<FileError::ErrorCode>(0), &result, 0);
489         return;
490     }
491
492     OwnPtr<TextResourceDecoder> decoder = TextResourceDecoder::create(m_mimeType, m_charset, true);
493     String result = decoder->decode(static_cast<char*>(buffer->data()), buffer->byteLength());
494     result = result + decoder->flush();
495     m_charset = decoder->encoding().name();
496     reportResult(static_cast<FileError::ErrorCode>(0), &result, &m_charset);
497 }
498
499 class DeleteEntryRequest FINAL : public RefCounted<DeleteEntryRequest> {
500 public:
501     static PassRefPtr<DeleteEntryRequest> create(PassRefPtr<DeleteEntryCallback> requestCallback, const KURL& url)
502     {
503         return adoptRef(new DeleteEntryRequest(requestCallback, url));
504     }
505
506     ~DeleteEntryRequest()
507     {
508         reportResult(FileError::ABORT_ERR);
509     }
510
511     void start(ExecutionContext*);
512
513 private:
514     // CallbackDispatcherFactory doesn't handle 0-arg handleEvent methods
515     class VoidCallbackImpl FINAL : public VoidCallback {
516     public:
517         explicit VoidCallbackImpl(PassRefPtr<DeleteEntryRequest> handler)
518             : m_handler(handler)
519         {
520         }
521
522         virtual void handleEvent() OVERRIDE
523         {
524             m_handler->didDeleteEntry();
525         }
526
527     private:
528         RefPtr<DeleteEntryRequest> m_handler;
529     };
530
531     bool didHitError(FileError* error)
532     {
533         reportResult(error->code());
534         return true;
535     }
536
537     bool didGetEntry(Entry*);
538     bool didDeleteEntry();
539
540     void reportResult(FileError::ErrorCode errorCode)
541     {
542         m_requestCallback->sendSuccess(static_cast<int>(errorCode));
543     }
544
545     DeleteEntryRequest(PassRefPtr<DeleteEntryCallback> requestCallback, const KURL& url)
546         : m_requestCallback(requestCallback)
547         , m_url(url) { }
548
549     RefPtr<DeleteEntryCallback> m_requestCallback;
550     KURL m_url;
551 };
552
553 void DeleteEntryRequest::start(ExecutionContext* executionContext)
554 {
555     ASSERT(executionContext);
556
557     OwnPtr<ErrorCallback> errorCallback = CallbackDispatcherFactory<ErrorCallback>::create(this, &DeleteEntryRequest::didHitError);
558
559     FileSystemType type;
560     String path;
561     if (!DOMFileSystemBase::crackFileSystemURL(m_url, type, path)) {
562         errorCallback->handleEvent(FileError::create(FileError::SYNTAX_ERR).get());
563         return;
564     }
565
566     if (path == "/") {
567         OwnPtr<VoidCallback> successCallback = adoptPtr(new VoidCallbackImpl(this));
568         OwnPtr<AsyncFileSystemCallbacks> fileSystemCallbacks = VoidCallbacks::create(successCallback.release(), errorCallback.release(), 0);
569         LocalFileSystem::from(executionContext)->deleteFileSystem(executionContext, type, fileSystemCallbacks.release());
570     } else {
571         OwnPtr<EntryCallback> successCallback = CallbackDispatcherFactory<EntryCallback>::create(this, &DeleteEntryRequest::didGetEntry);
572         OwnPtr<AsyncFileSystemCallbacks> fileSystemCallbacks = ResolveURICallbacks::create(successCallback.release(), errorCallback.release(), executionContext);
573         LocalFileSystem::from(executionContext)->resolveURL(executionContext, m_url, fileSystemCallbacks.release());
574     }
575 }
576
577 bool DeleteEntryRequest::didGetEntry(Entry* entry)
578 {
579     OwnPtr<VoidCallback> successCallback = adoptPtr(new VoidCallbackImpl(this));
580     OwnPtr<ErrorCallback> errorCallback = CallbackDispatcherFactory<ErrorCallback>::create(this, &DeleteEntryRequest::didHitError);
581     if (entry->isDirectory()) {
582         DirectoryEntry* directoryEntry = toDirectoryEntry(entry);
583         directoryEntry->removeRecursively(successCallback.release(), errorCallback.release());
584     } else {
585         entry->remove(successCallback.release(), errorCallback.release());
586     }
587     return true;
588 }
589
590 bool DeleteEntryRequest::didDeleteEntry()
591 {
592     reportResult(static_cast<FileError::ErrorCode>(0));
593     return true;
594 }
595
596 } // anonymous namespace
597
598 // static
599 PassOwnPtr<InspectorFileSystemAgent> InspectorFileSystemAgent::create(InspectorPageAgent* pageAgent)
600 {
601     return adoptPtr(new InspectorFileSystemAgent(pageAgent));
602 }
603
604 InspectorFileSystemAgent::~InspectorFileSystemAgent()
605 {
606 }
607
608 void InspectorFileSystemAgent::enable(ErrorString*)
609 {
610     if (m_enabled)
611         return;
612     m_enabled = true;
613     m_state->setBoolean(FileSystemAgentState::fileSystemAgentEnabled, m_enabled);
614 }
615
616 void InspectorFileSystemAgent::disable(ErrorString*)
617 {
618     if (!m_enabled)
619         return;
620     m_enabled = false;
621     m_state->setBoolean(FileSystemAgentState::fileSystemAgentEnabled, m_enabled);
622 }
623
624 void InspectorFileSystemAgent::requestFileSystemRoot(ErrorString* error, const String& origin, const String& type, PassRefPtr<RequestFileSystemRootCallback> requestCallback)
625 {
626     if (!assertEnabled(error))
627         return;
628
629     ExecutionContext* executionContext = assertExecutionContextForOrigin(error, SecurityOrigin::createFromString(origin).get());
630     if (!executionContext)
631         return;
632
633     FileSystemRootRequest::create(requestCallback, type)->start(executionContext);
634 }
635
636 void InspectorFileSystemAgent::requestDirectoryContent(ErrorString* error, const String& url, PassRefPtr<RequestDirectoryContentCallback> requestCallback)
637 {
638     if (!assertEnabled(error))
639         return;
640
641     ExecutionContext* executionContext = assertExecutionContextForOrigin(error, SecurityOrigin::createFromString(url).get());
642     if (!executionContext)
643         return;
644
645     DirectoryContentRequest::create(requestCallback, url)->start(executionContext);
646 }
647
648 void InspectorFileSystemAgent::requestMetadata(ErrorString* error, const String& url, PassRefPtr<RequestMetadataCallback> requestCallback)
649 {
650     if (!assertEnabled(error))
651         return;
652
653     ExecutionContext* executionContext = assertExecutionContextForOrigin(error, SecurityOrigin::createFromString(url).get());
654     if (!executionContext)
655         return;
656
657     MetadataRequest::create(requestCallback, url)->start(executionContext);
658 }
659
660 void InspectorFileSystemAgent::requestFileContent(ErrorString* error, const String& url, bool readAsText, const int* start, const int* end, const String* charset, PassRefPtr<RequestFileContentCallback> requestCallback)
661 {
662     if (!assertEnabled(error))
663         return;
664
665     ExecutionContext* executionContext = assertExecutionContextForOrigin(error, SecurityOrigin::createFromString(url).get());
666     if (!executionContext)
667         return;
668
669     long long startPosition = start ? *start : 0;
670     long long endPosition = end ? *end : std::numeric_limits<long long>::max();
671     FileContentRequest::create(requestCallback, url, readAsText, startPosition, endPosition, charset ? *charset : "")->start(executionContext);
672 }
673
674 void InspectorFileSystemAgent::deleteEntry(ErrorString* error, const String& urlString, PassRefPtr<DeleteEntryCallback> requestCallback)
675 {
676     if (!assertEnabled(error))
677         return;
678
679     KURL url(ParsedURLString, urlString);
680
681     ExecutionContext* executionContext = assertExecutionContextForOrigin(error, SecurityOrigin::create(url).get());
682     if (!executionContext)
683         return;
684
685     DeleteEntryRequest::create(requestCallback, url)->start(executionContext);
686 }
687
688 void InspectorFileSystemAgent::clearFrontend()
689 {
690     m_enabled = false;
691     m_state->setBoolean(FileSystemAgentState::fileSystemAgentEnabled, m_enabled);
692 }
693
694 void InspectorFileSystemAgent::restore()
695 {
696     m_enabled = m_state->getBoolean(FileSystemAgentState::fileSystemAgentEnabled);
697 }
698
699 InspectorFileSystemAgent::InspectorFileSystemAgent(InspectorPageAgent* pageAgent)
700     : InspectorBaseAgent<InspectorFileSystemAgent>("FileSystem")
701     , m_pageAgent(pageAgent)
702     , m_enabled(false)
703 {
704     ASSERT(m_pageAgent);
705 }
706
707 bool InspectorFileSystemAgent::assertEnabled(ErrorString* error)
708 {
709     if (!m_enabled) {
710         *error = "FileSystem agent is not enabled.";
711         return false;
712     }
713     return true;
714 }
715
716 ExecutionContext* InspectorFileSystemAgent::assertExecutionContextForOrigin(ErrorString* error, SecurityOrigin* origin)
717 {
718     for (Frame* frame = m_pageAgent->mainFrame(); frame; frame = frame->tree().traverseNext()) {
719         if (frame->document() && frame->document()->securityOrigin()->isSameSchemeHostPort(origin))
720             return frame->document();
721     }
722
723     *error = "No frame is available for the request";
724     return 0;
725 }
726
727 } // namespace WebCore