https://bugs.webkit.org/show_bug.cgi?id=89642
Patch by Taiju Tsuiki <tzik@chromium.org> on 2012-07-02
Reviewed by Vsevolod Vlasov.
Source/WebCore:
Test: http/tests/inspector/filesystem/read-file.html
* inspector/Inspector.json:
* inspector/InspectorFileSystemAgent.cpp:
(WebCore):
(WebCore::InspectorFileSystemAgent::requestFileContent):
* inspector/InspectorFileSystemAgent.h:
(InspectorFileSystemAgent):
* inspector/front-end/FileSystemModel.js:
(WebInspector.FileSystemModel.prototype.requestMetadata):
(WebInspector.FileSystemModel.prototype.requestFileContent):
(WebInspector.FileSystemModel.File.prototype.get resourceType):
(WebInspector.FileSystemModel.File.prototype.requestFileContent):
(WebInspector.FileSystemRequestManager):
(WebInspector.FileSystemRequestManager.prototype._metadataReceived):
(WebInspector.FileSystemRequestManager.prototype.requestFileContent.requestAccepted):
(WebInspector.FileSystemRequestManager.prototype.requestFileContent):
(WebInspector.FileSystemRequestManager.prototype._fileContentReceived):
(WebInspector.FileSystemDispatcher.prototype.metadataReceived):
(WebInspector.FileSystemDispatcher.prototype.fileContentReceived):
LayoutTests:
* http/tests/inspector/filesystem/read-file-expected.txt: Added.
* http/tests/inspector/filesystem/read-file.html: Added.
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@121676
268f45cc-cd09-0410-ab3c-
d52691b4dbfc
2012-07-02 Taiju Tsuiki <tzik@chromium.org>
+ Web Inspector: Add requestFileContent command and fileContentReceived event
+ https://bugs.webkit.org/show_bug.cgi?id=89642
+
+ Reviewed by Vsevolod Vlasov.
+
+ * http/tests/inspector/filesystem/read-file-expected.txt: Added.
+ * http/tests/inspector/filesystem/read-file.html: Added.
+
+2012-07-02 Taiju Tsuiki <tzik@chromium.org>
+
Web Inspector: Add refresh button to FileSystemView status bar
https://bugs.webkit.org/show_bug.cgi?id=90244
--- /dev/null
+Tests readFile.
+
+errorCode = 0
+content = "UEFTUw==" [PASS]
+
--- /dev/null
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="UTF-8">
+<script src="../inspector-test.js"></script>
+<script src="filesystem-test.js"></script>
+<script>
+document.addEventListener("DOMContentLoaded", runTest);
+function test()
+{
+ var requestManager = new WebInspector.FileSystemRequestManager();
+ InspectorTest.clearFileSystem(step1);
+
+ function step1()
+ {
+ InspectorTest.createDirectory("/hoge", step2);
+ }
+
+ function step2()
+ {
+ InspectorTest.writeFile("/hoge/fuga", "piPASSyo", step3);
+ }
+
+ function step3()
+ {
+ requestManager.requestFileContent("filesystem:http://127.0.0.1:8000/temporary/hoge/fuga", 2, 6, step4);
+ }
+
+ function step4(errorCode, content)
+ {
+ InspectorTest.addResult("errorCode = " + errorCode);
+ if (content)
+ InspectorTest.addResult("content = \"" + content + "\" [" + atob(content) + "]");
+ else
+ InspectorTest.addResult("content = (null)");
+
+ InspectorTest.clearFileSystem(step5);
+ }
+
+ function step5()
+ {
+ InspectorTest.completeTest();
+ }
+}
+</script>
+</head>
+<body>
+<p>Tests readFile.</p>
+</body>
+</html>
2012-07-02 Taiju Tsuiki <tzik@chromium.org>
+ Web Inspector: Add requestFileContent command and fileContentReceived event
+ https://bugs.webkit.org/show_bug.cgi?id=89642
+
+ Reviewed by Vsevolod Vlasov.
+
+ Test: http/tests/inspector/filesystem/read-file.html
+
+ * inspector/Inspector.json:
+ * inspector/InspectorFileSystemAgent.cpp:
+ (WebCore):
+ (WebCore::InspectorFileSystemAgent::requestFileContent):
+ * inspector/InspectorFileSystemAgent.h:
+ (InspectorFileSystemAgent):
+ * inspector/front-end/FileSystemModel.js:
+ (WebInspector.FileSystemModel.prototype.requestMetadata):
+ (WebInspector.FileSystemModel.prototype.requestFileContent):
+ (WebInspector.FileSystemModel.File.prototype.get resourceType):
+ (WebInspector.FileSystemModel.File.prototype.requestFileContent):
+ (WebInspector.FileSystemRequestManager):
+ (WebInspector.FileSystemRequestManager.prototype._metadataReceived):
+ (WebInspector.FileSystemRequestManager.prototype.requestFileContent.requestAccepted):
+ (WebInspector.FileSystemRequestManager.prototype.requestFileContent):
+ (WebInspector.FileSystemRequestManager.prototype._fileContentReceived):
+ (WebInspector.FileSystemDispatcher.prototype.metadataReceived):
+ (WebInspector.FileSystemDispatcher.prototype.fileContentReceived):
+
+2012-07-02 Taiju Tsuiki <tzik@chromium.org>
+
Web Inspector: Add refresh button to FileSystemView status bar
https://bugs.webkit.org/show_bug.cgi?id=90244
{ "name": "requestId", "$ref": "RequestId", "description": "Request identifier. Corresponding metadataReceived event should have same requestId with this." }
],
"description": "Returns metadata of the entry as metadataReceived event."
+ },
+ {
+ "name": "requestFileContent",
+ "parameters": [
+ { "name": "url", "type": "string", "description": "URL of the file that the frontend is requesting to read from." },
+ { "name": "start", "type": "integer", "optional": true, "description": "Specifies the start of range to read." },
+ { "name": "end", "type": "integer", "optional": true, "description": "Specifies the end of range to read exclusively." }
+ ],
+ "returns": [
+ { "name": "requestId", "$ref": "RequestId", "description": "Request identifier. Corresponding fileContentReceived event should have same requestId with this." }
+ ],
+ "description": "Returns content of the file as fileContentReceived event. Result should be sliced into [start, end)."
}
],
"events": [
{
"name": "metadataReceived",
"parameters": [
- { "name": "requestId", "type": "integer", "description": "Request Identifier that was returned in response to the corresponding getMetadata request." },
+ { "name": "requestId", "type": "integer", "description": "Request Identifier that was returned in response to the corresponding requestMetadata command." },
{ "name": "errorCode", "type": "integer", "description": "0, if no error. Otherwise, errorCode is set to FileError::ErrorCode value." },
{ "name": "metadata", "$ref": "FileSystem.Metadata", "optional": true, "description": "Contains metadata of the entry if the command completed successfully." }
],
- "description": "Completion event of getMetadata command."
+ "description": "Completion event of requestMetadata command."
+ },
+ {
+ "name": "fileContentReceived",
+ "parameters": [
+ { "name": "requestId", "type": "integer", "description": "Request Identifier that was returned in response to the corresponding requestFileContent command." },
+ { "name": "errorCode", "type": "integer", "description": "0, if no error. Otherwise, errorCode is set to FileError::ErrorCode value." },
+ { "name": "content", "type": "string", "optional": true, "description": "Contains content of the file as base64 encoded string." }
+ ],
+ "description": "Completion event of requestFileContent command."
}
]
},
#include "InspectorFileSystemAgent.h"
+#include "Base64.h"
#include "DOMFileSystem.h"
#include "DirectoryEntry.h"
#include "DirectoryReader.h"
#include "Document.h"
#include "EntriesCallback.h"
+#include "Entry.h"
#include "EntryArray.h"
#include "EntryCallback.h"
#include "ErrorCallback.h"
+#include "FileCallback.h"
+#include "FileEntry.h"
#include "FileError.h"
+#include "FileReader.h"
#include "FileSystemCallback.h"
#include "FileSystemCallbacks.h"
#include "Frame.h"
#include "MIMETypeRegistry.h"
#include "Metadata.h"
#include "MetadataCallback.h"
+#include "ScriptExecutionContext.h"
#include "SecurityOrigin.h"
using WebCore::TypeBuilder::Array;
return true;
}
+class ReadFileTask : public EventListener {
+ WTF_MAKE_NONCOPYABLE(ReadFileTask);
+public:
+ static PassRefPtr<ReadFileTask> create(PassRefPtr<FrontendProvider> frontendProvider, int requestId, const String& url, long long start, long long end)
+ {
+ return adoptRef(new ReadFileTask(frontendProvider, requestId, url, start, end));
+ }
+
+ virtual ~ReadFileTask()
+ {
+ reportResult(FileError::ABORT_ERR, 0);
+ }
+
+ void start(ScriptExecutionContext*);
+
+
+ virtual bool operator==(const EventListener& other) OVERRIDE
+ {
+ return this == &other;
+ }
+
+ virtual void handleEvent(ScriptExecutionContext*, Event* event) OVERRIDE
+ {
+ if (event->type() == eventNames().loadEvent)
+ didRead();
+ else if (event->type() == eventNames().errorEvent)
+ didHitError(m_reader->error().get());
+ }
+
+private:
+ bool didHitError(FileError* error)
+ {
+ reportResult(error->code(), 0);
+ return true;
+ }
+
+ bool didGetEntry(Entry*);
+ bool didGetFile(File*);
+ void didRead();
+
+ void reportResult(FileError::ErrorCode errorCode, const String* result)
+ {
+ if (!m_frontendProvider || !m_frontendProvider->frontend())
+ return;
+ m_frontendProvider->frontend()->fileContentReceived(m_requestId, static_cast<int>(errorCode), result);
+ m_frontendProvider = 0;
+ }
+
+ ReadFileTask(PassRefPtr<FrontendProvider> frontendProvider, int requestId, const String& url, long long start, long long end)
+ : EventListener(EventListener::CPPEventListenerType)
+ , m_frontendProvider(frontendProvider)
+ , m_requestId(requestId)
+ , m_url(ParsedURLString, url)
+ , m_start(start)
+ , m_end(end)
+ , m_current(start) { }
+
+ RefPtr<FrontendProvider> m_frontendProvider;
+ int m_requestId;
+ KURL m_url;
+ int m_start;
+ long long m_end;
+ long long m_current;
+
+ RefPtr<FileReader> m_reader;
+};
+
+void ReadFileTask::start(ScriptExecutionContext* scriptExecutionContext)
+{
+ ASSERT(scriptExecutionContext);
+
+ FileSystemType type;
+ String path;
+ if (!DOMFileSystemBase::crackFileSystemURL(m_url, type, path)) {
+ reportResult(FileError::SYNTAX_ERR, 0);
+ return;
+ }
+
+ RefPtr<EntryCallback> successCallback = CallbackDispatcherFactory<EntryCallback>::create(this, &ReadFileTask::didGetEntry);
+ RefPtr<ErrorCallback> errorCallback = CallbackDispatcherFactory<ErrorCallback>::create(this, &ReadFileTask::didHitError);
+ OwnPtr<ResolveURICallbacks> fileSystemCallbacks = ResolveURICallbacks::create(successCallback, errorCallback, scriptExecutionContext, type, path);
+
+ LocalFileSystem::localFileSystem().readFileSystem(scriptExecutionContext, type, fileSystemCallbacks.release());
+}
+
+bool ReadFileTask::didGetEntry(Entry* entry)
+{
+ if (entry->isDirectory()) {
+ reportResult(FileError::TYPE_MISMATCH_ERR, 0);
+ return true;
+ }
+
+ if (!entry->filesystem()->scriptExecutionContext()) {
+ reportResult(FileError::ABORT_ERR, 0);
+ return true;
+ }
+
+ RefPtr<FileCallback> successCallback = CallbackDispatcherFactory<FileCallback>::create(this, &ReadFileTask::didGetFile);
+ RefPtr<ErrorCallback> errorCallback = CallbackDispatcherFactory<ErrorCallback>::create(this, &ReadFileTask::didHitError);
+ static_cast<FileEntry*>(entry)->file(successCallback, errorCallback);
+
+ m_reader = FileReader::create(entry->filesystem()->scriptExecutionContext());
+ return true;
+}
+
+bool ReadFileTask::didGetFile(File* file)
+{
+ RefPtr<Blob> blob = file->slice(m_start, m_end);
+ m_reader->setOnload(this);
+ m_reader->setOnerror(this);
+
+ ExceptionCode ec = 0;
+ m_reader->readAsArrayBuffer(blob.get(), ec);
+ return true;
+}
+
+void ReadFileTask::didRead()
+{
+ RefPtr<ArrayBuffer> result = m_reader->arrayBufferResult();
+ String encodedResult = base64Encode(static_cast<char*>(result->data()), result->byteLength());
+ reportResult(static_cast<FileError::ErrorCode>(0), &encodedResult);
+}
+
}
// static
m_frontendProvider->frontend()->metadataReceived(*requestId, static_cast<int>(FileError::ABORT_ERR), 0);
}
+void InspectorFileSystemAgent::requestFileContent(ErrorString* error, const String& url, const int* start, const int* end, int* requestId)
+{
+ if (!m_enabled || !m_frontendProvider) {
+ *error = "FileSystem agent is not enabled";
+ return;
+ }
+ ASSERT(m_frontendProvider->frontend());
+
+ *requestId = m_nextRequestId++;
+
+ if (ScriptExecutionContext* scriptExecutionContext = scriptExecutionContextForOrigin(SecurityOrigin::createFromString(url).get()))
+ ReadFileTask::create(m_frontendProvider, *requestId, url, start ? *start : 0, end ? *end : std::numeric_limits<long long>::max())->start(scriptExecutionContext);
+ else
+ m_frontendProvider->frontend()->fileContentReceived(*requestId, static_cast<int>(FileError::ABORT_ERR), 0);
+}
+
void InspectorFileSystemAgent::setFrontend(InspectorFrontend* frontend)
{
ASSERT(frontend);
virtual void requestFileSystemRoot(ErrorString*, const String& origin, const String& type, int* requestId) OVERRIDE;
virtual void requestDirectoryContent(ErrorString*, const String& url, int* requestId) OVERRIDE;
virtual void requestMetadata(ErrorString*, const String& url, int* requestId) OVERRIDE;
+ virtual void requestFileContent(ErrorString*, const String& url, const int* start, const int* end, int* requestId) OVERRIDE;
virtual void setFrontend(InspectorFrontend*) OVERRIDE;
virtual void clearFrontend() OVERRIDE;
callback(errorCode, entries);
},
+ /**
+ * @param {WebInspector.FileSystemModel.Entry} entry
+ * @param {function(number, FileSystemAgent.Metadata=)} callback
+ */
requestMetadata: function(entry, callback)
{
this._agentWrapper.requestMetadata(entry.url, callback);
+ },
+
+ /**
+ * @param {WebInspector.FileSystemModel.File} file
+ * @param {number} start
+ * @param {number} end
+ * @param {function(number, string=)} callback
+ */
+ requestFileContent: function(file, start, end, callback)
+ {
+ this._agentWrapper.requestFileContent(file.url, start, end, callback);
}
}
get resourceType()
{
return this._resourceType;
+ },
+
+ /**
+ * @param {number} start
+ * @param {number} end
+ * @param {function(number, string=)} callback
+ */
+ requestFileContent: function(start, end, callback)
+ {
+ this.fileSystemModel.requestFileContent(this, start, end, callback);
}
}
this._pendingFileSystemRootRequests = {};
this._pendingDirectoryContentRequests = {};
this._pendingMetadataRequests = {};
+ this._pendingFileContentRequests = {};
InspectorBackend.registerFileSystemDispatcher(new WebInspector.FileSystemDispatcher(this));
FileSystemAgent.enable();
return;
delete this._pendingMetadataRequests[requestId];
callback(errorCode, metadata);
+ },
+
+ /**
+ * @param {string} url
+ * @param {number} start
+ * @param {number} end
+ * @param {function(number, string)} callback
+ */
+ requestFileContent: function(url, start, end, callback)
+ {
+ var store = this._pendingFileContentRequests;
+ FileSystemAgent.requestFileContent(url, start, end, requestAccepted);
+
+ function requestAccepted(error, requestId)
+ {
+ if (!error)
+ store[requestId] = callback;
+ }
+ },
+
+ /**
+ * @param {number} requestId
+ * @param {number} errorCode
+ * @param {string=} content
+ */
+ _fileContentReceived: function(requestId, errorCode, content)
+ {
+ var callback = /** @type {function(number, string=)} */ this._pendingFileContentRequests[requestId];
+ if (!callback)
+ return;
+ delete this._pendingFileContentRequests[requestId];
+ callback(errorCode, content);
}
}
metadataReceived: function(requestId, errorCode, metadata)
{
this._agentWrapper._metadataReceived(requestId, errorCode, metadata);
+ },
+
+ /**
+ * @param {number} requestId
+ * @param {number} errorCode
+ * @param {string=} content
+ */
+ fileContentReceived: function(requestId, errorCode, content)
+ {
+ this._agentWrapper._fileContentReceived(requestId, errorCode, content);
}
}