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