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