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 "modules/filesystem/InspectorFileSystemAgent.h" 33 34 #include "bindings/v8/ExceptionStatePlaceholder.h" 35 #include "core/dom/DOMImplementation.h" 36 #include "core/dom/Document.h" 37 #include "core/fileapi/File.h" 38 #include "core/fileapi/FileError.h" 39 #include "core/fileapi/FileReader.h" 40 #include "core/frame/LocalFrame.h" 41 #include "core/html/VoidCallback.h" 42 #include "core/html/parser/TextResourceDecoder.h" 43 #include "core/inspector/InspectorState.h" 44 #include "core/page/Page.h" 45 #include "modules/filesystem/DOMFileSystem.h" 46 #include "modules/filesystem/DirectoryEntry.h" 47 #include "modules/filesystem/DirectoryReader.h" 48 #include "modules/filesystem/EntriesCallback.h" 49 #include "modules/filesystem/Entry.h" 50 #include "modules/filesystem/EntryCallback.h" 51 #include "modules/filesystem/ErrorCallback.h" 52 #include "modules/filesystem/FileCallback.h" 53 #include "modules/filesystem/FileEntry.h" 54 #include "modules/filesystem/FileSystemCallbacks.h" 55 #include "modules/filesystem/LocalFileSystem.h" 56 #include "modules/filesystem/Metadata.h" 57 #include "modules/filesystem/MetadataCallback.h" 58 #include "platform/MIMETypeRegistry.h" 59 #include "platform/heap/Handle.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 = nullptr) 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 EntryHeapVector&); 205 206 void reportResult(FileError::ErrorCode errorCode, PassRefPtr<Array<TypeBuilder::FileSystem::Entry> > entries = nullptr) 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 Persistent<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 EntryHeapVector& 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 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 = nullptr) 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 RefPtrWillBePersistent<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 RefPtrWillBeRawPtr<Blob> blob = static_cast<Blob*>(file)->slice(m_start, m_end, IGNORE_EXCEPTION); 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(), executionContext, nullptr); 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(Page* page) 600 { 601 return adoptPtr(new InspectorFileSystemAgent(page)); 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(Page* page) 700 : InspectorBaseAgent<InspectorFileSystemAgent>("FileSystem") 701 , m_page(page) 702 , m_enabled(false) 703 { 704 ASSERT(m_page); 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_page->mainFrame(); frame; frame = frame->tree().traverseNext()) { 719 if (!frame->isLocalFrame()) 720 continue; 721 LocalFrame* localFrame = toLocalFrame(frame); 722 if (localFrame->document() && localFrame->document()->securityOrigin()->isSameSchemeHostPort(origin)) 723 return localFrame->document(); 724 } 725 726 *error = "No frame is available for the request"; 727 return 0; 728 } 729 730 } // namespace WebCore 731