InspectorFileSystemAgent.cpp 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743
  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. #include "config.h"
  31. #if ENABLE(INSPECTOR) && ENABLE(FILE_SYSTEM)
  32. #include "InspectorFileSystemAgent.h"
  33. #include "DOMFileSystem.h"
  34. #include "DOMImplementation.h"
  35. #include "DirectoryEntry.h"
  36. #include "DirectoryReader.h"
  37. #include "Document.h"
  38. #include "EntriesCallback.h"
  39. #include "EntryArray.h"
  40. #include "EntryCallback.h"
  41. #include "ErrorCallback.h"
  42. #include "Event.h"
  43. #include "File.h"
  44. #include "FileCallback.h"
  45. #include "FileEntry.h"
  46. #include "FileError.h"
  47. #include "FileReader.h"
  48. #include "FileSystemCallback.h"
  49. #include "FileSystemCallbacks.h"
  50. #include "Frame.h"
  51. #include "InspectorPageAgent.h"
  52. #include "InspectorState.h"
  53. #include "InstrumentingAgents.h"
  54. #include "KURL.h"
  55. #include "LocalFileSystem.h"
  56. #include "MIMETypeRegistry.h"
  57. #include "Metadata.h"
  58. #include "MetadataCallback.h"
  59. #include "ScriptExecutionContext.h"
  60. #include "SecurityOrigin.h"
  61. #include "TextEncoding.h"
  62. #include "TextResourceDecoder.h"
  63. #include "VoidCallback.h"
  64. #include <wtf/text/Base64.h>
  65. using WebCore::TypeBuilder::Array;
  66. typedef WebCore::InspectorBackendDispatcher::FileSystemCommandHandler::RequestFileSystemRootCallback RequestFileSystemRootCallback;
  67. typedef WebCore::InspectorBackendDispatcher::FileSystemCommandHandler::RequestDirectoryContentCallback RequestDirectoryContentCallback;
  68. typedef WebCore::InspectorBackendDispatcher::FileSystemCommandHandler::RequestMetadataCallback RequestMetadataCallback;
  69. typedef WebCore::InspectorBackendDispatcher::FileSystemCommandHandler::RequestFileContentCallback RequestFileContentCallback;
  70. typedef WebCore::InspectorBackendDispatcher::FileSystemCommandHandler::DeleteEntryCallback DeleteEntryCallback;
  71. namespace WebCore {
  72. namespace FileSystemAgentState {
  73. static const char fileSystemAgentEnabled[] = "fileSystemAgentEnabled";
  74. }
  75. namespace {
  76. template<typename BaseCallback, typename Handler, typename Argument>
  77. class CallbackDispatcher : public BaseCallback {
  78. public:
  79. typedef bool (Handler::*HandlingMethod)(Argument*);
  80. static PassRefPtr<CallbackDispatcher> create(PassRefPtr<Handler> handler, HandlingMethod handlingMethod)
  81. {
  82. return adoptRef(new CallbackDispatcher(handler, handlingMethod));
  83. }
  84. virtual bool handleEvent(Argument* argument) OVERRIDE
  85. {
  86. return (m_handler.get()->*m_handlingMethod)(argument);
  87. }
  88. private:
  89. CallbackDispatcher(PassRefPtr<Handler> handler, HandlingMethod handlingMethod)
  90. : m_handler(handler)
  91. , m_handlingMethod(handlingMethod) { }
  92. RefPtr<Handler> m_handler;
  93. HandlingMethod m_handlingMethod;
  94. };
  95. template<typename BaseCallback>
  96. class CallbackDispatcherFactory {
  97. public:
  98. template<typename Handler, typename Argument>
  99. static PassRefPtr<CallbackDispatcher<BaseCallback, Handler, Argument> > create(Handler* handler, bool (Handler::*handlingMethod)(Argument*))
  100. {
  101. return CallbackDispatcher<BaseCallback, Handler, Argument>::create(PassRefPtr<Handler>(handler), handlingMethod);
  102. }
  103. };
  104. class FileSystemRootRequest : public RefCounted<FileSystemRootRequest> {
  105. WTF_MAKE_NONCOPYABLE(FileSystemRootRequest);
  106. public:
  107. static PassRefPtr<FileSystemRootRequest> create(PassRefPtr<RequestFileSystemRootCallback> requestCallback, const String& type)
  108. {
  109. return adoptRef(new FileSystemRootRequest(requestCallback, type));
  110. }
  111. void start(ScriptExecutionContext*);
  112. private:
  113. bool didHitError(FileError* error)
  114. {
  115. reportResult(error->code());
  116. return true;
  117. }
  118. bool didGetEntry(Entry*);
  119. void reportResult(FileError::ErrorCode errorCode, PassRefPtr<TypeBuilder::FileSystem::Entry> entry = 0)
  120. {
  121. m_requestCallback->sendSuccess(static_cast<int>(errorCode), entry);
  122. }
  123. FileSystemRootRequest(PassRefPtr<RequestFileSystemRootCallback> requestCallback, const String& type)
  124. : m_requestCallback(requestCallback)
  125. , m_type(type) { }
  126. RefPtr<RequestFileSystemRootCallback> m_requestCallback;
  127. String m_type;
  128. };
  129. void FileSystemRootRequest::start(ScriptExecutionContext* scriptExecutionContext)
  130. {
  131. ASSERT(scriptExecutionContext);
  132. RefPtr<ErrorCallback> errorCallback = CallbackDispatcherFactory<ErrorCallback>::create(this, &FileSystemRootRequest::didHitError);
  133. FileSystemType type;
  134. if (m_type == DOMFileSystemBase::persistentPathPrefix)
  135. type = FileSystemTypePersistent;
  136. else if (m_type == DOMFileSystemBase::temporaryPathPrefix)
  137. type = FileSystemTypeTemporary;
  138. else {
  139. errorCallback->handleEvent(FileError::create(FileError::SYNTAX_ERR).get());
  140. return;
  141. }
  142. RefPtr<EntryCallback> successCallback = CallbackDispatcherFactory<EntryCallback>::create(this, &FileSystemRootRequest::didGetEntry);
  143. OwnPtr<ResolveURICallbacks> fileSystemCallbacks = ResolveURICallbacks::create(successCallback, errorCallback, scriptExecutionContext, type, "/");
  144. LocalFileSystem::localFileSystem().readFileSystem(scriptExecutionContext, type, fileSystemCallbacks.release());
  145. }
  146. bool FileSystemRootRequest::didGetEntry(Entry* entry)
  147. {
  148. RefPtr<TypeBuilder::FileSystem::Entry> result = TypeBuilder::FileSystem::Entry::create()
  149. .setUrl(entry->toURL())
  150. .setName("/")
  151. .setIsDirectory(true);
  152. reportResult(static_cast<FileError::ErrorCode>(0), result);
  153. return true;
  154. }
  155. class DirectoryContentRequest : public RefCounted<DirectoryContentRequest> {
  156. WTF_MAKE_NONCOPYABLE(DirectoryContentRequest);
  157. public:
  158. static PassRefPtr<DirectoryContentRequest> create(PassRefPtr<RequestDirectoryContentCallback> requestCallback, const String& url)
  159. {
  160. return adoptRef(new DirectoryContentRequest(requestCallback, url));
  161. }
  162. virtual ~DirectoryContentRequest()
  163. {
  164. reportResult(FileError::ABORT_ERR);
  165. }
  166. void start(ScriptExecutionContext*);
  167. private:
  168. bool didHitError(FileError* error)
  169. {
  170. reportResult(error->code());
  171. return true;
  172. }
  173. bool didGetEntry(Entry*);
  174. bool didReadDirectoryEntries(EntryArray*);
  175. void reportResult(FileError::ErrorCode errorCode, PassRefPtr<Array<TypeBuilder::FileSystem::Entry> > entries = 0)
  176. {
  177. m_requestCallback->sendSuccess(static_cast<int>(errorCode), entries);
  178. }
  179. DirectoryContentRequest(PassRefPtr<RequestDirectoryContentCallback> requestCallback, const String& url)
  180. : m_requestCallback(requestCallback)
  181. , m_url(ParsedURLString, url) { }
  182. void readDirectoryEntries();
  183. RefPtr<RequestDirectoryContentCallback> m_requestCallback;
  184. KURL m_url;
  185. RefPtr<Array<TypeBuilder::FileSystem::Entry> > m_entries;
  186. RefPtr<DirectoryReader> m_directoryReader;
  187. };
  188. void DirectoryContentRequest::start(ScriptExecutionContext* scriptExecutionContext)
  189. {
  190. ASSERT(scriptExecutionContext);
  191. RefPtr<ErrorCallback> errorCallback = CallbackDispatcherFactory<ErrorCallback>::create(this, &DirectoryContentRequest::didHitError);
  192. FileSystemType type;
  193. String path;
  194. if (!DOMFileSystemBase::crackFileSystemURL(m_url, type, path)) {
  195. errorCallback->handleEvent(FileError::create(FileError::SYNTAX_ERR).get());
  196. return;
  197. }
  198. RefPtr<EntryCallback> successCallback = CallbackDispatcherFactory<EntryCallback>::create(this, &DirectoryContentRequest::didGetEntry);
  199. OwnPtr<ResolveURICallbacks> fileSystemCallbacks = ResolveURICallbacks::create(successCallback, errorCallback, scriptExecutionContext, type, path);
  200. LocalFileSystem::localFileSystem().readFileSystem(scriptExecutionContext, type, fileSystemCallbacks.release());
  201. }
  202. bool DirectoryContentRequest::didGetEntry(Entry* entry)
  203. {
  204. if (!entry->isDirectory()) {
  205. reportResult(FileError::TYPE_MISMATCH_ERR);
  206. return true;
  207. }
  208. m_directoryReader = static_cast<DirectoryEntry*>(entry)->createReader();
  209. m_entries = Array<TypeBuilder::FileSystem::Entry>::create();
  210. readDirectoryEntries();
  211. return true;
  212. }
  213. void DirectoryContentRequest::readDirectoryEntries()
  214. {
  215. if (!m_directoryReader->filesystem()->scriptExecutionContext()) {
  216. reportResult(FileError::ABORT_ERR);
  217. return;
  218. }
  219. RefPtr<EntriesCallback> successCallback = CallbackDispatcherFactory<EntriesCallback>::create(this, &DirectoryContentRequest::didReadDirectoryEntries);
  220. RefPtr<ErrorCallback> errorCallback = CallbackDispatcherFactory<ErrorCallback>::create(this, &DirectoryContentRequest::didHitError);
  221. m_directoryReader->readEntries(successCallback, errorCallback);
  222. }
  223. bool DirectoryContentRequest::didReadDirectoryEntries(EntryArray* entries)
  224. {
  225. if (!entries->length()) {
  226. reportResult(static_cast<FileError::ErrorCode>(0), m_entries);
  227. return true;
  228. }
  229. for (unsigned i = 0; i < entries->length(); ++i) {
  230. Entry* entry = entries->item(i);
  231. RefPtr<TypeBuilder::FileSystem::Entry> entryForFrontend = TypeBuilder::FileSystem::Entry::create()
  232. .setUrl(entry->toURL())
  233. .setName(entry->name())
  234. .setIsDirectory(entry->isDirectory());
  235. using TypeBuilder::Page::ResourceType;
  236. if (!entry->isDirectory()) {
  237. String mimeType = MIMETypeRegistry::getMIMETypeForPath(entry->name());
  238. ResourceType::Enum resourceType;
  239. if (MIMETypeRegistry::isSupportedImageMIMEType(mimeType)) {
  240. resourceType = ResourceType::Image;
  241. entryForFrontend->setIsTextFile(false);
  242. } else if (MIMETypeRegistry::isSupportedJavaScriptMIMEType(mimeType)) {
  243. resourceType = ResourceType::Script;
  244. entryForFrontend->setIsTextFile(true);
  245. } else if (MIMETypeRegistry::isSupportedNonImageMIMEType(mimeType)) {
  246. resourceType = ResourceType::Document;
  247. entryForFrontend->setIsTextFile(true);
  248. } else {
  249. resourceType = ResourceType::Other;
  250. entryForFrontend->setIsTextFile(DOMImplementation::isXMLMIMEType(mimeType) || DOMImplementation::isTextMIMEType(mimeType));
  251. }
  252. entryForFrontend->setMimeType(mimeType);
  253. entryForFrontend->setResourceType(resourceType);
  254. }
  255. m_entries->addItem(entryForFrontend);
  256. }
  257. readDirectoryEntries();
  258. return true;
  259. }
  260. class MetadataRequest : public RefCounted<MetadataRequest> {
  261. WTF_MAKE_NONCOPYABLE(MetadataRequest);
  262. public:
  263. static PassRefPtr<MetadataRequest> create(PassRefPtr<RequestMetadataCallback> requestCallback, const String& url)
  264. {
  265. return adoptRef(new MetadataRequest(requestCallback, url));
  266. }
  267. virtual ~MetadataRequest()
  268. {
  269. reportResult(FileError::ABORT_ERR);
  270. }
  271. void start(ScriptExecutionContext*);
  272. private:
  273. bool didHitError(FileError* error)
  274. {
  275. reportResult(error->code());
  276. return true;
  277. }
  278. bool didGetEntry(Entry*);
  279. bool didGetMetadata(Metadata*);
  280. void reportResult(FileError::ErrorCode errorCode, PassRefPtr<TypeBuilder::FileSystem::Metadata> metadata = 0)
  281. {
  282. m_requestCallback->sendSuccess(static_cast<int>(errorCode), metadata);
  283. }
  284. MetadataRequest(PassRefPtr<RequestMetadataCallback> requestCallback, const String& url)
  285. : m_requestCallback(requestCallback)
  286. , m_url(ParsedURLString, url) { }
  287. RefPtr<RequestMetadataCallback> m_requestCallback;
  288. KURL m_url;
  289. String m_path;
  290. bool m_isDirectory;
  291. };
  292. void MetadataRequest::start(ScriptExecutionContext* scriptExecutionContext)
  293. {
  294. ASSERT(scriptExecutionContext);
  295. RefPtr<ErrorCallback> errorCallback = CallbackDispatcherFactory<ErrorCallback>::create(this, &MetadataRequest::didHitError);
  296. FileSystemType type;
  297. if (!DOMFileSystemBase::crackFileSystemURL(m_url, type, m_path)) {
  298. errorCallback->handleEvent(FileError::create(FileError::SYNTAX_ERR).get());
  299. return;
  300. }
  301. RefPtr<EntryCallback> successCallback = CallbackDispatcherFactory<EntryCallback>::create(this, &MetadataRequest::didGetEntry);
  302. OwnPtr<ResolveURICallbacks> fileSystemCallbacks = ResolveURICallbacks::create(successCallback, errorCallback, scriptExecutionContext, type, m_path);
  303. LocalFileSystem::localFileSystem().readFileSystem(scriptExecutionContext, type, fileSystemCallbacks.release());
  304. }
  305. bool MetadataRequest::didGetEntry(Entry* entry)
  306. {
  307. if (!entry->filesystem()->scriptExecutionContext()) {
  308. reportResult(FileError::ABORT_ERR);
  309. return true;
  310. }
  311. RefPtr<MetadataCallback> successCallback = CallbackDispatcherFactory<MetadataCallback>::create(this, &MetadataRequest::didGetMetadata);
  312. RefPtr<ErrorCallback> errorCallback = CallbackDispatcherFactory<ErrorCallback>::create(this, &MetadataRequest::didHitError);
  313. entry->getMetadata(successCallback, errorCallback);
  314. m_isDirectory = entry->isDirectory();
  315. return true;
  316. }
  317. bool MetadataRequest::didGetMetadata(Metadata* metadata)
  318. {
  319. using TypeBuilder::FileSystem::Metadata;
  320. RefPtr<Metadata> result = Metadata::create()
  321. .setModificationTime(metadata->modificationTime())
  322. .setSize(metadata->size());
  323. reportResult(static_cast<FileError::ErrorCode>(0), result);
  324. return true;
  325. }
  326. class FileContentRequest : public EventListener {
  327. WTF_MAKE_NONCOPYABLE(FileContentRequest);
  328. public:
  329. static PassRefPtr<FileContentRequest> create(PassRefPtr<RequestFileContentCallback> requestCallback, const String& url, bool readAsText, long long start, long long end, const String& charset)
  330. {
  331. return adoptRef(new FileContentRequest(requestCallback, url, readAsText, start, end, charset));
  332. }
  333. virtual ~FileContentRequest()
  334. {
  335. reportResult(FileError::ABORT_ERR);
  336. }
  337. void start(ScriptExecutionContext*);
  338. virtual bool operator==(const EventListener& other) OVERRIDE
  339. {
  340. return this == &other;
  341. }
  342. virtual void handleEvent(ScriptExecutionContext*, Event* event) OVERRIDE
  343. {
  344. if (event->type() == eventNames().loadEvent)
  345. didRead();
  346. else if (event->type() == eventNames().errorEvent)
  347. didHitError(m_reader->error().get());
  348. }
  349. private:
  350. bool didHitError(FileError* error)
  351. {
  352. reportResult(error->code());
  353. return true;
  354. }
  355. bool didGetEntry(Entry*);
  356. bool didGetFile(File*);
  357. void didRead();
  358. void reportResult(FileError::ErrorCode errorCode, const String* result = 0, const String* charset = 0)
  359. {
  360. m_requestCallback->sendSuccess(static_cast<int>(errorCode), result, charset);
  361. }
  362. FileContentRequest(PassRefPtr<RequestFileContentCallback> requestCallback, const String& url, bool readAsText, long long start, long long end, const String& charset)
  363. : EventListener(EventListener::CPPEventListenerType)
  364. , m_requestCallback(requestCallback)
  365. , m_url(ParsedURLString, url)
  366. , m_readAsText(readAsText)
  367. , m_start(start)
  368. , m_end(end)
  369. , m_charset(charset) { }
  370. RefPtr<RequestFileContentCallback> m_requestCallback;
  371. KURL m_url;
  372. bool m_readAsText;
  373. int m_start;
  374. long long m_end;
  375. String m_mimeType;
  376. String m_charset;
  377. RefPtr<FileReader> m_reader;
  378. };
  379. void FileContentRequest::start(ScriptExecutionContext* scriptExecutionContext)
  380. {
  381. ASSERT(scriptExecutionContext);
  382. RefPtr<ErrorCallback> errorCallback = CallbackDispatcherFactory<ErrorCallback>::create(this, &FileContentRequest::didHitError);
  383. FileSystemType type;
  384. String path;
  385. if (!DOMFileSystemBase::crackFileSystemURL(m_url, type, path)) {
  386. errorCallback->handleEvent(FileError::create(FileError::SYNTAX_ERR).get());
  387. return;
  388. }
  389. RefPtr<EntryCallback> successCallback = CallbackDispatcherFactory<EntryCallback>::create(this, &FileContentRequest::didGetEntry);
  390. OwnPtr<ResolveURICallbacks> fileSystemCallbacks = ResolveURICallbacks::create(successCallback, errorCallback, scriptExecutionContext, type, path);
  391. LocalFileSystem::localFileSystem().readFileSystem(scriptExecutionContext, type, fileSystemCallbacks.release());
  392. }
  393. bool FileContentRequest::didGetEntry(Entry* entry)
  394. {
  395. if (entry->isDirectory()) {
  396. reportResult(FileError::TYPE_MISMATCH_ERR);
  397. return true;
  398. }
  399. if (!entry->filesystem()->scriptExecutionContext()) {
  400. reportResult(FileError::ABORT_ERR);
  401. return true;
  402. }
  403. RefPtr<FileCallback> successCallback = CallbackDispatcherFactory<FileCallback>::create(this, &FileContentRequest::didGetFile);
  404. RefPtr<ErrorCallback> errorCallback = CallbackDispatcherFactory<ErrorCallback>::create(this, &FileContentRequest::didHitError);
  405. static_cast<FileEntry*>(entry)->file(successCallback, errorCallback);
  406. m_reader = FileReader::create(entry->filesystem()->scriptExecutionContext());
  407. m_mimeType = MIMETypeRegistry::getMIMETypeForPath(entry->name());
  408. return true;
  409. }
  410. bool FileContentRequest::didGetFile(File* file)
  411. {
  412. RefPtr<Blob> blob = file->slice(m_start, m_end);
  413. m_reader->setOnload(this);
  414. m_reader->setOnerror(this);
  415. m_reader->readAsArrayBuffer(blob.get(), IGNORE_EXCEPTION);
  416. return true;
  417. }
  418. void FileContentRequest::didRead()
  419. {
  420. RefPtr<ArrayBuffer> buffer = m_reader->arrayBufferResult();
  421. if (!m_readAsText) {
  422. String result = base64Encode(static_cast<char*>(buffer->data()), buffer->byteLength());
  423. reportResult(static_cast<FileError::ErrorCode>(0), &result, 0);
  424. return;
  425. }
  426. RefPtr<TextResourceDecoder> decoder = TextResourceDecoder::create(m_mimeType, m_charset, true);
  427. String result = decoder->decode(static_cast<char*>(buffer->data()), buffer->byteLength());
  428. result.append(decoder->flush());
  429. m_charset = decoder->encoding().domName();
  430. reportResult(static_cast<FileError::ErrorCode>(0), &result, &m_charset);
  431. }
  432. class DeleteEntryRequest : public VoidCallback {
  433. public:
  434. static PassRefPtr<DeleteEntryRequest> create(PassRefPtr<DeleteEntryCallback> requestCallback, const KURL& url)
  435. {
  436. return adoptRef(new DeleteEntryRequest(requestCallback, url));
  437. }
  438. virtual ~DeleteEntryRequest()
  439. {
  440. reportResult(FileError::ABORT_ERR);
  441. }
  442. virtual bool handleEvent() OVERRIDE
  443. {
  444. return didDeleteEntry();
  445. }
  446. void start(ScriptExecutionContext*);
  447. private:
  448. bool didHitError(FileError* error)
  449. {
  450. reportResult(error->code());
  451. return true;
  452. }
  453. bool didGetEntry(Entry*);
  454. bool didDeleteEntry();
  455. void reportResult(FileError::ErrorCode errorCode)
  456. {
  457. m_requestCallback->sendSuccess(static_cast<int>(errorCode));
  458. }
  459. DeleteEntryRequest(PassRefPtr<DeleteEntryCallback> requestCallback, const KURL& url)
  460. : m_requestCallback(requestCallback)
  461. , m_url(url) { }
  462. RefPtr<DeleteEntryCallback> m_requestCallback;
  463. KURL m_url;
  464. };
  465. void DeleteEntryRequest::start(ScriptExecutionContext* scriptExecutionContext)
  466. {
  467. ASSERT(scriptExecutionContext);
  468. RefPtr<ErrorCallback> errorCallback = CallbackDispatcherFactory<ErrorCallback>::create(this, &DeleteEntryRequest::didHitError);
  469. FileSystemType type;
  470. String path;
  471. if (!DOMFileSystemBase::crackFileSystemURL(m_url, type, path)) {
  472. errorCallback->handleEvent(FileError::create(FileError::SYNTAX_ERR).get());
  473. return;
  474. }
  475. if (path == "/") {
  476. OwnPtr<AsyncFileSystemCallbacks> fileSystemCallbacks = VoidCallbacks::create(this, errorCallback);
  477. LocalFileSystem::localFileSystem().deleteFileSystem(scriptExecutionContext, type, fileSystemCallbacks.release());
  478. } else {
  479. RefPtr<EntryCallback> successCallback = CallbackDispatcherFactory<EntryCallback>::create(this, &DeleteEntryRequest::didGetEntry);
  480. OwnPtr<ResolveURICallbacks> fileSystemCallbacks = ResolveURICallbacks::create(successCallback, errorCallback, scriptExecutionContext, type, path);
  481. LocalFileSystem::localFileSystem().readFileSystem(scriptExecutionContext, type, fileSystemCallbacks.release());
  482. }
  483. }
  484. bool DeleteEntryRequest::didGetEntry(Entry* entry)
  485. {
  486. RefPtr<ErrorCallback> errorCallback = CallbackDispatcherFactory<ErrorCallback>::create(this, &DeleteEntryRequest::didHitError);
  487. if (entry->isDirectory()) {
  488. DirectoryEntry* directoryEntry = static_cast<DirectoryEntry*>(entry);
  489. directoryEntry->removeRecursively(this, errorCallback);
  490. } else
  491. entry->remove(this, errorCallback);
  492. return true;
  493. }
  494. bool DeleteEntryRequest::didDeleteEntry()
  495. {
  496. reportResult(static_cast<FileError::ErrorCode>(0));
  497. return true;
  498. }
  499. } // anonymous namespace
  500. // static
  501. PassOwnPtr<InspectorFileSystemAgent> InspectorFileSystemAgent::create(InstrumentingAgents* instrumentingAgents, InspectorPageAgent* pageAgent, InspectorCompositeState* state)
  502. {
  503. return adoptPtr(new InspectorFileSystemAgent(instrumentingAgents, pageAgent, state));
  504. }
  505. InspectorFileSystemAgent::~InspectorFileSystemAgent()
  506. {
  507. m_instrumentingAgents->setInspectorFileSystemAgent(0);
  508. }
  509. void InspectorFileSystemAgent::enable(ErrorString*)
  510. {
  511. if (m_enabled)
  512. return;
  513. m_enabled = true;
  514. m_state->setBoolean(FileSystemAgentState::fileSystemAgentEnabled, m_enabled);
  515. }
  516. void InspectorFileSystemAgent::disable(ErrorString*)
  517. {
  518. if (!m_enabled)
  519. return;
  520. m_enabled = false;
  521. m_state->setBoolean(FileSystemAgentState::fileSystemAgentEnabled, m_enabled);
  522. }
  523. void InspectorFileSystemAgent::requestFileSystemRoot(ErrorString* error, const String& origin, const String& type, PassRefPtr<RequestFileSystemRootCallback> requestCallback)
  524. {
  525. if (!assertEnabled(error))
  526. return;
  527. ScriptExecutionContext* scriptExecutionContext = assertScriptExecutionContextForOrigin(error, SecurityOrigin::createFromString(origin).get());
  528. if (!scriptExecutionContext)
  529. return;
  530. FileSystemRootRequest::create(requestCallback, type)->start(scriptExecutionContext);
  531. }
  532. void InspectorFileSystemAgent::requestDirectoryContent(ErrorString* error, const String& url, PassRefPtr<RequestDirectoryContentCallback> requestCallback)
  533. {
  534. if (!assertEnabled(error))
  535. return;
  536. ScriptExecutionContext* scriptExecutionContext = assertScriptExecutionContextForOrigin(error, SecurityOrigin::createFromString(url).get());
  537. if (!scriptExecutionContext)
  538. return;
  539. DirectoryContentRequest::create(requestCallback, url)->start(scriptExecutionContext);
  540. }
  541. void InspectorFileSystemAgent::requestMetadata(ErrorString* error, const String& url, PassRefPtr<RequestMetadataCallback> requestCallback)
  542. {
  543. if (!assertEnabled(error))
  544. return;
  545. ScriptExecutionContext* scriptExecutionContext = assertScriptExecutionContextForOrigin(error, SecurityOrigin::createFromString(url).get());
  546. if (!scriptExecutionContext)
  547. return;
  548. MetadataRequest::create(requestCallback, url)->start(scriptExecutionContext);
  549. }
  550. void InspectorFileSystemAgent::requestFileContent(ErrorString* error, const String& url, bool readAsText, const int* start, const int* end, const String* charset, PassRefPtr<RequestFileContentCallback> requestCallback)
  551. {
  552. if (!assertEnabled(error))
  553. return;
  554. ScriptExecutionContext* scriptExecutionContext = assertScriptExecutionContextForOrigin(error, SecurityOrigin::createFromString(url).get());
  555. if (!scriptExecutionContext)
  556. return;
  557. long long startPosition = start ? *start : 0;
  558. long long endPosition = end ? *end : std::numeric_limits<long long>::max();
  559. FileContentRequest::create(requestCallback, url, readAsText, startPosition, endPosition, charset ? *charset : "")->start(scriptExecutionContext);
  560. }
  561. void InspectorFileSystemAgent::deleteEntry(ErrorString* error, const String& urlString, PassRefPtr<DeleteEntryCallback> requestCallback)
  562. {
  563. if (!assertEnabled(error))
  564. return;
  565. KURL url(ParsedURLString, urlString);
  566. ScriptExecutionContext* scriptExecutionContext = assertScriptExecutionContextForOrigin(error, SecurityOrigin::create(url).get());
  567. if (!scriptExecutionContext)
  568. return;
  569. DeleteEntryRequest::create(requestCallback, url)->start(scriptExecutionContext);
  570. }
  571. void InspectorFileSystemAgent::clearFrontend()
  572. {
  573. m_enabled = false;
  574. m_state->setBoolean(FileSystemAgentState::fileSystemAgentEnabled, m_enabled);
  575. }
  576. void InspectorFileSystemAgent::restore()
  577. {
  578. m_enabled = m_state->getBoolean(FileSystemAgentState::fileSystemAgentEnabled);
  579. }
  580. InspectorFileSystemAgent::InspectorFileSystemAgent(InstrumentingAgents* instrumentingAgents, InspectorPageAgent* pageAgent, InspectorCompositeState* state)
  581. : InspectorBaseAgent<InspectorFileSystemAgent>("FileSystem", instrumentingAgents, state)
  582. , m_pageAgent(pageAgent)
  583. , m_enabled(false)
  584. {
  585. ASSERT(instrumentingAgents);
  586. ASSERT(state);
  587. ASSERT(m_pageAgent);
  588. m_instrumentingAgents->setInspectorFileSystemAgent(this);
  589. }
  590. bool InspectorFileSystemAgent::assertEnabled(ErrorString* error)
  591. {
  592. if (!m_enabled) {
  593. *error = "FileSystem agent is not enabled.";
  594. return false;
  595. }
  596. return true;
  597. }
  598. ScriptExecutionContext* InspectorFileSystemAgent::assertScriptExecutionContextForOrigin(ErrorString* error, SecurityOrigin* origin)
  599. {
  600. for (Frame* frame = m_pageAgent->mainFrame(); frame; frame = frame->tree()->traverseNext()) {
  601. if (frame->document() && frame->document()->securityOrigin()->isSameSchemeHostPort(origin))
  602. return frame->document();
  603. }
  604. *error = "No frame is available for the request";
  605. return 0;
  606. }
  607. } // namespace WebCore
  608. #endif // ENABLE(INSPECTOR) && ENABLE(FILE_SYSTEM)