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