summaryrefslogtreecommitdiffstats
path: root/webkit/support
diff options
context:
space:
mode:
Diffstat (limited to 'webkit/support')
-rw-r--r--webkit/support/mac/DumpRenderTreePasteboard.h46
-rw-r--r--webkit/support/mac/DumpRenderTreePasteboard.m214
-rw-r--r--webkit/support/mock_webclipboard_impl.cc207
-rw-r--r--webkit/support/mock_webclipboard_impl.h60
-rw-r--r--webkit/support/platform_support_android.cc2
-rw-r--r--webkit/support/platform_support_mac.mm4
-rw-r--r--webkit/support/simple_appcache_system.cc465
-rw-r--r--webkit/support/simple_appcache_system.h136
-rw-r--r--webkit/support/simple_clipboard_impl.cc118
-rw-r--r--webkit/support/simple_clipboard_impl.h43
-rw-r--r--webkit/support/simple_dom_storage_system.cc286
-rw-r--r--webkit/support/simple_dom_storage_system.h79
-rw-r--r--webkit/support/simple_file_system.cc410
-rw-r--r--webkit/support/simple_file_system.h160
-rw-r--r--webkit/support/simple_file_writer.cc205
-rw-r--r--webkit/support/simple_file_writer.h53
-rw-r--r--webkit/support/simple_resource_loader_bridge.cc1168
-rw-r--r--webkit/support/simple_resource_loader_bridge.h61
-rw-r--r--webkit/support/simple_socket_stream_bridge.cc259
-rw-r--r--webkit/support/simple_socket_stream_bridge.h35
-rw-r--r--webkit/support/simple_webcookiejar_impl.cc25
-rw-r--r--webkit/support/simple_webcookiejar_impl.h22
-rw-r--r--webkit/support/test_shell_dummy.cc7
-rw-r--r--webkit/support/test_shell_request_context.cc140
-rw-r--r--webkit/support/test_shell_request_context.h56
-rw-r--r--webkit/support/test_shell_webblobregistry_impl.cc124
-rw-r--r--webkit/support/test_shell_webblobregistry_impl.h49
-rw-r--r--webkit/support/test_shell_webmimeregistry_impl.cc70
-rw-r--r--webkit/support/test_shell_webmimeregistry_impl.h45
-rw-r--r--webkit/support/test_webkit_platform_support.cc16
-rw-r--r--webkit/support/test_webkit_platform_support.h12
-rw-r--r--webkit/support/webkit_support.cc8
-rw-r--r--webkit/support/webkit_support.gypi52
33 files changed, 4590 insertions, 47 deletions
diff --git a/webkit/support/mac/DumpRenderTreePasteboard.h b/webkit/support/mac/DumpRenderTreePasteboard.h
new file mode 100644
index 0000000..41796ea3
--- /dev/null
+++ b/webkit/support/mac/DumpRenderTreePasteboard.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2005, 2006, 2007 Apple, Inc. All rights reserved.
+ * (C) 2007 Graham Dennis (graham.dennis@gmail.com)
+ * (C) 2007 Eric Seidel <eric@webkit.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+//
+// This file comes from WebKit:
+// WebKit/Tools/DumpRenderTree/mac/DumpRenderTreePasteboard.m
+// It is copied here since that location is the best for pulling into Chromium
+// and has a few includes commented out. darin@chromium.org suggests in the
+// future we see if there is a better place for it to live so it could be
+// shared.
+//
+
+#import <AppKit/AppKit.h>
+// #import <WebKit/WebTypesInternal.h>
+
+@interface DumpRenderTreePasteboard : NSPasteboard
+- (NSInteger)declareType:(NSString *)type owner:(id)newOwner;
++ (void)releaseLocalPasteboards;
+@end
diff --git a/webkit/support/mac/DumpRenderTreePasteboard.m b/webkit/support/mac/DumpRenderTreePasteboard.m
new file mode 100644
index 0000000..3e3cf1c
--- /dev/null
+++ b/webkit/support/mac/DumpRenderTreePasteboard.m
@@ -0,0 +1,214 @@
+/*
+ * Copyright (C) 2005, 2006, 2007 Apple, Inc. All rights reserved.
+ * (C) 2007 Graham Dennis (graham.dennis@gmail.com)
+ * (C) 2007 Eric Seidel <eric@webkit.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+//
+// This file comes from WebKit:
+// WebKit/Tools/DumpRenderTree/mac/DumpRenderTreePasteboard.m
+// It is copied here since that location is the best for pulling into Chromium
+// and has a few includes commented out. darin@chromium.org suggests in the
+// future we see if there is a better place for it to live so it could be
+// shared.
+//
+
+// #import "DumpRenderTreeMac.h"
+#import "DumpRenderTreePasteboard.h"
+
+// #import <WebKit/WebTypesInternal.h>
+
+@interface LocalPasteboard : NSPasteboard
+{
+ NSMutableArray *typesArray;
+ NSMutableSet *typesSet;
+ NSMutableDictionary *dataByType;
+ NSInteger changeCount;
+}
+@end
+
+static NSMutableDictionary *localPasteboards;
+
+@implementation DumpRenderTreePasteboard
+
+// Return a local pasteboard so we don't disturb the real pasteboards when running tests.
++ (NSPasteboard *)_pasteboardWithName:(NSString *)name
+{
+ static int number = 0;
+ if (!name)
+ name = [NSString stringWithFormat:@"LocalPasteboard%d", ++number];
+ if (!localPasteboards)
+ localPasteboards = [[NSMutableDictionary alloc] init];
+ LocalPasteboard *pasteboard = [localPasteboards objectForKey:name];
+ if (pasteboard)
+ return pasteboard;
+ pasteboard = [[LocalPasteboard alloc] init];
+ [localPasteboards setObject:pasteboard forKey:name];
+ [pasteboard release];
+ return pasteboard;
+}
+
++ (void)releaseLocalPasteboards
+{
+ [localPasteboards release];
+ localPasteboards = nil;
+}
+
+// Convenience method for JS so that it doesn't have to try and create a NSArray on the objc side instead
+// of the usual WebScriptObject that is passed around
+- (NSInteger)declareType:(NSString *)type owner:(id)newOwner
+{
+ return [self declareTypes:[NSArray arrayWithObject:type] owner:newOwner];
+}
+
+@end
+
+@implementation LocalPasteboard
+
++ (id)alloc
+{
+ return NSAllocateObject(self, 0, 0);
+}
+
+- (id)init
+{
+ typesArray = [[NSMutableArray alloc] init];
+ typesSet = [[NSMutableSet alloc] init];
+ dataByType = [[NSMutableDictionary alloc] init];
+ return self;
+}
+
+- (void)dealloc
+{
+ [typesArray release];
+ [typesSet release];
+ [dataByType release];
+ [super dealloc];
+}
+
+- (NSString *)name
+{
+ return nil;
+}
+
+- (void)releaseGlobally
+{
+}
+
+- (NSInteger)declareTypes:(NSArray *)newTypes owner:(id)newOwner
+{
+ [typesArray removeAllObjects];
+ [typesSet removeAllObjects];
+ [dataByType removeAllObjects];
+ return [self addTypes:newTypes owner:newOwner];
+}
+
+- (NSInteger)addTypes:(NSArray *)newTypes owner:(id)newOwner
+{
+ unsigned count = [newTypes count];
+ unsigned i;
+ for (i = 0; i < count; ++i) {
+ NSString *type = [newTypes objectAtIndex:i];
+ NSString *setType = [typesSet member:type];
+ if (!setType) {
+ setType = [type copy];
+ [typesArray addObject:setType];
+ [typesSet addObject:setType];
+ [setType release];
+ }
+ if (newOwner && [newOwner respondsToSelector:@selector(pasteboard:provideDataForType:)])
+ [newOwner pasteboard:self provideDataForType:setType];
+ }
+ return ++changeCount;
+}
+
+- (NSInteger)changeCount
+{
+ return changeCount;
+}
+
+- (NSArray *)types
+{
+ return typesArray;
+}
+
+- (NSString *)availableTypeFromArray:(NSArray *)types
+{
+ unsigned count = [types count];
+ unsigned i;
+ for (i = 0; i < count; ++i) {
+ NSString *type = [types objectAtIndex:i];
+ NSString *setType = [typesSet member:type];
+ if (setType)
+ return setType;
+ }
+ return nil;
+}
+
+- (BOOL)setData:(NSData *)data forType:(NSString *)dataType
+{
+ if (data == nil)
+ data = [NSData data];
+ if (![typesSet containsObject:dataType])
+ return NO;
+ [dataByType setObject:data forKey:dataType];
+ ++changeCount;
+ return YES;
+}
+
+- (NSData *)dataForType:(NSString *)dataType
+{
+ return [dataByType objectForKey:dataType];
+}
+
+- (BOOL)setPropertyList:(id)propertyList forType:(NSString *)dataType
+{
+ CFDataRef data = NULL;
+ if (propertyList)
+ data = CFPropertyListCreateXMLData(NULL, propertyList);
+ BOOL result = [self setData:(NSData *)data forType:dataType];
+ if (data)
+ CFRelease(data);
+ return result;
+}
+
+- (BOOL)setString:(NSString *)string forType:(NSString *)dataType
+{
+ CFDataRef data = NULL;
+ if (string) {
+ if ([string length] == 0)
+ data = CFDataCreate(NULL, NULL, 0);
+ else
+ data = CFStringCreateExternalRepresentation(NULL, (CFStringRef)string, kCFStringEncodingUTF8, 0);
+ }
+ BOOL result = [self setData:(NSData *)data forType:dataType];
+ if (data)
+ CFRelease(data);
+ return result;
+}
+
+@end
diff --git a/webkit/support/mock_webclipboard_impl.cc b/webkit/support/mock_webclipboard_impl.cc
new file mode 100644
index 0000000..e71681c
--- /dev/null
+++ b/webkit/support/mock_webclipboard_impl.cc
@@ -0,0 +1,207 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "webkit/support/mock_webclipboard_impl.h"
+
+#include <algorithm>
+
+#include "base/logging.h"
+#include "base/stl_util.h"
+#include "base/string_util.h"
+#include "base/utf_string_conversions.h"
+#include "third_party/WebKit/public/platform/WebCommon.h"
+#include "third_party/WebKit/public/platform/WebDragData.h"
+#include "third_party/WebKit/public/platform/WebImage.h"
+#include "third_party/WebKit/public/platform/WebURL.h"
+#include "ui/base/clipboard/clipboard.h"
+#include "webkit/glue/webclipboard_impl.h"
+#include "webkit/glue/webkit_glue.h"
+#include "webkit/support/webkit_support_gfx.h"
+
+using WebKit::WebDragData;
+using WebKit::WebString;
+using WebKit::WebURL;
+using WebKit::WebVector;
+
+MockWebClipboardImpl::MockWebClipboardImpl() {
+}
+
+MockWebClipboardImpl::~MockWebClipboardImpl() {
+}
+
+bool MockWebClipboardImpl::isFormatAvailable(Format format, Buffer buffer) {
+ switch (format) {
+ case FormatPlainText:
+ return !m_plainText.isNull();
+
+ case FormatHTML:
+ return !m_htmlText.isNull();
+
+ case FormatSmartPaste:
+ return m_writeSmartPaste;
+
+ default:
+ NOTREACHED();
+ return false;
+ }
+
+ switch (buffer) {
+ case BufferStandard:
+ break;
+ case BufferSelection:
+#if defined(OS_POSIX) && !defined(OS_MACOSX)
+ break;
+#endif
+ default:
+ NOTREACHED();
+ return false;
+ }
+
+ return true;
+}
+
+WebVector<WebString> MockWebClipboardImpl::readAvailableTypes(
+ Buffer buffer, bool* containsFilenames) {
+ *containsFilenames = false;
+ std::vector<WebString> results;
+ if (!m_plainText.isEmpty()) {
+ results.push_back(WebString("text/plain"));
+ }
+ if (!m_htmlText.isEmpty()) {
+ results.push_back(WebString("text/html"));
+ }
+ if (!m_image.isNull()) {
+ results.push_back(WebString("image/png"));
+ }
+ for (std::map<base::string16, base::string16>::const_iterator it =
+ m_customData.begin();
+ it != m_customData.end(); ++it) {
+ CHECK(std::find(results.begin(), results.end(), it->first) ==
+ results.end());
+ results.push_back(it->first);
+ }
+ return results;
+}
+
+WebKit::WebString MockWebClipboardImpl::readPlainText(
+ WebKit::WebClipboard::Buffer buffer) {
+ return m_plainText;
+}
+
+// TODO(wtc): set output argument *url.
+WebKit::WebString MockWebClipboardImpl::readHTML(
+ WebKit::WebClipboard::Buffer buffer, WebKit::WebURL* url,
+ unsigned* fragmentStart, unsigned* fragmentEnd) {
+ *fragmentStart = 0;
+ *fragmentEnd = static_cast<unsigned>(m_htmlText.length());
+ return m_htmlText;
+}
+
+WebKit::WebData MockWebClipboardImpl::readImage(
+ WebKit::WebClipboard::Buffer buffer) {
+ std::string data;
+ std::vector<unsigned char> encoded_image;
+ // TODO(dcheng): Verify that we can assume the image is ARGB8888. Note that
+ // for endianess reasons, it will be BGRA8888 on Windows.
+ const SkBitmap& bitmap = m_image.getSkBitmap();
+ SkAutoLockPixels lock(bitmap);
+#if defined(OS_ANDROID)
+ webkit_support::EncodeRGBAPNG(static_cast<unsigned char*>(bitmap.getPixels()),
+ bitmap.width(),
+ bitmap.height(),
+ bitmap.rowBytes(),
+ &encoded_image);
+#else
+ webkit_support::EncodeBGRAPNG(static_cast<unsigned char*>(bitmap.getPixels()),
+ bitmap.width(),
+ bitmap.height(),
+ bitmap.rowBytes(),
+ false,
+ &encoded_image);
+#endif
+ data.assign(reinterpret_cast<char*>(vector_as_array(&encoded_image)),
+ encoded_image.size());
+ return data;
+}
+
+WebKit::WebString MockWebClipboardImpl::readCustomData(
+ WebKit::WebClipboard::Buffer buffer,
+ const WebKit::WebString& type) {
+ std::map<base::string16, base::string16>::const_iterator it =
+ m_customData.find(type);
+ if (it != m_customData.end())
+ return it->second;
+ return WebKit::WebString();
+}
+
+void MockWebClipboardImpl::writeHTML(
+ const WebKit::WebString& htmlText, const WebKit::WebURL& url,
+ const WebKit::WebString& plainText, bool writeSmartPaste) {
+ clear();
+
+ m_htmlText = htmlText;
+ m_plainText = plainText;
+ m_writeSmartPaste = writeSmartPaste;
+}
+
+void MockWebClipboardImpl::writePlainText(const WebKit::WebString& plain_text) {
+ clear();
+
+ m_plainText = plain_text;
+}
+
+void MockWebClipboardImpl::writeURL(
+ const WebKit::WebURL& url, const WebKit::WebString& title) {
+ clear();
+
+ m_htmlText = WebString::fromUTF8(
+ webkit_glue::WebClipboardImpl::URLToMarkup(url, title));
+ m_plainText = url.spec().utf16();
+}
+
+void MockWebClipboardImpl::writeImage(const WebKit::WebImage& image,
+ const WebKit::WebURL& url, const WebKit::WebString& title) {
+ if (!image.isNull()) {
+ clear();
+
+ m_plainText = m_htmlText;
+ m_htmlText = WebString::fromUTF8(
+ webkit_glue::WebClipboardImpl::URLToImageMarkup(url, title));
+ m_image = image;
+ }
+}
+
+void MockWebClipboardImpl::writeDataObject(const WebDragData& data) {
+ clear();
+
+ const WebVector<WebDragData::Item>& itemList = data.items();
+ for (size_t i = 0; i < itemList.size(); ++i) {
+ const WebDragData::Item& item = itemList[i];
+ switch (item.storageType) {
+ case WebDragData::Item::StorageTypeString: {
+ if (EqualsASCII(item.stringType, ui::Clipboard::kMimeTypeText)) {
+ m_plainText = item.stringData;
+ continue;
+ }
+ if (EqualsASCII(item.stringType, ui::Clipboard::kMimeTypeHTML)) {
+ m_htmlText = item.stringData;
+ continue;
+ }
+ m_customData.insert(std::make_pair(item.stringType, item.stringData));
+ continue;
+ }
+ case WebDragData::Item::StorageTypeFilename:
+ case WebDragData::Item::StorageTypeBinaryData:
+ NOTREACHED(); // Currently unused by the clipboard implementation.
+ }
+ }
+}
+
+void MockWebClipboardImpl::clear() {
+ m_plainText = WebString();
+ m_htmlText = WebString();
+ m_image.reset();
+ m_customData.clear();
+ m_writeSmartPaste = false;
+}
diff --git a/webkit/support/mock_webclipboard_impl.h b/webkit/support/mock_webclipboard_impl.h
new file mode 100644
index 0000000..845d1bf
--- /dev/null
+++ b/webkit/support/mock_webclipboard_impl.h
@@ -0,0 +1,60 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// This file mocks out just enough of the WebClipboard API for running the
+// webkit tests. This is so we can run webkit tests without them sharing a
+// clipboard, which allows for running them in parallel and having the tests
+// not interact with actual user actions.
+
+#ifndef WEBKIT_SUPPORT_MOCK_WEBCLIPBOARD_IMPL_H_
+#define WEBKIT_SUPPORT_MOCK_WEBCLIPBOARD_IMPL_H_
+
+#include <map>
+
+#include "base/string16.h"
+#include "third_party/WebKit/public/platform/WebClipboard.h"
+#include "third_party/WebKit/public/platform/WebDragData.h"
+#include "third_party/WebKit/public/platform/WebImage.h"
+
+class MockWebClipboardImpl : public WebKit::WebClipboard {
+ public:
+ MockWebClipboardImpl();
+ virtual ~MockWebClipboardImpl();
+
+ virtual bool isFormatAvailable(WebKit::WebClipboard::Format format,
+ WebKit::WebClipboard::Buffer buffer);
+ virtual WebKit::WebVector<WebKit::WebString> readAvailableTypes(
+ WebKit::WebClipboard::Buffer buffer, bool* containsFilenames);
+
+ virtual WebKit::WebString readPlainText(WebKit::WebClipboard::Buffer buffer);
+ virtual WebKit::WebString readHTML(WebKit::WebClipboard::Buffer buffer,
+ WebKit::WebURL* url,
+ unsigned* fragmentStart,
+ unsigned* fragmentEnd);
+ virtual WebKit::WebData readImage(WebKit::WebClipboard::Buffer buffer);
+ virtual WebKit::WebString readCustomData(WebKit::WebClipboard::Buffer buffer,
+ const WebKit::WebString& type);
+
+ virtual void writePlainText(const WebKit::WebString& plain_text);
+ virtual void writeHTML(
+ const WebKit::WebString& htmlText, const WebKit::WebURL& url,
+ const WebKit::WebString& plainText, bool writeSmartPaste);
+ virtual void writeURL(
+ const WebKit::WebURL& url, const WebKit::WebString& title);
+ virtual void writeImage(
+ const WebKit::WebImage& image, const WebKit::WebURL& url,
+ const WebKit::WebString& title);
+ virtual void writeDataObject(const WebKit::WebDragData& data);
+
+ private:
+ void clear();
+
+ WebKit::WebString m_plainText;
+ WebKit::WebString m_htmlText;
+ WebKit::WebImage m_image;
+ std::map<base::string16, base::string16> m_customData;
+ bool m_writeSmartPaste;
+};
+
+#endif // WEBKIT_SUPPORT_MOCK_WEBCLIPBOARD_IMPL_H_
diff --git a/webkit/support/platform_support_android.cc b/webkit/support/platform_support_android.cc
index 3c1e2c4..581c974 100644
--- a/webkit/support/platform_support_android.cc
+++ b/webkit/support/platform_support_android.cc
@@ -20,8 +20,8 @@
#include "ui/android/ui_jni_registrar.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gl/android/gl_jni_registrar.h"
+#include "webkit/support/simple_resource_loader_bridge.h"
#include "webkit/support/test_webkit_platform_support.h"
-#include "webkit/tools/test_shell/simple_resource_loader_bridge.h"
namespace {
diff --git a/webkit/support/platform_support_mac.mm b/webkit/support/platform_support_mac.mm
index 5abd93f..9a48d95 100644
--- a/webkit/support/platform_support_mac.mm
+++ b/webkit/support/platform_support_mac.mm
@@ -20,9 +20,9 @@
#include "grit/webkit_resources.h"
#include "ui/base/resource/data_pack.h"
#include "webkit/plugins/npapi/plugin_list.h"
-#include "webkit/support/test_webkit_platform_support.h"
#import "webkit/support/drt_application_mac.h"
-#import "webkit/tools/test_shell/mac/DumpRenderTreePasteboard.h"
+#import "webkit/support/mac/DumpRenderTreePasteboard.h"
+#include "webkit/support/test_webkit_platform_support.h"
static ui::DataPack* g_resource_data_pack = NULL;
diff --git a/webkit/support/simple_appcache_system.cc b/webkit/support/simple_appcache_system.cc
new file mode 100644
index 0000000..1305bc9
--- /dev/null
+++ b/webkit/support/simple_appcache_system.cc
@@ -0,0 +1,465 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "webkit/support/simple_appcache_system.h"
+
+#include <string>
+#include <vector>
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/callback.h"
+#include "base/synchronization/waitable_event.h"
+#include "webkit/appcache/appcache_interceptor.h"
+#include "webkit/appcache/web_application_cache_host_impl.h"
+#include "webkit/support/simple_resource_loader_bridge.h"
+
+using WebKit::WebApplicationCacheHost;
+using WebKit::WebApplicationCacheHostClient;
+using appcache::WebApplicationCacheHostImpl;
+using appcache::AppCacheBackendImpl;
+using appcache::AppCacheInterceptor;
+
+// SimpleFrontendProxy --------------------------------------------------------
+// Proxies method calls from the backend IO thread to the frontend UI thread.
+
+class SimpleFrontendProxy
+ : public base::RefCountedThreadSafe<SimpleFrontendProxy>,
+ public appcache::AppCacheFrontend {
+ public:
+ explicit SimpleFrontendProxy(SimpleAppCacheSystem* appcache_system)
+ : system_(appcache_system) {
+ }
+
+ void clear_appcache_system() { system_ = NULL; }
+
+ virtual void OnCacheSelected(int host_id,
+ const appcache::AppCacheInfo& info) OVERRIDE {
+ if (!system_)
+ return;
+ if (system_->is_io_thread()) {
+ system_->ui_message_loop()->PostTask(
+ FROM_HERE,
+ base::Bind(&SimpleFrontendProxy::OnCacheSelected, this, host_id,
+ info));
+ } else if (system_->is_ui_thread()) {
+ system_->frontend_impl_.OnCacheSelected(host_id, info);
+ } else {
+ NOTREACHED();
+ }
+ }
+
+ virtual void OnStatusChanged(const std::vector<int>& host_ids,
+ appcache::Status status) OVERRIDE {
+ if (!system_)
+ return;
+ if (system_->is_io_thread())
+ system_->ui_message_loop()->PostTask(
+ FROM_HERE,
+ base::Bind(&SimpleFrontendProxy::OnStatusChanged, this, host_ids,
+ status));
+ else if (system_->is_ui_thread())
+ system_->frontend_impl_.OnStatusChanged(host_ids, status);
+ else
+ NOTREACHED();
+ }
+
+ virtual void OnEventRaised(const std::vector<int>& host_ids,
+ appcache::EventID event_id) OVERRIDE {
+ if (!system_)
+ return;
+ if (system_->is_io_thread())
+ system_->ui_message_loop()->PostTask(
+ FROM_HERE,
+ base::Bind(&SimpleFrontendProxy::OnEventRaised, this, host_ids,
+ event_id));
+ else if (system_->is_ui_thread())
+ system_->frontend_impl_.OnEventRaised(host_ids, event_id);
+ else
+ NOTREACHED();
+ }
+
+ virtual void OnProgressEventRaised(const std::vector<int>& host_ids,
+ const GURL& url,
+ int num_total, int num_complete) OVERRIDE {
+ if (!system_)
+ return;
+ if (system_->is_io_thread())
+ system_->ui_message_loop()->PostTask(
+ FROM_HERE,
+ base::Bind(&SimpleFrontendProxy::OnProgressEventRaised, this,
+ host_ids, url, num_total, num_complete));
+ else if (system_->is_ui_thread())
+ system_->frontend_impl_.OnProgressEventRaised(
+ host_ids, url, num_total, num_complete);
+ else
+ NOTREACHED();
+ }
+
+ virtual void OnErrorEventRaised(const std::vector<int>& host_ids,
+ const std::string& message) OVERRIDE {
+ if (!system_)
+ return;
+ if (system_->is_io_thread())
+ system_->ui_message_loop()->PostTask(
+ FROM_HERE,
+ base::Bind(&SimpleFrontendProxy::OnErrorEventRaised, this, host_ids,
+ message));
+ else if (system_->is_ui_thread())
+ system_->frontend_impl_.OnErrorEventRaised(
+ host_ids, message);
+ else
+ NOTREACHED();
+ }
+
+ virtual void OnLogMessage(int host_id,
+ appcache::LogLevel log_level,
+ const std::string& message) OVERRIDE {
+ if (!system_)
+ return;
+ if (system_->is_io_thread())
+ system_->ui_message_loop()->PostTask(
+ FROM_HERE,
+ base::Bind(&SimpleFrontendProxy::OnLogMessage, this, host_id,
+ log_level, message));
+ else if (system_->is_ui_thread())
+ system_->frontend_impl_.OnLogMessage(
+ host_id, log_level, message);
+ else
+ NOTREACHED();
+ }
+
+ virtual void OnContentBlocked(int host_id,
+ const GURL& manifest_url) OVERRIDE {}
+
+ private:
+ friend class base::RefCountedThreadSafe<SimpleFrontendProxy>;
+
+ virtual ~SimpleFrontendProxy() {}
+
+ SimpleAppCacheSystem* system_;
+};
+
+
+// SimpleBackendProxy --------------------------------------------------------
+// Proxies method calls from the frontend UI thread to the backend IO thread.
+
+class SimpleBackendProxy
+ : public base::RefCountedThreadSafe<SimpleBackendProxy>,
+ public appcache::AppCacheBackend {
+ public:
+ explicit SimpleBackendProxy(SimpleAppCacheSystem* appcache_system)
+ : system_(appcache_system), event_(true, false) {
+ get_status_callback_ =
+ base::Bind(&SimpleBackendProxy::GetStatusCallback,
+ base::Unretained(this));
+ start_update_callback_ =
+ base::Bind(&SimpleBackendProxy::StartUpdateCallback,
+ base::Unretained(this));
+ swap_cache_callback_=
+ base::Bind(&SimpleBackendProxy::SwapCacheCallback,
+ base::Unretained(this));
+ }
+
+ virtual void RegisterHost(int host_id) OVERRIDE {
+ if (system_->is_ui_thread()) {
+ system_->io_message_loop()->PostTask(
+ FROM_HERE,
+ base::Bind(&SimpleBackendProxy::RegisterHost, this, host_id));
+ } else if (system_->is_io_thread()) {
+ system_->backend_impl_->RegisterHost(host_id);
+ } else {
+ NOTREACHED();
+ }
+ }
+
+ virtual void UnregisterHost(int host_id) OVERRIDE {
+ if (system_->is_ui_thread()) {
+ system_->io_message_loop()->PostTask(
+ FROM_HERE,
+ base::Bind(&SimpleBackendProxy::UnregisterHost, this, host_id));
+ } else if (system_->is_io_thread()) {
+ system_->backend_impl_->UnregisterHost(host_id);
+ } else {
+ NOTREACHED();
+ }
+ }
+
+ virtual void SetSpawningHostId(int host_id, int spawning_host_id) OVERRIDE {
+ if (system_->is_ui_thread()) {
+ system_->io_message_loop()->PostTask(
+ FROM_HERE,
+ base::Bind(&SimpleBackendProxy::SetSpawningHostId, this, host_id,
+ spawning_host_id));
+ } else if (system_->is_io_thread()) {
+ system_->backend_impl_->SetSpawningHostId(host_id, spawning_host_id);
+ } else {
+ NOTREACHED();
+ }
+ }
+
+ virtual void SelectCache(int host_id,
+ const GURL& document_url,
+ const int64 cache_document_was_loaded_from,
+ const GURL& manifest_url) OVERRIDE {
+ if (system_->is_ui_thread()) {
+ system_->io_message_loop()->PostTask(
+ FROM_HERE,
+ base::Bind(&SimpleBackendProxy::SelectCache, this, host_id,
+ document_url, cache_document_was_loaded_from,
+ manifest_url));
+ } else if (system_->is_io_thread()) {
+ system_->backend_impl_->SelectCache(host_id, document_url,
+ cache_document_was_loaded_from,
+ manifest_url);
+ } else {
+ NOTREACHED();
+ }
+ }
+
+ virtual void GetResourceList(
+ int host_id,
+ std::vector<appcache::AppCacheResourceInfo>* resource_infos) OVERRIDE {
+ if (system_->is_ui_thread()) {
+ system_->io_message_loop()->PostTask(
+ FROM_HERE,
+ base::Bind(&SimpleBackendProxy::GetResourceList, this, host_id,
+ resource_infos));
+ } else if (system_->is_io_thread()) {
+ system_->backend_impl_->GetResourceList(host_id, resource_infos);
+ } else {
+ NOTREACHED();
+ }
+ }
+
+ virtual void SelectCacheForWorker(
+ int host_id,
+ int parent_process_id,
+ int parent_host_id) OVERRIDE {
+ NOTIMPLEMENTED(); // Workers are not supported in test_shell.
+ }
+
+ virtual void SelectCacheForSharedWorker(
+ int host_id,
+ int64 appcache_id) OVERRIDE {
+ NOTIMPLEMENTED(); // Workers are not supported in test_shell.
+ }
+
+ virtual void MarkAsForeignEntry(
+ int host_id,
+ const GURL& document_url,
+ int64 cache_document_was_loaded_from) OVERRIDE {
+ if (system_->is_ui_thread()) {
+ system_->io_message_loop()->PostTask(
+ FROM_HERE,
+ base::Bind(&SimpleBackendProxy::MarkAsForeignEntry, this, host_id,
+ document_url, cache_document_was_loaded_from));
+ } else if (system_->is_io_thread()) {
+ system_->backend_impl_->MarkAsForeignEntry(
+ host_id, document_url,
+ cache_document_was_loaded_from);
+ } else {
+ NOTREACHED();
+ }
+ }
+
+ virtual appcache::Status GetStatus(int host_id) OVERRIDE {
+ if (system_->is_ui_thread()) {
+ status_result_ = appcache::UNCACHED;
+ event_.Reset();
+ system_->io_message_loop()->PostTask(
+ FROM_HERE,
+ base::Bind(base::IgnoreResult(&SimpleBackendProxy::GetStatus),
+ this, host_id));
+ event_.Wait();
+ } else if (system_->is_io_thread()) {
+ system_->backend_impl_->GetStatusWithCallback(
+ host_id, get_status_callback_, NULL);
+ } else {
+ NOTREACHED();
+ }
+ return status_result_;
+ }
+
+ virtual bool StartUpdate(int host_id) OVERRIDE {
+ if (system_->is_ui_thread()) {
+ bool_result_ = false;
+ event_.Reset();
+ system_->io_message_loop()->PostTask(
+ FROM_HERE,
+ base::Bind(base::IgnoreResult(&SimpleBackendProxy::StartUpdate),
+ this, host_id));
+ event_.Wait();
+ } else if (system_->is_io_thread()) {
+ system_->backend_impl_->StartUpdateWithCallback(
+ host_id, start_update_callback_, NULL);
+ } else {
+ NOTREACHED();
+ }
+ return bool_result_;
+ }
+
+ virtual bool SwapCache(int host_id) OVERRIDE {
+ if (system_->is_ui_thread()) {
+ bool_result_ = false;
+ event_.Reset();
+ system_->io_message_loop()->PostTask(
+ FROM_HERE,
+ base::Bind(base::IgnoreResult(&SimpleBackendProxy::SwapCache),
+ this, host_id));
+ event_.Wait();
+ } else if (system_->is_io_thread()) {
+ system_->backend_impl_->SwapCacheWithCallback(
+ host_id, swap_cache_callback_, NULL);
+ } else {
+ NOTREACHED();
+ }
+ return bool_result_;
+ }
+
+ void GetStatusCallback(appcache::Status status, void* param) {
+ status_result_ = status;
+ event_.Signal();
+ }
+
+ void StartUpdateCallback(bool result, void* param) {
+ bool_result_ = result;
+ event_.Signal();
+ }
+
+ void SwapCacheCallback(bool result, void* param) {
+ bool_result_ = result;
+ event_.Signal();
+ }
+
+ void SignalEvent() {
+ event_.Signal();
+ }
+
+ private:
+ friend class base::RefCountedThreadSafe<SimpleBackendProxy>;
+
+ virtual ~SimpleBackendProxy() {}
+
+ SimpleAppCacheSystem* system_;
+ base::WaitableEvent event_;
+ bool bool_result_;
+ appcache::Status status_result_;
+ appcache::GetStatusCallback get_status_callback_;
+ appcache::StartUpdateCallback start_update_callback_;
+ appcache::SwapCacheCallback swap_cache_callback_;
+};
+
+
+// SimpleAppCacheSystem --------------------------------------------------------
+
+// This class only works for a single process browser.
+static const int kSingleProcessId = 1;
+
+// A not so thread safe singleton, but should work for test_shell.
+SimpleAppCacheSystem* SimpleAppCacheSystem::instance_ = NULL;
+
+SimpleAppCacheSystem::SimpleAppCacheSystem()
+ : io_message_loop_(NULL), ui_message_loop_(NULL),
+ backend_proxy_(new SimpleBackendProxy(this)),
+ frontend_proxy_(new SimpleFrontendProxy(this)),
+ backend_impl_(NULL), service_(NULL), db_thread_("AppCacheDBThread") {
+ DCHECK(!instance_);
+ instance_ = this;
+}
+
+static void SignalEvent(base::WaitableEvent* event) {
+ event->Signal();
+}
+
+SimpleAppCacheSystem::~SimpleAppCacheSystem() {
+ DCHECK(!io_message_loop_ && !backend_impl_ && !service_);
+ frontend_proxy_->clear_appcache_system(); // in case a task is in transit
+ instance_ = NULL;
+
+ if (db_thread_.IsRunning()) {
+ // We pump a task thru the db thread to ensure any tasks previously
+ // scheduled on that thread have been performed prior to return.
+ base::WaitableEvent event(false, false);
+ db_thread_.message_loop()->PostTask(
+ FROM_HERE, base::Bind(&SignalEvent, &event));
+ event.Wait();
+ }
+}
+
+void SimpleAppCacheSystem::InitOnUIThread(
+ const base::FilePath& cache_directory) {
+ DCHECK(!ui_message_loop_);
+ ui_message_loop_ = base::MessageLoop::current();
+ cache_directory_ = cache_directory;
+}
+
+void SimpleAppCacheSystem::InitOnIOThread(
+ net::URLRequestContext* request_context) {
+ if (!is_initailized_on_ui_thread())
+ return;
+
+ DCHECK(!io_message_loop_);
+ io_message_loop_ = base::MessageLoop::current();
+
+ if (!db_thread_.IsRunning())
+ db_thread_.Start();
+
+ // Recreate and initialize per each IO thread.
+ service_ = new appcache::AppCacheService(NULL);
+ backend_impl_ = new appcache::AppCacheBackendImpl();
+ service_->Initialize(cache_directory_,
+ db_thread_.message_loop_proxy(),
+ SimpleResourceLoaderBridge::GetCacheThread());
+ service_->set_request_context(request_context);
+ backend_impl_->Initialize(service_, frontend_proxy_.get(), kSingleProcessId);
+
+ AppCacheInterceptor::EnsureRegistered();
+}
+
+void SimpleAppCacheSystem::CleanupIOThread() {
+ DCHECK(is_io_thread());
+
+ delete backend_impl_;
+ delete service_;
+ backend_impl_ = NULL;
+ service_ = NULL;
+ io_message_loop_ = NULL;
+
+ // Just in case the main thread is waiting on it.
+ backend_proxy_->SignalEvent();
+}
+
+WebApplicationCacheHost* SimpleAppCacheSystem::CreateCacheHostForWebKit(
+ WebApplicationCacheHostClient* client) {
+ if (!is_initailized_on_ui_thread())
+ return NULL;
+
+ DCHECK(is_ui_thread());
+
+ // The IO thread needs to be running for this system to work.
+ SimpleResourceLoaderBridge::EnsureIOThread();
+
+ if (!is_initialized())
+ return NULL;
+ return new WebApplicationCacheHostImpl(client, backend_proxy_.get());
+}
+
+void SimpleAppCacheSystem::SetExtraRequestBits(
+ net::URLRequest* request, int host_id, ResourceType::Type resource_type) {
+ if (is_initialized()) {
+ DCHECK(is_io_thread());
+ AppCacheInterceptor::SetExtraRequestInfo(
+ request, service_, kSingleProcessId, host_id, resource_type);
+ }
+}
+
+void SimpleAppCacheSystem::GetExtraResponseBits(
+ net::URLRequest* request, int64* cache_id, GURL* manifest_url) {
+ if (is_initialized()) {
+ DCHECK(is_io_thread());
+ AppCacheInterceptor::GetExtraResponseInfo(
+ request, cache_id, manifest_url);
+ }
+}
diff --git a/webkit/support/simple_appcache_system.h b/webkit/support/simple_appcache_system.h
new file mode 100644
index 0000000..c07a52f
--- /dev/null
+++ b/webkit/support/simple_appcache_system.h
@@ -0,0 +1,136 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef WEBKIT_SUPPORT_SIMPLE_APPCACHE_SYSTEM_H_
+#define WEBKIT_SUPPORT_SIMPLE_APPCACHE_SYSTEM_H_
+
+#include "base/files/file_path.h"
+#include "base/message_loop.h"
+#include "base/threading/thread.h"
+#include "webkit/appcache/appcache_backend_impl.h"
+#include "webkit/appcache/appcache_frontend_impl.h"
+#include "webkit/appcache/appcache_service.h"
+#include "webkit/glue/resource_type.h"
+
+namespace WebKit {
+class WebApplicationCacheHost;
+class WebApplicationCacheHostClient;
+}
+class SimpleBackendProxy;
+class SimpleFrontendProxy;
+
+namespace net {
+class URLRequest;
+class URLRequestContext;
+} // namespace net
+
+// A class that composes the constituent parts of an appcache system
+// together for use in a single process with two relavant threads,
+// a UI thread on which webkit runs and an IO thread on which URLRequests
+// are handled. This class conspires with SimpleResourceLoaderBridge to
+// retrieve resources from the appcache.
+class SimpleAppCacheSystem {
+ public:
+ // Should be instanced somewhere in main(). If not instanced, the public
+ // static methods are all safe no-ops.
+ SimpleAppCacheSystem();
+ virtual ~SimpleAppCacheSystem();
+
+ // One-time main UI thread initialization.
+ static void InitializeOnUIThread(const base::FilePath& cache_directory) {
+ if (instance_)
+ instance_->InitOnUIThread(cache_directory);
+ }
+
+ // Called by SimpleResourceLoaderBridge's IOThread class.
+ // Per IO thread initialization. Only one IO thread can exist
+ // at a time, but after IO thread termination a new one can be
+ // started on which this method should be called. The instance
+ // is assumed to outlive the IO thread.
+ static void InitializeOnIOThread(net::URLRequestContext* request_context) {
+ if (instance_)
+ instance_->InitOnIOThread(request_context);
+ }
+
+ static void CleanupOnIOThread() {
+ if (instance_)
+ instance_->CleanupIOThread();
+ }
+
+ // Called by TestShellWebKitInit to manufacture a 'host' for webcore.
+ static WebKit::WebApplicationCacheHost* CreateApplicationCacheHost(
+ WebKit::WebApplicationCacheHostClient* client) {
+ return instance_ ? instance_->CreateCacheHostForWebKit(client) : NULL;
+ }
+
+ // Called by SimpleResourceLoaderBridge to hook into resource loads.
+ static void SetExtraRequestInfo(net::URLRequest* request,
+ int host_id,
+ ResourceType::Type resource_type) {
+ if (instance_)
+ instance_->SetExtraRequestBits(request, host_id, resource_type);
+ }
+
+ // Called by SimpleResourceLoaderBridge extract extra response bits.
+ static void GetExtraResponseInfo(net::URLRequest* request,
+ int64* cache_id,
+ GURL* manifest_url) {
+ if (instance_)
+ instance_->GetExtraResponseBits(request, cache_id, manifest_url);
+ }
+
+ private:
+ friend class SimpleBackendProxy;
+ friend class SimpleFrontendProxy;
+
+ // Instance methods called by our static public methods
+ void InitOnUIThread(const base::FilePath& cache_directory);
+ void InitOnIOThread(net::URLRequestContext* request_context);
+ void CleanupIOThread();
+ WebKit::WebApplicationCacheHost* CreateCacheHostForWebKit(
+ WebKit::WebApplicationCacheHostClient* client);
+ void SetExtraRequestBits(net::URLRequest* request,
+ int host_id,
+ ResourceType::Type resource_type);
+ void GetExtraResponseBits(net::URLRequest* request,
+ int64* cache_id,
+ GURL* manifest_url);
+
+ // Helpers
+ base::MessageLoop* io_message_loop() { return io_message_loop_; }
+ base::MessageLoop* ui_message_loop() { return ui_message_loop_; }
+ bool is_io_thread() {
+ return base::MessageLoop::current() == io_message_loop_;
+ }
+ bool is_ui_thread() {
+ return base::MessageLoop::current() == ui_message_loop_;
+ }
+ bool is_initialized() {
+ return io_message_loop_ && is_initailized_on_ui_thread();
+ }
+ bool is_initailized_on_ui_thread() {
+ return ui_message_loop_ ? true : false;
+ }
+
+ base::FilePath cache_directory_;
+ base::MessageLoop* io_message_loop_;
+ base::MessageLoop* ui_message_loop_;
+ scoped_refptr<SimpleBackendProxy> backend_proxy_;
+ scoped_refptr<SimpleFrontendProxy> frontend_proxy_;
+ appcache::AppCacheFrontendImpl frontend_impl_;
+
+ // Created and used only on the IO thread, these do
+ // not survive IO thread termination. If a new IO thread
+ // is started new instances will be created.
+ appcache::AppCacheBackendImpl* backend_impl_;
+ appcache::AppCacheService* service_;
+
+ // We start a thread for use as the DB thread.
+ base::Thread db_thread_;
+
+ // A low-tech singleton.
+ static SimpleAppCacheSystem* instance_;
+};
+
+#endif // WEBKIT_SUPPORT_SIMPLE_APPCACHE_SYSTEM_H_
diff --git a/webkit/support/simple_clipboard_impl.cc b/webkit/support/simple_clipboard_impl.cc
new file mode 100644
index 0000000..ac10492
--- /dev/null
+++ b/webkit/support/simple_clipboard_impl.cc
@@ -0,0 +1,118 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "webkit/support/simple_clipboard_impl.h"
+
+#include <string>
+
+#include "base/lazy_instance.h"
+#include "base/stl_util.h"
+#include "base/string16.h"
+#include "googleurl/src/gurl.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "third_party/zlib/zlib.h"
+#include "ui/base/clipboard/clipboard.h"
+#include "ui/gfx/codec/png_codec.h"
+#include "ui/gfx/size.h"
+#include "webkit/glue/webkit_glue.h"
+
+namespace {
+
+} // anonymous namespace
+
+SimpleClipboardClient::SimpleClipboardClient() {
+}
+
+SimpleClipboardClient::~SimpleClipboardClient() {
+}
+
+
+ui::Clipboard* SimpleClipboardClient::GetClipboard() {
+ return ui::Clipboard::GetForCurrentThread();
+}
+
+uint64 SimpleClipboardClient::GetSequenceNumber(ui::Clipboard::Buffer buffer) {
+ return GetClipboard()->GetSequenceNumber(buffer);
+}
+
+bool SimpleClipboardClient::IsFormatAvailable(
+ const ui::Clipboard::FormatType& format,
+ ui::Clipboard::Buffer buffer) {
+ return GetClipboard()->IsFormatAvailable(format, buffer);
+}
+
+void SimpleClipboardClient::Clear(ui::Clipboard::Buffer buffer) {
+ GetClipboard()->Clear(buffer);
+}
+
+void SimpleClipboardClient::ReadAvailableTypes(
+ ui::Clipboard::Buffer buffer,
+ std::vector<base::string16>* types,
+ bool* contains_filenames) {
+ return GetClipboard()->ReadAvailableTypes(buffer, types, contains_filenames);
+}
+
+void SimpleClipboardClient::ReadText(ui::Clipboard::Buffer buffer,
+ base::string16* result) {
+ GetClipboard()->ReadText(buffer, result);
+}
+
+void SimpleClipboardClient::ReadAsciiText(ui::Clipboard::Buffer buffer,
+ std::string* result) {
+ GetClipboard()->ReadAsciiText(buffer, result);
+}
+
+void SimpleClipboardClient::ReadHTML(ui::Clipboard::Buffer buffer,
+ base::string16* markup,
+ GURL* url, uint32* fragment_start,
+ uint32* fragment_end) {
+ std::string url_str;
+ GetClipboard()->ReadHTML(buffer, markup, url ? &url_str : NULL,
+ fragment_start, fragment_end);
+ if (url)
+ *url = GURL(url_str);
+}
+
+void SimpleClipboardClient::ReadRTF(ui::Clipboard::Buffer buffer,
+ std::string* result) {
+ GetClipboard()->ReadRTF(buffer, result);
+}
+
+void SimpleClipboardClient::ReadImage(ui::Clipboard::Buffer buffer,
+ std::string* data) {
+ SkBitmap bitmap = GetClipboard()->ReadImage(buffer);
+ if (bitmap.isNull())
+ return;
+
+ std::vector<unsigned char> png_data;
+ SkAutoLockPixels lock(bitmap);
+ if (gfx::PNGCodec::EncodeWithCompressionLevel(
+ static_cast<const unsigned char*>(bitmap.getPixels()),
+ gfx::PNGCodec::FORMAT_BGRA,
+ gfx::Size(bitmap.width(), bitmap.height()),
+ bitmap.rowBytes(),
+ false,
+ std::vector<gfx::PNGCodec::Comment>(),
+ Z_BEST_SPEED,
+ &png_data)) {
+ data->assign(reinterpret_cast<char*>(vector_as_array(&png_data)),
+ png_data.size());
+ }
+}
+
+void SimpleClipboardClient::ReadCustomData(ui::Clipboard::Buffer buffer,
+ const base::string16& type,
+ base::string16* data) {
+ GetClipboard()->ReadCustomData(buffer, type, data);
+}
+
+void SimpleClipboardClient::ReadData(const ui::Clipboard::FormatType& format,
+ std::string* data) {
+ GetClipboard()->ReadData(format, data);
+}
+
+webkit_glue::ClipboardClient::WriteContext*
+SimpleClipboardClient::CreateWriteContext() {
+ return NULL;
+}
diff --git a/webkit/support/simple_clipboard_impl.h b/webkit/support/simple_clipboard_impl.h
new file mode 100644
index 0000000..0d3d146
--- /dev/null
+++ b/webkit/support/simple_clipboard_impl.h
@@ -0,0 +1,43 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef WEBKIT_SUPPORT_SIMPLE_CLIPBOARD_IMPL_H_
+#define WEBKIT_SUPPORT_SIMPLE_CLIPBOARD_IMPL_H_
+
+#include "base/compiler_specific.h"
+#include "webkit/glue/clipboard_client.h"
+
+class SimpleClipboardClient : public webkit_glue::ClipboardClient {
+ public:
+ SimpleClipboardClient();
+ virtual ~SimpleClipboardClient();
+
+ virtual ui::Clipboard* GetClipboard() OVERRIDE;
+ virtual uint64 GetSequenceNumber(ui::Clipboard::Buffer buffer) OVERRIDE;
+ virtual bool IsFormatAvailable(const ui::Clipboard::FormatType& format,
+ ui::Clipboard::Buffer buffer) OVERRIDE;
+ virtual void Clear(ui::Clipboard::Buffer buffer) OVERRIDE;
+ virtual void ReadAvailableTypes(ui::Clipboard::Buffer buffer,
+ std::vector<base::string16>* types,
+ bool* contains_filenames) OVERRIDE;
+ virtual void ReadText(ui::Clipboard::Buffer buffer,
+ base::string16* result) OVERRIDE;
+ virtual void ReadAsciiText(ui::Clipboard::Buffer buffer,
+ std::string* result) OVERRIDE;
+ virtual void ReadHTML(ui::Clipboard::Buffer buffer, base::string16* markup,
+ GURL* url, uint32* fragment_start,
+ uint32* fragment_end) OVERRIDE;
+ virtual void ReadRTF(ui::Clipboard::Buffer buffer,
+ std::string* result) OVERRIDE;
+ virtual void ReadImage(ui::Clipboard::Buffer buffer,
+ std::string* data) OVERRIDE;
+ virtual void ReadCustomData(ui::Clipboard::Buffer buffer,
+ const base::string16& type,
+ base::string16* data) OVERRIDE;
+ virtual void ReadData(const ui::Clipboard::FormatType& format,
+ std::string* data) OVERRIDE;
+ virtual WriteContext* CreateWriteContext() OVERRIDE;
+};
+
+#endif // WEBKIT_SUPPORT_SIMPLE_CLIPBOARD_IMPL_H_
diff --git a/webkit/support/simple_dom_storage_system.cc b/webkit/support/simple_dom_storage_system.cc
new file mode 100644
index 0000000..34762ac
--- /dev/null
+++ b/webkit/support/simple_dom_storage_system.cc
@@ -0,0 +1,286 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "webkit/support/simple_dom_storage_system.h"
+
+#include "base/auto_reset.h"
+#include "googleurl/src/gurl.h"
+#include "third_party/WebKit/public/platform/WebStorageArea.h"
+#include "third_party/WebKit/public/platform/WebStorageNamespace.h"
+#include "third_party/WebKit/public/platform/WebURL.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebStorageEventDispatcher.h"
+#include "webkit/browser/database/database_util.h"
+#include "webkit/browser/dom_storage/dom_storage_area.h"
+#include "webkit/browser/dom_storage/dom_storage_host.h"
+
+using dom_storage::DomStorageContext;
+using dom_storage::DomStorageHost;
+using dom_storage::DomStorageSession;
+using webkit_database::DatabaseUtil;
+using WebKit::WebStorageArea;
+using WebKit::WebStorageNamespace;
+using WebKit::WebStorageEventDispatcher;
+using WebKit::WebString;
+using WebKit::WebURL;
+
+namespace {
+const int kInvalidNamespaceId = -1;
+}
+
+class SimpleDomStorageSystem::NamespaceImpl : public WebStorageNamespace {
+ public:
+ explicit NamespaceImpl(const base::WeakPtr<SimpleDomStorageSystem>& parent);
+ NamespaceImpl(const base::WeakPtr<SimpleDomStorageSystem>& parent,
+ int session_namespace_id);
+ virtual ~NamespaceImpl();
+ virtual WebStorageArea* createStorageArea(const WebString& origin) OVERRIDE;
+ virtual WebStorageNamespace* copy() OVERRIDE;
+ virtual bool isSameNamespace(const WebStorageNamespace&) const OVERRIDE;
+
+ private:
+ DomStorageContext* Context() {
+ if (!parent_.get())
+ return NULL;
+ return parent_->context_.get();
+ }
+
+ base::WeakPtr<SimpleDomStorageSystem> parent_;
+ int namespace_id_;
+};
+
+class SimpleDomStorageSystem::AreaImpl : public WebStorageArea {
+ public:
+ AreaImpl(const base::WeakPtr<SimpleDomStorageSystem>& parent,
+ int namespace_id, const GURL& origin);
+ virtual ~AreaImpl();
+ virtual unsigned length() OVERRIDE;
+ virtual WebString key(unsigned index) OVERRIDE;
+ virtual WebString getItem(const WebString& key) OVERRIDE;
+ virtual void setItem(const WebString& key, const WebString& newValue,
+ const WebURL& pageUrl, Result&) OVERRIDE;
+ virtual void removeItem(const WebString& key,
+ const WebURL& pageUrl) OVERRIDE;
+ virtual void clear(const WebURL& pageUrl) OVERRIDE;
+
+ private:
+ DomStorageHost* Host() {
+ if (!parent_.get())
+ return NULL;
+ return parent_->host_.get();
+ }
+
+ base::WeakPtr<SimpleDomStorageSystem> parent_;
+ int connection_id_;
+};
+
+// NamespaceImpl -----------------------------
+
+SimpleDomStorageSystem::NamespaceImpl::NamespaceImpl(
+ const base::WeakPtr<SimpleDomStorageSystem>& parent)
+ : parent_(parent),
+ namespace_id_(dom_storage::kLocalStorageNamespaceId) {
+}
+
+SimpleDomStorageSystem::NamespaceImpl::NamespaceImpl(
+ const base::WeakPtr<SimpleDomStorageSystem>& parent,
+ int session_namespace_id)
+ : parent_(parent),
+ namespace_id_(session_namespace_id) {
+}
+
+SimpleDomStorageSystem::NamespaceImpl::~NamespaceImpl() {
+ if (namespace_id_ == dom_storage::kLocalStorageNamespaceId ||
+ namespace_id_ == kInvalidNamespaceId || !Context()) {
+ return;
+ }
+ Context()->DeleteSessionNamespace(namespace_id_, false);
+}
+
+WebStorageArea* SimpleDomStorageSystem::NamespaceImpl::createStorageArea(
+ const WebString& origin) {
+ return new AreaImpl(parent_, namespace_id_, GURL(origin));
+}
+
+WebStorageNamespace* SimpleDomStorageSystem::NamespaceImpl::copy() {
+ DCHECK_NE(dom_storage::kLocalStorageNamespaceId, namespace_id_);
+ int new_id = kInvalidNamespaceId;
+ if (Context()) {
+ new_id = Context()->AllocateSessionId();
+ Context()->CloneSessionNamespace(namespace_id_, new_id, std::string());
+ }
+ return new NamespaceImpl(parent_, new_id);
+}
+
+bool SimpleDomStorageSystem::NamespaceImpl::isSameNamespace(
+ const WebStorageNamespace& other) const {
+ const NamespaceImpl* other_impl = static_cast<const NamespaceImpl*>(&other);
+ return namespace_id_ == other_impl->namespace_id_;
+}
+
+// AreaImpl -----------------------------
+
+SimpleDomStorageSystem::AreaImpl::AreaImpl(
+ const base::WeakPtr<SimpleDomStorageSystem>& parent,
+ int namespace_id, const GURL& origin)
+ : parent_(parent),
+ connection_id_(0) {
+ if (Host()) {
+ connection_id_ = (parent_->next_connection_id_)++;
+ Host()->OpenStorageArea(connection_id_, namespace_id, origin);
+ }
+}
+
+SimpleDomStorageSystem::AreaImpl::~AreaImpl() {
+ if (Host())
+ Host()->CloseStorageArea(connection_id_);
+}
+
+unsigned SimpleDomStorageSystem::AreaImpl::length() {
+ if (Host())
+ return Host()->GetAreaLength(connection_id_);
+ return 0;
+}
+
+WebString SimpleDomStorageSystem::AreaImpl::key(unsigned index) {
+ if (Host())
+ return Host()->GetAreaKey(connection_id_, index);
+ return NullableString16(true);
+}
+
+WebString SimpleDomStorageSystem::AreaImpl::getItem(const WebString& key) {
+ if (Host())
+ return Host()->GetAreaItem(connection_id_, key);
+ return NullableString16(true);
+}
+
+void SimpleDomStorageSystem::AreaImpl::setItem(
+ const WebString& key, const WebString& newValue,
+ const WebURL& pageUrl, Result& result) {
+ result = ResultBlockedByQuota;
+ if (!Host())
+ return;
+
+ base::AutoReset<AreaImpl*> auto_reset(&parent_->area_being_processed_, this);
+ NullableString16 unused;
+ if (!Host()->SetAreaItem(connection_id_, key, newValue, pageUrl,
+ &unused))
+ return;
+
+ result = ResultOK;
+}
+
+void SimpleDomStorageSystem::AreaImpl::removeItem(
+ const WebString& key, const WebURL& pageUrl) {
+ if (!Host())
+ return;
+
+ base::AutoReset<AreaImpl*> auto_reset(&parent_->area_being_processed_, this);
+ base::string16 notused;
+ Host()->RemoveAreaItem(connection_id_, key, pageUrl, &notused);
+}
+
+void SimpleDomStorageSystem::AreaImpl::clear(const WebURL& pageUrl) {
+ if (!Host())
+ return;
+
+ base::AutoReset<AreaImpl*> auto_reset(&parent_->area_being_processed_, this);
+ Host()->ClearArea(connection_id_, pageUrl);
+}
+
+// SimpleDomStorageSystem -----------------------------
+
+SimpleDomStorageSystem* SimpleDomStorageSystem::g_instance_;
+
+SimpleDomStorageSystem::SimpleDomStorageSystem()
+ : weak_factory_(this),
+ context_(new DomStorageContext(base::FilePath(),
+ base::FilePath(),
+ NULL,
+ NULL)),
+ host_(new DomStorageHost(context_.get())),
+ area_being_processed_(NULL),
+ next_connection_id_(1) {
+ DCHECK(!g_instance_);
+ g_instance_ = this;
+ context_->AddEventObserver(this);
+}
+
+SimpleDomStorageSystem::~SimpleDomStorageSystem() {
+ g_instance_ = NULL;
+ host_.reset();
+ context_->RemoveEventObserver(this);
+}
+
+WebStorageNamespace* SimpleDomStorageSystem::CreateLocalStorageNamespace() {
+ return new NamespaceImpl(weak_factory_.GetWeakPtr());
+}
+
+WebStorageNamespace* SimpleDomStorageSystem::CreateSessionStorageNamespace() {
+ int id = context_->AllocateSessionId();
+ context_->CreateSessionNamespace(id, std::string());
+ return new NamespaceImpl(weak_factory_.GetWeakPtr(), id);
+}
+
+void SimpleDomStorageSystem::OnDomStorageItemSet(
+ const dom_storage::DomStorageArea* area,
+ const base::string16& key,
+ const base::string16& new_value,
+ const NullableString16& old_value,
+ const GURL& page_url) {
+ DispatchDomStorageEvent(area, page_url,
+ NullableString16(key, false),
+ NullableString16(new_value, false),
+ old_value);
+}
+
+void SimpleDomStorageSystem::OnDomStorageItemRemoved(
+ const dom_storage::DomStorageArea* area,
+ const base::string16& key,
+ const base::string16& old_value,
+ const GURL& page_url) {
+ DispatchDomStorageEvent(area, page_url,
+ NullableString16(key, false),
+ NullableString16(true),
+ NullableString16(old_value, false));
+}
+
+void SimpleDomStorageSystem::OnDomStorageAreaCleared(
+ const dom_storage::DomStorageArea* area,
+ const GURL& page_url) {
+ DispatchDomStorageEvent(area, page_url,
+ NullableString16(true),
+ NullableString16(true),
+ NullableString16(true));
+}
+
+void SimpleDomStorageSystem::DispatchDomStorageEvent(
+ const dom_storage::DomStorageArea* area,
+ const GURL& page_url,
+ const NullableString16& key,
+ const NullableString16& new_value,
+ const NullableString16& old_value) {
+ DCHECK(area_being_processed_);
+ if (area->namespace_id() == dom_storage::kLocalStorageNamespaceId) {
+ WebStorageEventDispatcher::dispatchLocalStorageEvent(
+ key,
+ old_value,
+ new_value,
+ area->origin(),
+ page_url,
+ area_being_processed_,
+ true /* originatedInProcess */);
+ } else {
+ NamespaceImpl session_namespace_for_event_dispatch(
+ base::WeakPtr<SimpleDomStorageSystem>(), area->namespace_id());
+ WebStorageEventDispatcher::dispatchSessionStorageEvent(
+ key,
+ old_value,
+ new_value,
+ area->origin(),
+ page_url,
+ session_namespace_for_event_dispatch,
+ area_being_processed_,
+ true /* originatedInProcess */);
+ }
+}
diff --git a/webkit/support/simple_dom_storage_system.h b/webkit/support/simple_dom_storage_system.h
new file mode 100644
index 0000000..71824a9
--- /dev/null
+++ b/webkit/support/simple_dom_storage_system.h
@@ -0,0 +1,79 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef WEBKIT_SUPPORT_SIMPLE_DOM_STORAGE_SYSTEM_H_
+#define WEBKIT_SUPPORT_SIMPLE_DOM_STORAGE_SYSTEM_H_
+
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
+#include "webkit/browser/dom_storage/dom_storage_context.h"
+
+namespace dom_storage {
+class DomStorageHost;
+}
+namespace WebKit {
+class WebStorageNamespace;
+}
+
+// Class that composes dom_storage classes together for use
+// in simple single process environments like test_shell and DRT.
+class SimpleDomStorageSystem
+ : public dom_storage::DomStorageContext::EventObserver {
+ public:
+ static SimpleDomStorageSystem& instance() { return *g_instance_; }
+
+ SimpleDomStorageSystem();
+ virtual ~SimpleDomStorageSystem();
+
+ // The Create<<>> calls are bound to WebKit api that the embedder
+ // is responsible for implementing. These factories are called strictly
+ // on the 'main' webkit thread. Ditto the methods on the returned
+ // objects. SimplDomStorageSystem manufactures implementations of the
+ // WebStorageNamespace and WebStorageArea interfaces that ultimately
+ // plumb Get, Set, Remove, and Clear javascript calls to the dom_storage
+ // classes. The caller (webkit/webcore) takes ownership of the returned
+ // instances and will delete them when done.
+ WebKit::WebStorageNamespace* CreateLocalStorageNamespace();
+ WebKit::WebStorageNamespace* CreateSessionStorageNamespace();
+
+ private:
+ // Inner classes that implement the WebKit WebStorageNamespace and
+ // WebStorageArea interfaces in terms of dom_storage classes.
+ class NamespaceImpl;
+ class AreaImpl;
+
+ // DomStorageContext::EventObserver implementation which
+ // calls into webkit/webcore to dispatch events.
+ virtual void OnDomStorageItemSet(
+ const dom_storage::DomStorageArea* area,
+ const base::string16& key,
+ const base::string16& new_value,
+ const NullableString16& old_value,
+ const GURL& page_url) OVERRIDE;
+ virtual void OnDomStorageItemRemoved(
+ const dom_storage::DomStorageArea* area,
+ const base::string16& key,
+ const base::string16& old_value,
+ const GURL& page_url) OVERRIDE;
+ virtual void OnDomStorageAreaCleared(
+ const dom_storage::DomStorageArea* area,
+ const GURL& page_url) OVERRIDE;
+
+ void DispatchDomStorageEvent(
+ const dom_storage::DomStorageArea* area,
+ const GURL& page_url,
+ const NullableString16& key,
+ const NullableString16& new_value,
+ const NullableString16& old_value);
+
+ base::WeakPtrFactory<SimpleDomStorageSystem> weak_factory_;
+ scoped_refptr<dom_storage::DomStorageContext> context_;
+ scoped_ptr<dom_storage::DomStorageHost> host_;
+ AreaImpl* area_being_processed_;
+ int next_connection_id_;
+
+ static SimpleDomStorageSystem* g_instance_;
+};
+
+#endif // WEBKIT_SUPPORT_SIMPLE_DOM_STORAGE_SYSTEM_H_
diff --git a/webkit/support/simple_file_system.cc b/webkit/support/simple_file_system.cc
new file mode 100644
index 0000000..b7e9ef3
--- /dev/null
+++ b/webkit/support/simple_file_system.cc
@@ -0,0 +1,410 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "webkit/support/simple_file_system.h"
+
+#include "base/bind.h"
+#include "base/files/file_path.h"
+#include "base/message_loop.h"
+#include "base/message_loop_proxy.h"
+#include "base/time.h"
+#include "base/utf_string_conversions.h"
+#include "googleurl/src/gurl.h"
+#include "net/base/mime_util.h"
+#include "third_party/WebKit/public/platform/WebFileInfo.h"
+#include "third_party/WebKit/public/platform/WebURL.h"
+#include "third_party/WebKit/public/platform/WebVector.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebFileSystemCallbacks.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebFileSystemEntry.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
+#include "webkit/base/file_path_string_conversions.h"
+#include "webkit/browser/blob/blob_storage_controller.h"
+#include "webkit/browser/fileapi/file_permission_policy.h"
+#include "webkit/browser/fileapi/file_system_mount_point_provider.h"
+#include "webkit/browser/fileapi/file_system_url.h"
+#include "webkit/browser/fileapi/mock_file_system_context.h"
+#include "webkit/common/fileapi/directory_entry.h"
+#include "webkit/common/fileapi/file_system_util.h"
+#include "webkit/support/simple_file_writer.h"
+
+using base::WeakPtr;
+
+using WebKit::WebFileInfo;
+using WebKit::WebFileSystem;
+using WebKit::WebFileSystemCallbacks;
+using WebKit::WebFileSystemEntry;
+using WebKit::WebFileWriter;
+using WebKit::WebFileWriterClient;
+using WebKit::WebFrame;
+using WebKit::WebString;
+using WebKit::WebURL;
+using WebKit::WebVector;
+
+using webkit_blob::BlobData;
+using webkit_blob::BlobStorageController;
+using fileapi::DirectoryEntry;
+using fileapi::FileSystemContext;
+using fileapi::FileSystemOperation;
+using fileapi::FileSystemTaskRunners;
+using fileapi::FileSystemURL;
+
+namespace {
+base::MessageLoop* g_io_thread;
+webkit_blob::BlobStorageController* g_blob_storage_controller;
+
+void RegisterBlob(const GURL& blob_url, const base::FilePath& file_path) {
+ DCHECK(g_blob_storage_controller);
+
+ base::FilePath::StringType extension = file_path.Extension();
+ if (!extension.empty())
+ extension = extension.substr(1); // Strip leading ".".
+
+ // This may fail, but then we'll be just setting the empty mime type.
+ std::string mime_type;
+ net::GetWellKnownMimeTypeFromExtension(extension, &mime_type);
+
+ BlobData::Item item;
+ item.SetToFilePathRange(file_path, 0, -1, base::Time());
+ g_blob_storage_controller->StartBuildingBlob(blob_url);
+ g_blob_storage_controller->AppendBlobDataItem(blob_url, item);
+ g_blob_storage_controller->FinishBuildingBlob(blob_url, mime_type);
+}
+
+} // namespace
+
+SimpleFileSystem::SimpleFileSystem() {
+ if (file_system_dir_.CreateUniqueTempDir()) {
+ file_system_context_ = fileapi::CreateFileSystemContextForTesting(
+ NULL /* quota manager */,
+ file_system_dir_.path());
+ } else {
+ LOG(WARNING) << "Failed to create a temp dir for the filesystem."
+ "FileSystem feature will be disabled.";
+ }
+}
+
+SimpleFileSystem::~SimpleFileSystem() {
+}
+
+void SimpleFileSystem::OpenFileSystem(
+ WebFrame* frame,
+ WebKit::WebFileSystemType type,
+ long long, bool create,
+ WebFileSystemCallbacks* callbacks) {
+ if (!frame || !file_system_context_.get()) {
+ // The FileSystem temp directory was not initialized successfully.
+ callbacks->didFail(WebKit::WebFileErrorSecurity);
+ return;
+ }
+
+ fileapi::OpenFileSystemMode mode =
+ create ? fileapi::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT
+ : fileapi::OPEN_FILE_SYSTEM_FAIL_IF_NONEXISTENT;
+ GURL origin_url(frame->document().securityOrigin().toString());
+ file_system_context_->OpenFileSystem(
+ origin_url, static_cast<fileapi::FileSystemType>(type), mode,
+ OpenFileSystemHandler(callbacks));
+}
+
+void SimpleFileSystem::DeleteFileSystem(
+ WebFrame* frame,
+ WebKit::WebFileSystemType type,
+ WebFileSystemCallbacks* callbacks) {
+ if (!frame || !file_system_context_.get()) {
+ callbacks->didFail(WebKit::WebFileErrorSecurity);
+ return;
+ }
+
+ GURL origin_url(frame->document().securityOrigin().toString());
+ file_system_context_->DeleteFileSystem(
+ origin_url, static_cast<fileapi::FileSystemType>(type),
+ DeleteFileSystemHandler(callbacks));
+}
+
+void SimpleFileSystem::move(
+ const WebURL& src_path,
+ const WebURL& dest_path, WebFileSystemCallbacks* callbacks) {
+ FileSystemURL src_url(file_system_context()->CrackURL(src_path));
+ FileSystemURL dest_url(file_system_context()->CrackURL(dest_path));
+ if (!HasFilePermission(src_url, fileapi::kWriteFilePermissions) ||
+ !HasFilePermission(dest_url, fileapi::kCreateFilePermissions)) {
+ callbacks->didFail(WebKit::WebFileErrorSecurity);
+ return;
+ }
+ GetNewOperation(src_url)->Move(src_url, dest_url,
+ FinishHandler(callbacks));
+}
+
+void SimpleFileSystem::copy(
+ const WebURL& src_path, const WebURL& dest_path,
+ WebFileSystemCallbacks* callbacks) {
+ FileSystemURL src_url(file_system_context()->CrackURL(src_path));
+ FileSystemURL dest_url(file_system_context()->CrackURL(dest_path));
+ if (!HasFilePermission(src_url, fileapi::kReadFilePermissions) ||
+ !HasFilePermission(dest_url, fileapi::kCreateFilePermissions)) {
+ callbacks->didFail(WebKit::WebFileErrorSecurity);
+ return;
+ }
+ GetNewOperation(src_url)->Copy(src_url, dest_url,
+ FinishHandler(callbacks));
+}
+
+void SimpleFileSystem::remove(
+ const WebURL& path, WebFileSystemCallbacks* callbacks) {
+ FileSystemURL url(file_system_context()->CrackURL(path));
+ if (!HasFilePermission(url, fileapi::kWriteFilePermissions)) {
+ callbacks->didFail(WebKit::WebFileErrorSecurity);
+ return;
+ }
+ GetNewOperation(url)->Remove(url, false /* recursive */,
+ FinishHandler(callbacks));
+}
+
+void SimpleFileSystem::removeRecursively(
+ const WebURL& path, WebFileSystemCallbacks* callbacks) {
+ FileSystemURL url(file_system_context()->CrackURL(path));
+ if (!HasFilePermission(url, fileapi::kWriteFilePermissions)) {
+ callbacks->didFail(WebKit::WebFileErrorSecurity);
+ return;
+ }
+ GetNewOperation(url)->Remove(url, true /* recursive */,
+ FinishHandler(callbacks));
+}
+
+void SimpleFileSystem::readMetadata(
+ const WebURL& path, WebFileSystemCallbacks* callbacks) {
+ FileSystemURL url(file_system_context()->CrackURL(path));
+ if (!HasFilePermission(url, fileapi::kReadFilePermissions)) {
+ callbacks->didFail(WebKit::WebFileErrorSecurity);
+ return;
+ }
+ GetNewOperation(url)->GetMetadata(url, GetMetadataHandler(callbacks));
+}
+
+void SimpleFileSystem::createFile(
+ const WebURL& path, bool exclusive, WebFileSystemCallbacks* callbacks) {
+ FileSystemURL url(file_system_context()->CrackURL(path));
+ if (!HasFilePermission(url, fileapi::kCreateFilePermissions)) {
+ callbacks->didFail(WebKit::WebFileErrorSecurity);
+ return;
+ }
+ GetNewOperation(url)->CreateFile(url, exclusive, FinishHandler(callbacks));
+}
+
+void SimpleFileSystem::createDirectory(
+ const WebURL& path, bool exclusive, WebFileSystemCallbacks* callbacks) {
+ FileSystemURL url(file_system_context()->CrackURL(path));
+ if (!HasFilePermission(url, fileapi::kCreateFilePermissions)) {
+ callbacks->didFail(WebKit::WebFileErrorSecurity);
+ return;
+ }
+ GetNewOperation(url)->CreateDirectory(url, exclusive, false,
+ FinishHandler(callbacks));
+}
+
+void SimpleFileSystem::fileExists(
+ const WebURL& path, WebFileSystemCallbacks* callbacks) {
+ FileSystemURL url(file_system_context()->CrackURL(path));
+ if (!HasFilePermission(url, fileapi::kReadFilePermissions)) {
+ callbacks->didFail(WebKit::WebFileErrorSecurity);
+ return;
+ }
+ GetNewOperation(url)->FileExists(url, FinishHandler(callbacks));
+}
+
+void SimpleFileSystem::directoryExists(
+ const WebURL& path, WebFileSystemCallbacks* callbacks) {
+ FileSystemURL url(file_system_context()->CrackURL(path));
+ if (!HasFilePermission(url, fileapi::kReadFilePermissions)) {
+ callbacks->didFail(WebKit::WebFileErrorSecurity);
+ return;
+ }
+ GetNewOperation(url)->DirectoryExists(url, FinishHandler(callbacks));
+}
+
+void SimpleFileSystem::readDirectory(
+ const WebURL& path, WebFileSystemCallbacks* callbacks) {
+ FileSystemURL url(file_system_context()->CrackURL(path));
+ if (!HasFilePermission(url, fileapi::kReadFilePermissions)) {
+ callbacks->didFail(WebKit::WebFileErrorSecurity);
+ return;
+ }
+ GetNewOperation(url)->ReadDirectory(url, ReadDirectoryHandler(callbacks));
+}
+
+WebFileWriter* SimpleFileSystem::createFileWriter(
+ const WebURL& path, WebFileWriterClient* client) {
+ return new SimpleFileWriter(path, client, file_system_context_.get());
+}
+
+void SimpleFileSystem::createSnapshotFileAndReadMetadata(
+ const WebURL& path,
+ WebFileSystemCallbacks* callbacks) {
+ FileSystemURL url(file_system_context()->CrackURL(path));
+ if (!HasFilePermission(url, fileapi::kReadFilePermissions)) {
+ callbacks->didFail(WebKit::WebFileErrorSecurity);
+ return;
+ }
+ GetNewOperation(url)->CreateSnapshotFile(
+ url, SnapshotFileHandler(callbacks));
+}
+
+// static
+void SimpleFileSystem::InitializeOnIOThread(
+ webkit_blob::BlobStorageController* blob_storage_controller) {
+ g_io_thread = base::MessageLoop::current();
+ g_blob_storage_controller = blob_storage_controller;
+}
+
+// static
+void SimpleFileSystem::CleanupOnIOThread() {
+ g_io_thread = NULL;
+ g_blob_storage_controller = NULL;
+}
+
+bool SimpleFileSystem::HasFilePermission(
+ const fileapi::FileSystemURL& url, int permissions) {
+ if (!url.is_valid())
+ return false;
+ fileapi::FileSystemMountPointProvider* mount_point_provider =
+ file_system_context_->GetMountPointProvider(url.type());
+ DCHECK(mount_point_provider);
+ // In test_shell we don't perform further detailed security checks if it's
+ // not specifically forbidden by ALWAYS_DENY.
+ return (mount_point_provider->GetPermissionPolicy(url, permissions)
+ != fileapi::FILE_PERMISSION_ALWAYS_DENY);
+}
+
+FileSystemOperation* SimpleFileSystem::GetNewOperation(
+ const fileapi::FileSystemURL& url) {
+ return file_system_context_->CreateFileSystemOperation(url, NULL);
+}
+
+FileSystemOperation::StatusCallback
+SimpleFileSystem::FinishHandler(WebFileSystemCallbacks* callbacks) {
+ return base::Bind(&SimpleFileSystem::DidFinish,
+ AsWeakPtr(), base::Unretained(callbacks));
+}
+
+FileSystemOperation::ReadDirectoryCallback
+SimpleFileSystem::ReadDirectoryHandler(WebFileSystemCallbacks* callbacks) {
+ return base::Bind(&SimpleFileSystem::DidReadDirectory,
+ AsWeakPtr(), base::Unretained(callbacks));
+}
+
+FileSystemOperation::GetMetadataCallback
+SimpleFileSystem::GetMetadataHandler(WebFileSystemCallbacks* callbacks) {
+ return base::Bind(&SimpleFileSystem::DidGetMetadata,
+ AsWeakPtr(), base::Unretained(callbacks));
+}
+
+FileSystemContext::OpenFileSystemCallback
+SimpleFileSystem::OpenFileSystemHandler(WebFileSystemCallbacks* callbacks) {
+ return base::Bind(&SimpleFileSystem::DidOpenFileSystem,
+ AsWeakPtr(), base::Unretained(callbacks));
+}
+
+FileSystemContext::DeleteFileSystemCallback
+SimpleFileSystem::DeleteFileSystemHandler(WebFileSystemCallbacks* callbacks) {
+ return base::Bind(&SimpleFileSystem::DidDeleteFileSystem,
+ AsWeakPtr(), callbacks);
+}
+
+FileSystemOperation::SnapshotFileCallback
+SimpleFileSystem::SnapshotFileHandler(
+ WebFileSystemCallbacks* callbacks) {
+ return base::Bind(&SimpleFileSystem::DidCreateSnapshotFile,
+ AsWeakPtr(), base::Unretained(callbacks));
+}
+
+void SimpleFileSystem::DidFinish(WebFileSystemCallbacks* callbacks,
+ base::PlatformFileError result) {
+ if (result == base::PLATFORM_FILE_OK)
+ callbacks->didSucceed();
+ else
+ callbacks->didFail(fileapi::PlatformFileErrorToWebFileError(result));
+}
+
+void SimpleFileSystem::DidGetMetadata(WebFileSystemCallbacks* callbacks,
+ base::PlatformFileError result,
+ const base::PlatformFileInfo& info,
+ const base::FilePath& platform_path) {
+ if (result == base::PLATFORM_FILE_OK) {
+ WebFileInfo web_file_info;
+ web_file_info.length = info.size;
+ web_file_info.modificationTime = info.last_modified.ToDoubleT();
+ web_file_info.type = info.is_directory ?
+ WebFileInfo::TypeDirectory : WebFileInfo::TypeFile;
+ web_file_info.platformPath =
+ webkit_base::FilePathToWebString(platform_path);
+ callbacks->didReadMetadata(web_file_info);
+ } else {
+ callbacks->didFail(fileapi::PlatformFileErrorToWebFileError(result));
+ }
+}
+
+void SimpleFileSystem::DidReadDirectory(
+ WebFileSystemCallbacks* callbacks,
+ base::PlatformFileError result,
+ const std::vector<DirectoryEntry>& entries,
+ bool has_more) {
+ if (result == base::PLATFORM_FILE_OK) {
+ std::vector<WebFileSystemEntry> web_entries_vector;
+ for (std::vector<DirectoryEntry>::const_iterator it = entries.begin();
+ it != entries.end(); ++it) {
+ WebFileSystemEntry entry;
+ entry.name = webkit_base::FilePathStringToWebString(it->name);
+ entry.isDirectory = it->is_directory;
+ web_entries_vector.push_back(entry);
+ }
+ WebVector<WebKit::WebFileSystemEntry> web_entries = web_entries_vector;
+ callbacks->didReadDirectory(web_entries, has_more);
+ } else {
+ callbacks->didFail(fileapi::PlatformFileErrorToWebFileError(result));
+ }
+}
+
+void SimpleFileSystem::DidOpenFileSystem(
+ WebFileSystemCallbacks* callbacks,
+ base::PlatformFileError result,
+ const std::string& name, const GURL& root) {
+ if (result == base::PLATFORM_FILE_OK) {
+ if (!root.is_valid())
+ callbacks->didFail(WebKit::WebFileErrorSecurity);
+ else
+ callbacks->didOpenFileSystem(WebString::fromUTF8(name), root);
+ } else {
+ callbacks->didFail(fileapi::PlatformFileErrorToWebFileError(result));
+ }
+}
+
+void SimpleFileSystem::DidDeleteFileSystem(
+ WebFileSystemCallbacks* callbacks,
+ base::PlatformFileError result) {
+ if (result == base::PLATFORM_FILE_OK)
+ callbacks->didSucceed();
+ else
+ callbacks->didFail(fileapi::PlatformFileErrorToWebFileError(result));
+}
+
+void SimpleFileSystem::DidCreateSnapshotFile(
+ WebFileSystemCallbacks* callbacks,
+ base::PlatformFileError result,
+ const base::PlatformFileInfo& info,
+ const base::FilePath& platform_path,
+ const scoped_refptr<webkit_blob::ShareableFileReference>& file_ref) {
+ if (result == base::PLATFORM_FILE_OK) {
+ WebFileInfo web_file_info;
+ web_file_info.length = info.size;
+ web_file_info.modificationTime = info.last_modified.ToDoubleT();
+ web_file_info.type = info.is_directory ?
+ WebFileInfo::TypeDirectory : WebFileInfo::TypeFile;
+ web_file_info.platformPath =
+ webkit_base::FilePathToWebString(platform_path);
+ callbacks->didCreateSnapshotFile(web_file_info);
+ } else {
+ callbacks->didFail(fileapi::PlatformFileErrorToWebFileError(result));
+ }
+}
diff --git a/webkit/support/simple_file_system.h b/webkit/support/simple_file_system.h
new file mode 100644
index 0000000..6430aa0
--- /dev/null
+++ b/webkit/support/simple_file_system.h
@@ -0,0 +1,160 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef WEBKIT_SUPPORT_SIMPLE_FILE_SYSTEM_H_
+#define WEBKIT_SUPPORT_SIMPLE_FILE_SYSTEM_H_
+
+#include <vector>
+
+#include "base/files/scoped_temp_dir.h"
+#include "base/id_map.h"
+#include "base/memory/weak_ptr.h"
+#include "third_party/WebKit/public/platform/WebFileSystem.h"
+#include "third_party/WebKit/public/platform/WebFileSystemType.h"
+#include "webkit/browser/fileapi/file_system_context.h"
+#include "webkit/browser/fileapi/file_system_operation.h"
+#include "webkit/common/fileapi/file_system_types.h"
+
+namespace WebKit {
+class WebFileSystemCallbacks;
+class WebFrame;
+class WebURL;
+}
+
+namespace fileapi {
+class FileSystemContext;
+class FileSystemURL;
+}
+
+namespace webkit_blob {
+class BlobStorageController;
+}
+
+class SimpleFileSystem
+ : public WebKit::WebFileSystem,
+ public base::SupportsWeakPtr<SimpleFileSystem> {
+ public:
+ SimpleFileSystem();
+ virtual ~SimpleFileSystem();
+
+ void OpenFileSystem(WebKit::WebFrame* frame,
+ WebKit::WebFileSystemType type,
+ long long size,
+ bool create,
+ WebKit::WebFileSystemCallbacks* callbacks);
+ void DeleteFileSystem(WebKit::WebFrame* frame,
+ WebKit::WebFileSystemType type,
+ WebKit::WebFileSystemCallbacks* callbacks);
+
+ fileapi::FileSystemContext* file_system_context() {
+ return file_system_context_.get();
+ }
+
+ // WebKit::WebFileSystem implementation.
+ virtual void move(
+ const WebKit::WebURL& src_path,
+ const WebKit::WebURL& dest_path,
+ WebKit::WebFileSystemCallbacks*) OVERRIDE;
+ virtual void copy(
+ const WebKit::WebURL& src_path,
+ const WebKit::WebURL& dest_path,
+ WebKit::WebFileSystemCallbacks*) OVERRIDE;
+ virtual void remove(
+ const WebKit::WebURL& path,
+ WebKit::WebFileSystemCallbacks*) OVERRIDE;
+ virtual void removeRecursively(
+ const WebKit::WebURL& path,
+ WebKit::WebFileSystemCallbacks*) OVERRIDE;
+ virtual void readMetadata(
+ const WebKit::WebURL& path,
+ WebKit::WebFileSystemCallbacks*) OVERRIDE;
+ virtual void createFile(
+ const WebKit::WebURL& path,
+ bool exclusive,
+ WebKit::WebFileSystemCallbacks*) OVERRIDE;
+ virtual void createDirectory(
+ const WebKit::WebURL& path,
+ bool exclusive,
+ WebKit::WebFileSystemCallbacks*) OVERRIDE;
+ virtual void fileExists(
+ const WebKit::WebURL& path,
+ WebKit::WebFileSystemCallbacks*) OVERRIDE;
+ virtual void directoryExists(
+ const WebKit::WebURL& path,
+ WebKit::WebFileSystemCallbacks*) OVERRIDE;
+ virtual void readDirectory(
+ const WebKit::WebURL& path,
+ WebKit::WebFileSystemCallbacks*) OVERRIDE;
+ virtual WebKit::WebFileWriter* createFileWriter(
+ const WebKit::WebURL& path, WebKit::WebFileWriterClient*) OVERRIDE;
+ virtual void createSnapshotFileAndReadMetadata(
+ const WebKit::WebURL& path,
+ WebKit::WebFileSystemCallbacks* callbacks);
+
+ static void InitializeOnIOThread(
+ webkit_blob::BlobStorageController* blob_storage_controller);
+ static void CleanupOnIOThread();
+
+ private:
+ // Helpers.
+ bool HasFilePermission(const fileapi::FileSystemURL& url, int permissions);
+ fileapi::FileSystemOperation* GetNewOperation(
+ const fileapi::FileSystemURL& url);
+
+ // Callback Handlers
+ fileapi::FileSystemOperation::StatusCallback FinishHandler(
+ WebKit::WebFileSystemCallbacks* callbacks);
+ fileapi::FileSystemOperation::GetMetadataCallback GetMetadataHandler(
+ WebKit::WebFileSystemCallbacks* callbacks);
+ fileapi::FileSystemOperation::ReadDirectoryCallback
+ ReadDirectoryHandler(WebKit::WebFileSystemCallbacks* callbacks);
+ fileapi::FileSystemContext::OpenFileSystemCallback OpenFileSystemHandler(
+ WebKit::WebFileSystemCallbacks* callbacks);
+ fileapi::FileSystemContext::DeleteFileSystemCallback DeleteFileSystemHandler(
+ WebKit::WebFileSystemCallbacks* callbacks);
+ fileapi::FileSystemOperation::SnapshotFileCallback
+ SnapshotFileHandler(WebKit::WebFileSystemCallbacks* callbacks);
+ fileapi::FileSystemOperation::SnapshotFileCallback
+ SnapshotFileHandler_Deprecated(
+ const GURL& blob_url,
+ WebKit::WebFileSystemCallbacks* callbacks);
+ void DidFinish(WebKit::WebFileSystemCallbacks* callbacks,
+ base::PlatformFileError result);
+ void DidGetMetadata(WebKit::WebFileSystemCallbacks* callbacks,
+ base::PlatformFileError result,
+ const base::PlatformFileInfo& info,
+ const base::FilePath& platform_path);
+ void DidReadDirectory(
+ WebKit::WebFileSystemCallbacks* callbacks,
+ base::PlatformFileError result,
+ const std::vector<fileapi::DirectoryEntry>& entries,
+ bool has_more);
+ void DidOpenFileSystem(WebKit::WebFileSystemCallbacks* callbacks,
+ base::PlatformFileError result,
+ const std::string& name, const GURL& root);
+ void DidDeleteFileSystem(WebKit::WebFileSystemCallbacks* callbacks,
+ base::PlatformFileError result);
+ void DidCreateSnapshotFile(
+ WebKit::WebFileSystemCallbacks* callbacks,
+ base::PlatformFileError result,
+ const base::PlatformFileInfo& info,
+ const base::FilePath& platform_path,
+ const scoped_refptr<webkit_blob::ShareableFileReference>& file_ref);
+ void DidCreateSnapshotFile_Deprecated(
+ const GURL& blob_url,
+ WebKit::WebFileSystemCallbacks* callbacks,
+ base::PlatformFileError result,
+ const base::PlatformFileInfo& info,
+ const base::FilePath& platform_path,
+ const scoped_refptr<webkit_blob::ShareableFileReference>& file_ref);
+
+ // A temporary directory for FileSystem API.
+ base::ScopedTempDir file_system_dir_;
+
+ scoped_refptr<fileapi::FileSystemContext> file_system_context_;
+
+ DISALLOW_COPY_AND_ASSIGN(SimpleFileSystem);
+};
+
+#endif // WEBKIT_SUPPORT_SIMPLE_FILE_SYSTEM_H_
diff --git a/webkit/support/simple_file_writer.cc b/webkit/support/simple_file_writer.cc
new file mode 100644
index 0000000..b372fd1
--- /dev/null
+++ b/webkit/support/simple_file_writer.cc
@@ -0,0 +1,205 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "webkit/support/simple_file_writer.h"
+
+#include "base/bind.h"
+#include "base/location.h"
+#include "base/logging.h"
+#include "base/message_loop_proxy.h"
+#include "net/url_request/url_request_context.h"
+#include "webkit/browser/fileapi/file_system_context.h"
+#include "webkit/browser/fileapi/file_system_operation.h"
+#include "webkit/browser/fileapi/file_system_url.h"
+#include "webkit/common/fileapi/file_system_types.h"
+#include "webkit/glue/webkit_glue.h"
+#include "webkit/support/simple_resource_loader_bridge.h"
+
+using fileapi::FileSystemURL;
+using fileapi::FileSystemContext;
+using fileapi::FileSystemOperation;
+using fileapi::WebFileWriterBase;
+using WebKit::WebFileWriterClient;
+using WebKit::WebString;
+using WebKit::WebURL;
+
+net::URLRequestContext* SimpleFileWriter::request_context_ = NULL;
+
+// Helper class to proxy to write and truncate calls to the IO thread,
+// and to proxy the results back to the main thead. There is a one-to-one
+// relationship between SimpleFileWriters and IOThreadBackends.
+class SimpleFileWriter::IOThreadProxy
+ : public base::RefCountedThreadSafe<SimpleFileWriter::IOThreadProxy> {
+ public:
+ IOThreadProxy(const base::WeakPtr<SimpleFileWriter>& simple_writer,
+ FileSystemContext* file_system_context)
+ : simple_writer_(simple_writer),
+ operation_(NULL),
+ file_system_context_(file_system_context) {
+ // The IO thread needs to be running for this class to work.
+ SimpleResourceLoaderBridge::EnsureIOThread();
+ io_thread_ = SimpleResourceLoaderBridge::GetIoThread();
+ main_thread_ = base::MessageLoopProxy::current();
+ }
+
+ void Truncate(const FileSystemURL& url, int64 offset) {
+ if (!io_thread_->BelongsToCurrentThread()) {
+ io_thread_->PostTask(
+ FROM_HERE,
+ base::Bind(&IOThreadProxy::Truncate, this, url, offset));
+ return;
+ }
+ if (FailIfNotWritable(url))
+ return;
+ DCHECK(!operation_);
+ operation_ = GetNewOperation(url);
+ operation_->Truncate(url, offset,
+ base::Bind(&IOThreadProxy::DidFinish, this));
+ }
+
+ void Write(const FileSystemURL& url, const GURL& blob_url, int64 offset) {
+ if (!io_thread_->BelongsToCurrentThread()) {
+ io_thread_->PostTask(
+ FROM_HERE,
+ base::Bind(&IOThreadProxy::Write, this, url, blob_url, offset));
+ return;
+ }
+ if (FailIfNotWritable(url))
+ return;
+ DCHECK(request_context_);
+ DCHECK(!operation_);
+ operation_ = GetNewOperation(url);
+ operation_->Write(request_context_, url, blob_url, offset,
+ base::Bind(&IOThreadProxy::DidWrite, this));
+ }
+
+ void Cancel() {
+ if (!io_thread_->BelongsToCurrentThread()) {
+ io_thread_->PostTask(
+ FROM_HERE,
+ base::Bind(&IOThreadProxy::Cancel, this));
+ return;
+ }
+ if (!operation_) {
+ DidFailOnMainThread(base::PLATFORM_FILE_ERROR_INVALID_OPERATION);
+ return;
+ }
+ operation_->Cancel(base::Bind(&IOThreadProxy::DidFinish, this));
+ }
+
+ private:
+ friend class base::RefCountedThreadSafe<IOThreadProxy>;
+ virtual ~IOThreadProxy() {}
+
+ FileSystemOperation* GetNewOperation( const FileSystemURL& url) {
+ return file_system_context_->CreateFileSystemOperation(url, NULL);
+ }
+
+ // Returns true if it is not writable.
+ bool FailIfNotWritable(const FileSystemURL& url) {
+ if (url.type() == fileapi::kFileSystemTypeDragged) {
+ // Write is not allowed in isolate file system in SimpleFileWriter.
+ DidFailOnMainThread(base::PLATFORM_FILE_ERROR_SECURITY);
+ return true;
+ }
+ return false;
+ }
+
+ void DidSucceedOnMainThread() {
+ if (!main_thread_->BelongsToCurrentThread()) {
+ main_thread_->PostTask(
+ FROM_HERE,
+ base::Bind(&IOThreadProxy::DidSucceedOnMainThread, this));
+ return;
+ }
+ if (simple_writer_.get())
+ simple_writer_->DidSucceed();
+ }
+
+ void DidFailOnMainThread(base::PlatformFileError error_code) {
+ if (!main_thread_->BelongsToCurrentThread()) {
+ main_thread_->PostTask(
+ FROM_HERE,
+ base::Bind(&IOThreadProxy::DidFailOnMainThread, this, error_code));
+ return;
+ }
+ if (simple_writer_.get())
+ simple_writer_->DidFail(error_code);
+ }
+
+ void DidWriteOnMainThread(int64 bytes, bool complete) {
+ if (!main_thread_->BelongsToCurrentThread()) {
+ main_thread_->PostTask(
+ FROM_HERE,
+ base::Bind(&IOThreadProxy::DidWriteOnMainThread,
+ this, bytes, complete));
+ return;
+ }
+ if (simple_writer_.get())
+ simple_writer_->DidWrite(bytes, complete);
+ }
+
+ void ClearOperation() {
+ DCHECK(io_thread_->BelongsToCurrentThread());
+ operation_ = NULL;
+ }
+
+ void DidFinish(base::PlatformFileError result) {
+ if (result == base::PLATFORM_FILE_OK)
+ DidSucceedOnMainThread();
+ else
+ DidFailOnMainThread(result);
+ ClearOperation();
+ }
+
+ void DidWrite(base::PlatformFileError result, int64 bytes, bool complete) {
+ if (result == base::PLATFORM_FILE_OK) {
+ DidWriteOnMainThread(bytes, complete);
+ if (complete)
+ ClearOperation();
+ } else {
+ DidFailOnMainThread(result);
+ ClearOperation();
+ }
+ }
+
+ scoped_refptr<base::MessageLoopProxy> io_thread_;
+ scoped_refptr<base::MessageLoopProxy> main_thread_;
+
+ // Only used on the main thread.
+ base::WeakPtr<SimpleFileWriter> simple_writer_;
+
+ // Only used on the io thread.
+ FileSystemOperation* operation_;
+
+ scoped_refptr<FileSystemContext> file_system_context_;
+};
+
+
+SimpleFileWriter::SimpleFileWriter(
+ const GURL& path,
+ WebFileWriterClient* client,
+ FileSystemContext* file_system_context)
+ : WebFileWriterBase(path, client),
+ file_system_context_(file_system_context),
+ io_thread_proxy_(new IOThreadProxy(AsWeakPtr(), file_system_context)) {
+}
+
+SimpleFileWriter::~SimpleFileWriter() {
+}
+
+void SimpleFileWriter::DoTruncate(const GURL& path, int64 offset) {
+ FileSystemURL url = file_system_context_->CrackURL(path);
+ io_thread_proxy_->Truncate(url, offset);
+}
+
+void SimpleFileWriter::DoWrite(
+ const GURL& path, const GURL& blob_url, int64 offset) {
+ FileSystemURL url = file_system_context_->CrackURL(path);
+ io_thread_proxy_->Write(url, blob_url, offset);
+}
+
+void SimpleFileWriter::DoCancel() {
+ io_thread_proxy_->Cancel();
+}
diff --git a/webkit/support/simple_file_writer.h b/webkit/support/simple_file_writer.h
new file mode 100644
index 0000000..778fb55
--- /dev/null
+++ b/webkit/support/simple_file_writer.h
@@ -0,0 +1,53 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef WEBKIT_SUPPORT_SIMPLE_FILE_WRITER_H_
+#define WEBKIT_SUPPORT_SIMPLE_FILE_WRITER_H_
+
+#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "webkit/renderer/fileapi/webfilewriter_base.h"
+
+namespace net {
+class URLRequestContext;
+} // namespace net
+
+namespace fileapi {
+class FileSystemContext;
+}
+
+// An implementation of WebFileWriter for use in test_shell and DRT.
+class SimpleFileWriter : public fileapi::WebFileWriterBase,
+ public base::SupportsWeakPtr<SimpleFileWriter> {
+ public:
+ SimpleFileWriter(
+ const GURL& path,
+ WebKit::WebFileWriterClient* client,
+ fileapi::FileSystemContext* file_system_context);
+ virtual ~SimpleFileWriter();
+
+ // Called by SimpleResourceLoaderBridge when the context is
+ // created and destroyed.
+ static void InitializeOnIOThread(net::URLRequestContext* request_context) {
+ request_context_ = request_context;
+ }
+ static void CleanupOnIOThread() {
+ request_context_ = NULL;
+ }
+
+ protected:
+ // WebFileWriterBase overrides
+ virtual void DoTruncate(const GURL& path, int64 offset) OVERRIDE;
+ virtual void DoWrite(const GURL& path, const GURL& blob_url,
+ int64 offset) OVERRIDE;
+ virtual void DoCancel() OVERRIDE;
+
+ private:
+ class IOThreadProxy;
+ scoped_refptr<fileapi::FileSystemContext> file_system_context_;
+ scoped_refptr<IOThreadProxy> io_thread_proxy_;
+ static net::URLRequestContext* request_context_;
+};
+
+#endif // WEBKIT_SUPPORT_SIMPLE_FILE_WRITER_H_
diff --git a/webkit/support/simple_resource_loader_bridge.cc b/webkit/support/simple_resource_loader_bridge.cc
new file mode 100644
index 0000000..42701a8
--- /dev/null
+++ b/webkit/support/simple_resource_loader_bridge.cc
@@ -0,0 +1,1168 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// This file contains an implementation of the ResourceLoaderBridge class.
+// The class is implemented using net::URLRequest, meaning it is a "simple"
+// version that directly issues requests. The more complicated one used in the
+// browser uses IPC.
+//
+// Because net::URLRequest only provides an asynchronous resource loading API,
+// this file makes use of net::URLRequest from a background IO thread. Requests
+// for cookies and synchronously loaded resources result in the main thread of
+// the application blocking until the IO thread completes the operation. (See
+// GetCookies and SyncLoad)
+//
+// Main thread IO thread
+// ----------- ---------
+// ResourceLoaderBridge <---o---------> RequestProxy (normal case)
+// \ -> net::URLRequest
+// o-------> SyncRequestProxy (synchronous case)
+// -> net::URLRequest
+// SetCookie <------------------------> CookieSetter
+// -> net_util::SetCookie
+// GetCookies <-----------------------> CookieGetter
+// -> net_util::GetCookies
+//
+// NOTE: The implementation in this file may be used to have WebKit fetch
+// resources in-process. For example, it is handy for building a single-
+// process WebKit embedding (e.g., test_shell) that can use net::URLRequest to
+// perform URL loads. See renderer/resource_dispatcher.h for details on an
+// alternate implementation that defers fetching to another process.
+
+#include "webkit/support/simple_resource_loader_bridge.h"
+
+#include "base/bind.h"
+#include "base/compiler_specific.h"
+#include "base/file_util.h"
+#include "base/files/file_path.h"
+#include "base/logging.h"
+#include "base/memory/ref_counted.h"
+#include "base/message_loop.h"
+#include "base/message_loop_proxy.h"
+#include "base/string_util.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/threading/thread.h"
+#include "base/time.h"
+#include "base/timer.h"
+#include "net/base/file_stream.h"
+#include "net/base/io_buffer.h"
+#include "net/base/load_flags.h"
+#include "net/base/mime_util.h"
+#include "net/base/net_errors.h"
+#include "net/base/net_util.h"
+#include "net/base/network_delegate.h"
+#include "net/base/static_cookie_policy.h"
+#include "net/base/upload_data_stream.h"
+#include "net/cookies/cookie_store.h"
+#include "net/http/http_cache.h"
+#include "net/http/http_request_headers.h"
+#include "net/http/http_response_headers.h"
+#include "net/url_request/url_request.h"
+#include "net/url_request/url_request_context.h"
+#include "net/url_request/url_request_job.h"
+#include "webkit/appcache/appcache_interfaces.h"
+#include "webkit/browser/blob/blob_storage_controller.h"
+#include "webkit/browser/blob/blob_url_request_job.h"
+#include "webkit/browser/fileapi/file_system_context.h"
+#include "webkit/browser/fileapi/file_system_dir_url_request_job.h"
+#include "webkit/browser/fileapi/file_system_url_request_job.h"
+#include "webkit/common/blob/shareable_file_reference.h"
+#include "webkit/glue/resource_loader_bridge.h"
+#include "webkit/glue/resource_request_body.h"
+#include "webkit/glue/webkit_glue.h"
+#include "webkit/support/simple_appcache_system.h"
+#include "webkit/support/simple_file_system.h"
+#include "webkit/support/simple_file_writer.h"
+#include "webkit/support/simple_socket_stream_bridge.h"
+#include "webkit/support/test_shell_request_context.h"
+#include "webkit/support/test_shell_webblobregistry_impl.h"
+
+#if defined(OS_MACOSX) || defined(OS_WIN)
+#include "crypto/nss_util.h"
+#endif
+
+using webkit_glue::ResourceLoaderBridge;
+using webkit_glue::ResourceRequestBody;
+using webkit_glue::ResourceResponseInfo;
+using net::StaticCookiePolicy;
+using net::HttpResponseHeaders;
+using webkit_blob::ShareableFileReference;
+
+namespace {
+
+struct TestShellRequestContextParams {
+ TestShellRequestContextParams(
+ const base::FilePath& in_cache_path,
+ net::HttpCache::Mode in_cache_mode,
+ bool in_no_proxy)
+ : cache_path(in_cache_path),
+ cache_mode(in_cache_mode),
+ no_proxy(in_no_proxy) {}
+
+ base::FilePath cache_path;
+ net::HttpCache::Mode cache_mode;
+ bool no_proxy;
+};
+
+//-----------------------------------------------------------------------------
+
+bool g_accept_all_cookies = false;
+
+class TestShellNetworkDelegate : public net::NetworkDelegate {
+ public:
+ virtual ~TestShellNetworkDelegate() {}
+
+ protected:
+ // net::NetworkDelegate implementation.
+ virtual int OnBeforeURLRequest(net::URLRequest* request,
+ const net::CompletionCallback& callback,
+ GURL* new_url) OVERRIDE {
+ return net::OK;
+ }
+ virtual int OnBeforeSendHeaders(net::URLRequest* request,
+ const net::CompletionCallback& callback,
+ net::HttpRequestHeaders* headers) OVERRIDE {
+ return net::OK;
+ }
+ virtual void OnSendHeaders(net::URLRequest* request,
+ const net::HttpRequestHeaders& headers) OVERRIDE {}
+ virtual int OnHeadersReceived(
+ net::URLRequest* request,
+ const net::CompletionCallback& callback,
+ const net::HttpResponseHeaders* original_response_headers,
+ scoped_refptr<net::HttpResponseHeaders>*
+ override_response_headers) OVERRIDE {
+ return net::OK;
+ }
+ virtual void OnBeforeRedirect(net::URLRequest* request,
+ const GURL& new_location) OVERRIDE {}
+ virtual void OnResponseStarted(net::URLRequest* request) OVERRIDE {}
+ virtual void OnRawBytesRead(const net::URLRequest& request,
+ int bytes_read) OVERRIDE {}
+ virtual void OnCompleted(net::URLRequest* request, bool started) OVERRIDE {}
+ virtual void OnURLRequestDestroyed(net::URLRequest* request) OVERRIDE {}
+
+ virtual void OnPACScriptError(int line_number,
+ const base::string16& error) OVERRIDE {
+ }
+ virtual AuthRequiredResponse OnAuthRequired(
+ net::URLRequest* request,
+ const net::AuthChallengeInfo& auth_info,
+ const AuthCallback& callback,
+ net::AuthCredentials* credentials) OVERRIDE {
+ return AUTH_REQUIRED_RESPONSE_NO_ACTION;
+ }
+ virtual bool OnCanGetCookies(const net::URLRequest& request,
+ const net::CookieList& cookie_list) OVERRIDE {
+ StaticCookiePolicy::Type policy_type = g_accept_all_cookies ?
+ StaticCookiePolicy::ALLOW_ALL_COOKIES :
+ StaticCookiePolicy::BLOCK_SETTING_THIRD_PARTY_COOKIES;
+
+ StaticCookiePolicy policy(policy_type);
+ int rv = policy.CanGetCookies(
+ request.url(), request.first_party_for_cookies());
+ return rv == net::OK;
+ }
+ virtual bool OnCanSetCookie(const net::URLRequest& request,
+ const std::string& cookie_line,
+ net::CookieOptions* options) OVERRIDE {
+ StaticCookiePolicy::Type policy_type = g_accept_all_cookies ?
+ StaticCookiePolicy::ALLOW_ALL_COOKIES :
+ StaticCookiePolicy::BLOCK_SETTING_THIRD_PARTY_COOKIES;
+
+ StaticCookiePolicy policy(policy_type);
+ int rv = policy.CanSetCookie(
+ request.url(), request.first_party_for_cookies());
+ return rv == net::OK;
+ }
+ virtual bool OnCanAccessFile(const net::URLRequest& request,
+ const base::FilePath& path) const OVERRIDE {
+ return true;
+ }
+ virtual bool OnCanThrottleRequest(
+ const net::URLRequest& request) const OVERRIDE {
+ return false;
+ }
+
+ virtual int OnBeforeSocketStreamConnect(
+ net::SocketStream* stream,
+ const net::CompletionCallback& callback) OVERRIDE {
+ return net::OK;
+ }
+
+ virtual void OnRequestWaitStateChange(const net::URLRequest& request,
+ RequestWaitState state) OVERRIDE {
+ }
+};
+
+TestShellRequestContextParams* g_request_context_params = NULL;
+TestShellRequestContext* g_request_context = NULL;
+TestShellNetworkDelegate* g_network_delegate = NULL;
+base::Thread* g_cache_thread = NULL;
+
+//-----------------------------------------------------------------------------
+
+struct FileOverHTTPParams {
+ FileOverHTTPParams(std::string in_file_path_template, GURL in_http_prefix)
+ : file_path_template(in_file_path_template),
+ http_prefix(in_http_prefix) {}
+
+ std::string file_path_template;
+ GURL http_prefix;
+};
+
+class FileOverHTTPPathMappings {
+ public:
+ FileOverHTTPPathMappings() : redirections_() {}
+ void AddMapping(std::string file_path_template, GURL http_prefix) {
+ redirections_.push_back(FileOverHTTPParams(file_path_template,
+ http_prefix));
+ }
+
+ const FileOverHTTPParams* ParamsForRequest(std::string request,
+ std::string::size_type& offset) {
+ std::vector<FileOverHTTPParams>::iterator it;
+ for (it = redirections_.begin(); it != redirections_.end(); ++it) {
+ offset = request.find(it->file_path_template);
+ if (offset != std::string::npos)
+ return &*it;
+ }
+ return 0;
+ }
+
+ const FileOverHTTPParams* ParamsForResponse(std::string response_url) {
+ std::vector<FileOverHTTPParams>::iterator it;
+ for (it = redirections_.begin(); it != redirections_.end(); ++it) {
+ if (response_url.find(it->http_prefix.spec()) == 0)
+ return &*it;
+ }
+ return 0;
+ }
+
+ private:
+ std::vector<FileOverHTTPParams> redirections_;
+};
+
+FileOverHTTPPathMappings* g_file_over_http_mappings = NULL;
+
+//-----------------------------------------------------------------------------
+
+class IOThread : public base::Thread {
+ public:
+ IOThread() : base::Thread("IOThread") {}
+
+ virtual ~IOThread() {
+ Stop();
+ }
+
+ virtual void Init() OVERRIDE {
+ if (g_request_context_params) {
+ g_request_context = new TestShellRequestContext(
+ g_request_context_params->cache_path,
+ g_request_context_params->cache_mode,
+ g_request_context_params->no_proxy);
+ delete g_request_context_params;
+ g_request_context_params = NULL;
+ } else {
+ g_request_context = new TestShellRequestContext();
+ }
+
+ g_network_delegate = new TestShellNetworkDelegate();
+ g_request_context->set_network_delegate(g_network_delegate);
+
+ SimpleAppCacheSystem::InitializeOnIOThread(g_request_context);
+ SimpleSocketStreamBridge::InitializeOnIOThread(g_request_context);
+ SimpleFileWriter::InitializeOnIOThread(g_request_context);
+ SimpleFileSystem::InitializeOnIOThread(
+ g_request_context->blob_storage_controller());
+ TestShellWebBlobRegistryImpl::InitializeOnIOThread(
+ g_request_context->blob_storage_controller());
+ }
+
+ virtual void CleanUp() OVERRIDE {
+ // In reverse order of initialization.
+ TestShellWebBlobRegistryImpl::Cleanup();
+ SimpleFileSystem::CleanupOnIOThread();
+ SimpleFileWriter::CleanupOnIOThread();
+ SimpleSocketStreamBridge::Cleanup();
+ SimpleAppCacheSystem::CleanupOnIOThread();
+
+ if (g_request_context) {
+ g_request_context->set_network_delegate(NULL);
+ delete g_request_context;
+ g_request_context = NULL;
+ }
+
+ if (g_network_delegate) {
+ delete g_network_delegate;
+ g_network_delegate = NULL;
+ }
+ }
+};
+
+IOThread* g_io_thread = NULL;
+
+//-----------------------------------------------------------------------------
+
+struct RequestParams {
+ std::string method;
+ GURL url;
+ GURL first_party_for_cookies;
+ GURL referrer;
+ WebKit::WebReferrerPolicy referrer_policy;
+ std::string headers;
+ int load_flags;
+ ResourceType::Type request_type;
+ int appcache_host_id;
+ bool download_to_file;
+ scoped_refptr<ResourceRequestBody> request_body;
+};
+
+// The interval for calls to RequestProxy::MaybeUpdateUploadProgress
+static const int kUpdateUploadProgressIntervalMsec = 100;
+
+// The RequestProxy does most of its work on the IO thread. The Start and
+// Cancel methods are proxied over to the IO thread, where an net::URLRequest
+// object is instantiated.
+struct DeleteOnIOThread; // See below.
+class RequestProxy
+ : public net::URLRequest::Delegate,
+ public base::RefCountedThreadSafe<RequestProxy, DeleteOnIOThread> {
+ public:
+ // Takes ownership of the params.
+ RequestProxy()
+ : download_to_file_(false),
+ buf_(new net::IOBuffer(kDataSize)),
+ last_upload_position_(0) {
+ }
+
+ void DropPeer() {
+ peer_ = NULL;
+ }
+
+ void Start(ResourceLoaderBridge::Peer* peer, RequestParams* params) {
+ peer_ = peer;
+ owner_loop_ = base::MessageLoop::current();
+
+ ConvertRequestParamsForFileOverHTTPIfNeeded(params);
+ // proxy over to the io thread
+ g_io_thread->message_loop()->PostTask(
+ FROM_HERE,
+ base::Bind(&RequestProxy::AsyncStart, this, params));
+ }
+
+ void Cancel() {
+ // proxy over to the io thread
+ g_io_thread->message_loop()->PostTask(
+ FROM_HERE,
+ base::Bind(&RequestProxy::AsyncCancel, this));
+ }
+
+ protected:
+ friend class base::DeleteHelper<RequestProxy>;
+ friend class base::RefCountedThreadSafe<RequestProxy>;
+ friend struct DeleteOnIOThread;
+
+ virtual ~RequestProxy() {
+ // Ensure we are deleted on the IO thread because base::Timer requires that.
+ // (guaranteed by the Traits class template parameter).
+ DCHECK(base::MessageLoop::current() == g_io_thread->message_loop());
+ }
+
+ // --------------------------------------------------------------------------
+ // The following methods are called on the owner's thread in response to
+ // various net::URLRequest callbacks. The event hooks, defined below, trigger
+ // these methods asynchronously.
+
+ void NotifyReceivedRedirect(const GURL& new_url,
+ const ResourceResponseInfo& info) {
+ bool has_new_first_party_for_cookies = false;
+ GURL new_first_party_for_cookies;
+ if (peer_ && peer_->OnReceivedRedirect(new_url, info,
+ &has_new_first_party_for_cookies,
+ &new_first_party_for_cookies)) {
+ g_io_thread->message_loop()->PostTask(
+ FROM_HERE,
+ base::Bind(&RequestProxy::AsyncFollowDeferredRedirect, this,
+ has_new_first_party_for_cookies,
+ new_first_party_for_cookies));
+ } else {
+ Cancel();
+ }
+ }
+
+ void NotifyReceivedResponse(const ResourceResponseInfo& info) {
+ if (peer_)
+ peer_->OnReceivedResponse(info);
+ }
+
+ void NotifyReceivedData(int bytes_read) {
+ if (!peer_)
+ return;
+
+ // Make a local copy of buf_, since AsyncReadData reuses it.
+ scoped_ptr<char[]> buf_copy(new char[bytes_read]);
+ memcpy(buf_copy.get(), buf_->data(), bytes_read);
+
+ // Continue reading more data into buf_
+ // Note: Doing this before notifying our peer ensures our load events get
+ // dispatched in a manner consistent with DumpRenderTree (and also avoids a
+ // race condition). If the order of the next 2 functions were reversed, the
+ // peer could generate new requests in reponse to the received data, which
+ // when run on the io thread, could race against this function in doing
+ // another InvokeLater. See bug 769249.
+ g_io_thread->message_loop()->PostTask(
+ FROM_HERE,
+ base::Bind(&RequestProxy::AsyncReadData, this));
+
+ peer_->OnReceivedData(buf_copy.get(), bytes_read, -1);
+ }
+
+ void NotifyDownloadedData(int bytes_read) {
+ if (!peer_)
+ return;
+
+ // Continue reading more data, see the comment in NotifyReceivedData.
+ g_io_thread->message_loop()->PostTask(
+ FROM_HERE,
+ base::Bind(&RequestProxy::AsyncReadData, this));
+
+ peer_->OnDownloadedData(bytes_read);
+ }
+
+ void NotifyCompletedRequest(int error_code,
+ const std::string& security_info,
+ const base::TimeTicks& complete_time) {
+ if (peer_) {
+ peer_->OnCompletedRequest(error_code, false, security_info,
+ complete_time);
+ DropPeer(); // ensure no further notifications
+ }
+ }
+
+ void NotifyUploadProgress(uint64 position, uint64 size) {
+ if (peer_)
+ peer_->OnUploadProgress(position, size);
+ }
+
+ // --------------------------------------------------------------------------
+ // The following methods are called on the io thread. They correspond to
+ // actions performed on the owner's thread.
+
+ void AsyncStart(RequestParams* params) {
+ request_.reset(g_request_context->CreateRequest(params->url, this));
+ request_->set_method(params->method);
+ request_->set_first_party_for_cookies(params->first_party_for_cookies);
+ request_->SetReferrer(params->referrer.spec());
+ webkit_glue::ConfigureURLRequestForReferrerPolicy(
+ request_.get(), params->referrer_policy);
+ net::HttpRequestHeaders headers;
+ headers.AddHeadersFromString(params->headers);
+ request_->SetExtraRequestHeaders(headers);
+ request_->set_load_flags(params->load_flags);
+ if (params->request_body.get()) {
+ request_->set_upload(make_scoped_ptr(
+ params->request_body->ResolveElementsAndCreateUploadDataStream(
+ static_cast<TestShellRequestContext*>(g_request_context)
+ ->blob_storage_controller(),
+ static_cast<TestShellRequestContext*>(g_request_context)
+ ->file_system_context(),
+ base::MessageLoopProxy::current())));
+ }
+ SimpleAppCacheSystem::SetExtraRequestInfo(
+ request_.get(), params->appcache_host_id, params->request_type);
+
+ download_to_file_ = params->download_to_file;
+ if (download_to_file_) {
+ base::FilePath path;
+ if (file_util::CreateTemporaryFile(&path)) {
+ downloaded_file_ = ShareableFileReference::GetOrCreate(
+ path, ShareableFileReference::DELETE_ON_FINAL_RELEASE,
+ base::MessageLoopProxy::current());
+ file_stream_.reset(new net::FileStream(NULL));
+ file_stream_->OpenSync(
+ path, base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_WRITE);
+ }
+ }
+
+ request_->Start();
+
+ if (request_->has_upload() &&
+ params->load_flags & net::LOAD_ENABLE_UPLOAD_PROGRESS) {
+ upload_progress_timer_.Start(FROM_HERE,
+ base::TimeDelta::FromMilliseconds(kUpdateUploadProgressIntervalMsec),
+ this, &RequestProxy::MaybeUpdateUploadProgress);
+ }
+
+ delete params;
+ }
+
+ void AsyncCancel() {
+ // This can be null in cases where the request is already done.
+ if (!request_)
+ return;
+
+ request_->Cancel();
+ Done();
+ }
+
+ void AsyncFollowDeferredRedirect(bool has_new_first_party_for_cookies,
+ const GURL& new_first_party_for_cookies) {
+ // This can be null in cases where the request is already done.
+ if (!request_)
+ return;
+
+ if (has_new_first_party_for_cookies)
+ request_->set_first_party_for_cookies(new_first_party_for_cookies);
+ request_->FollowDeferredRedirect();
+ }
+
+ void AsyncReadData() {
+ // This can be null in cases where the request is already done.
+ if (!request_)
+ return;
+
+ if (request_->status().is_success()) {
+ int bytes_read;
+ if (request_->Read(buf_.get(), kDataSize, &bytes_read) && bytes_read) {
+ OnReceivedData(bytes_read);
+ } else if (!request_->status().is_io_pending()) {
+ Done();
+ } // else wait for OnReadCompleted
+ } else {
+ Done();
+ }
+ }
+
+ // --------------------------------------------------------------------------
+ // The following methods are event hooks (corresponding to net::URLRequest
+ // callbacks) that run on the IO thread. They are designed to be overridden
+ // by the SyncRequestProxy subclass.
+
+ virtual void OnReceivedRedirect(
+ const GURL& new_url,
+ const ResourceResponseInfo& info,
+ bool* defer_redirect) {
+ *defer_redirect = true; // See AsyncFollowDeferredRedirect
+ owner_loop_->PostTask(
+ FROM_HERE,
+ base::Bind(&RequestProxy::NotifyReceivedRedirect, this, new_url, info));
+ }
+
+ virtual void OnReceivedResponse(
+ const ResourceResponseInfo& info) {
+ owner_loop_->PostTask(
+ FROM_HERE,
+ base::Bind(&RequestProxy::NotifyReceivedResponse, this, info));
+ }
+
+ virtual void OnReceivedData(int bytes_read) {
+ if (download_to_file_) {
+ file_stream_->WriteSync(buf_->data(), bytes_read);
+ owner_loop_->PostTask(
+ FROM_HERE,
+ base::Bind(&RequestProxy::NotifyDownloadedData, this, bytes_read));
+ return;
+ }
+
+ owner_loop_->PostTask(
+ FROM_HERE,
+ base::Bind(&RequestProxy::NotifyReceivedData, this, bytes_read));
+ }
+
+ virtual void OnCompletedRequest(int error_code,
+ const std::string& security_info,
+ const base::TimeTicks& complete_time) {
+ if (download_to_file_)
+ file_stream_.reset();
+ owner_loop_->PostTask(
+ FROM_HERE,
+ base::Bind(&RequestProxy::NotifyCompletedRequest, this, error_code,
+ security_info, complete_time));
+ }
+
+ // --------------------------------------------------------------------------
+ // net::URLRequest::Delegate implementation:
+
+ virtual void OnReceivedRedirect(net::URLRequest* request,
+ const GURL& new_url,
+ bool* defer_redirect) OVERRIDE {
+ DCHECK(request->status().is_success());
+ ResourceResponseInfo info;
+ PopulateResponseInfo(request, &info);
+ // For file protocol, should never have the redirect situation.
+ DCHECK(!ConvertResponseInfoForFileOverHTTPIfNeeded(request, &info));
+ OnReceivedRedirect(new_url, info, defer_redirect);
+ }
+
+ virtual void OnResponseStarted(net::URLRequest* request) OVERRIDE {
+ if (request->status().is_success()) {
+ ResourceResponseInfo info;
+ PopulateResponseInfo(request, &info);
+ // If encountering error when requesting the file, cancel the request.
+ if (ConvertResponseInfoForFileOverHTTPIfNeeded(request, &info) &&
+ failed_file_request_status_.get()) {
+ AsyncCancel();
+ } else {
+ OnReceivedResponse(info);
+ AsyncReadData(); // start reading
+ }
+ } else {
+ Done();
+ }
+ }
+
+ virtual void OnSSLCertificateError(net::URLRequest* request,
+ const net::SSLInfo& ssl_info,
+ bool fatal) OVERRIDE {
+ // Allow all certificate errors.
+ request->ContinueDespiteLastError();
+ }
+
+ virtual void OnReadCompleted(net::URLRequest* request,
+ int bytes_read) OVERRIDE {
+ if (request->status().is_success() && bytes_read > 0) {
+ OnReceivedData(bytes_read);
+ } else {
+ Done();
+ }
+ }
+
+ // --------------------------------------------------------------------------
+ // Helpers and data:
+
+ void Done() {
+ if (upload_progress_timer_.IsRunning()) {
+ MaybeUpdateUploadProgress();
+ upload_progress_timer_.Stop();
+ }
+ DCHECK(request_.get());
+ // If |failed_file_request_status_| is not empty, which means the request
+ // was a file request and encountered an error, then we need to use the
+ // |failed_file_request_status_|. Otherwise use request_'s status.
+ OnCompletedRequest(failed_file_request_status_.get() ?
+ failed_file_request_status_->error() :
+ request_->status().error(),
+ std::string(), base::TimeTicks::Now());
+ request_.reset(); // destroy on the io thread
+ }
+
+ // Called on the IO thread.
+ void MaybeUpdateUploadProgress() {
+ // If a redirect is received upload is cancelled in net::URLRequest, we
+ // should try to stop the |upload_progress_timer_| timer and return.
+ if (!request_->has_upload()) {
+ if (upload_progress_timer_.IsRunning())
+ upload_progress_timer_.Stop();
+ return;
+ }
+
+ net::UploadProgress progress = request_->GetUploadProgress();
+ if (progress.position() == last_upload_position_)
+ return; // no progress made since last time
+
+ const uint64 kHalfPercentIncrements = 200;
+ const base::TimeDelta kOneSecond = base::TimeDelta::FromMilliseconds(1000);
+
+ uint64 amt_since_last = progress.position() - last_upload_position_;
+ base::TimeDelta time_since_last = base::TimeTicks::Now() -
+ last_upload_ticks_;
+
+ bool is_finished = (progress.size() == progress.position());
+ bool enough_new_progress = (amt_since_last > (progress.size() /
+ kHalfPercentIncrements));
+ bool too_much_time_passed = time_since_last > kOneSecond;
+
+ if (is_finished || enough_new_progress || too_much_time_passed) {
+ owner_loop_->PostTask(
+ FROM_HERE,
+ base::Bind(&RequestProxy::NotifyUploadProgress, this,
+ progress.position(), progress.size()));
+ last_upload_ticks_ = base::TimeTicks::Now();
+ last_upload_position_ = progress.position();
+ }
+ }
+
+ void PopulateResponseInfo(net::URLRequest* request,
+ ResourceResponseInfo* info) const {
+ if (request->load_flags() & net::LOAD_ENABLE_LOAD_TIMING)
+ request->GetLoadTimingInfo(&info->load_timing);
+ info->request_time = request->request_time();
+ info->response_time = request->response_time();
+ info->headers = request->response_headers();
+ request->GetMimeType(&info->mime_type);
+ request->GetCharset(&info->charset);
+ info->content_length = request->GetExpectedContentSize();
+ if (downloaded_file_.get())
+ info->download_file_path = downloaded_file_->path();
+ SimpleAppCacheSystem::GetExtraResponseInfo(
+ request,
+ &info->appcache_id,
+ &info->appcache_manifest_url);
+ }
+
+ // Called on owner thread
+ void ConvertRequestParamsForFileOverHTTPIfNeeded(RequestParams* params) {
+ // Reset the status.
+ file_url_prefix_ .clear();
+ failed_file_request_status_.reset();
+ // Only do this when enabling file-over-http and request is file scheme.
+ if (!g_file_over_http_mappings || !params->url.SchemeIsFile())
+ return;
+
+ // For file protocol, method must be GET, POST or NULL.
+ DCHECK(params->method == "GET" || params->method == "POST" ||
+ params->method.empty());
+ DCHECK(!params->download_to_file);
+
+ if (params->method.empty())
+ params->method = "GET";
+ std::string original_request = params->url.spec();
+
+ std::string::size_type offset = 0;
+ const FileOverHTTPParams* redirection_params =
+ g_file_over_http_mappings->ParamsForRequest(original_request, offset);
+ if (!redirection_params)
+ return;
+
+ offset += redirection_params->file_path_template.size();
+ file_url_prefix_ = original_request.substr(0, offset);
+ original_request.replace(0, offset,
+ redirection_params->http_prefix.spec());
+ params->url = GURL(original_request);
+ params->first_party_for_cookies = params->url;
+ // For file protocol, nerver use cache.
+ params->load_flags = net::LOAD_BYPASS_CACHE;
+ }
+
+ // Called on IO thread.
+ bool ConvertResponseInfoForFileOverHTTPIfNeeded(net::URLRequest* request,
+ ResourceResponseInfo* info) {
+ // Only do this when enabling file-over-http and request url
+ // matches the http prefix for file-over-http feature.
+ if (!g_file_over_http_mappings || file_url_prefix_.empty())
+ return false;
+
+ std::string original_request = request->url().spec();
+ DCHECK(!original_request.empty());
+
+ const FileOverHTTPParams* redirection_params =
+ g_file_over_http_mappings->ParamsForResponse(original_request);
+ DCHECK(redirection_params);
+
+ std::string http_prefix = redirection_params->http_prefix.spec();
+ DCHECK(StartsWithASCII(original_request, http_prefix, true));
+
+ // Get the File URL.
+ original_request.replace(0, http_prefix.size(), file_url_prefix_);
+
+ base::FilePath file_path;
+ if (!net::FileURLToFilePath(GURL(original_request), &file_path)) {
+ NOTREACHED();
+ }
+
+ info->mime_type.clear();
+ DCHECK(info->headers.get());
+ int status_code = info->headers->response_code();
+ // File protocol does not support response headers.
+ info->headers = NULL;
+ if (200 == status_code) {
+ // Don't use the MIME type from HTTP server, use net::GetMimeTypeFromFile
+ // instead.
+ net::GetMimeTypeFromFile(file_path, &info->mime_type);
+ } else {
+ // If the file does not exist, immediately call OnCompletedRequest with
+ // setting URLRequestStatus to FAILED.
+ DCHECK(status_code == 404 || status_code == 403);
+ if (status_code == 404) {
+ failed_file_request_status_.reset(
+ new net::URLRequestStatus(net::URLRequestStatus::FAILED,
+ net::ERR_FILE_NOT_FOUND));
+ } else {
+ failed_file_request_status_.reset(
+ new net::URLRequestStatus(net::URLRequestStatus::FAILED,
+ net::ERR_ACCESS_DENIED));
+ }
+ }
+ return true;
+ }
+
+ scoped_ptr<net::URLRequest> request_;
+
+ // Support for request.download_to_file behavior.
+ bool download_to_file_;
+ scoped_ptr<net::FileStream> file_stream_;
+ scoped_refptr<ShareableFileReference> downloaded_file_;
+
+ // Size of our async IO data buffers
+ static const int kDataSize = 16*1024;
+
+ // read buffer for async IO
+ scoped_refptr<net::IOBuffer> buf_;
+
+ base::MessageLoop* owner_loop_;
+
+ // This is our peer in WebKit (implemented as ResourceHandleInternal). We do
+ // not manage its lifetime, and we may only access it from the owner's
+ // message loop (owner_loop_).
+ ResourceLoaderBridge::Peer* peer_;
+
+ // Timer used to pull upload progress info.
+ base::RepeatingTimer<RequestProxy> upload_progress_timer_;
+
+ // Info used to determine whether or not to send an upload progress update.
+ uint64 last_upload_position_;
+ base::TimeTicks last_upload_ticks_;
+
+ // Save the real FILE URL prefix for the FILE URL which converts to HTTP URL.
+ std::string file_url_prefix_;
+ // Save a failed file request status to pass it to webkit.
+ scoped_ptr<net::URLRequestStatus> failed_file_request_status_;
+};
+
+// Helper guaranteeing deletion on the IO thread (like
+// content::BrowserThread::DeleteOnIOThread, but without the dependency).
+struct DeleteOnIOThread {
+ static void Destruct(const RequestProxy* obj) {
+ if (base::MessageLoop::current() == g_io_thread->message_loop())
+ delete obj;
+ else
+ g_io_thread->message_loop()->DeleteSoon(FROM_HERE, obj);
+ }
+};
+
+//-----------------------------------------------------------------------------
+
+class SyncRequestProxy : public RequestProxy {
+ public:
+ explicit SyncRequestProxy(ResourceLoaderBridge::SyncLoadResponse* result)
+ : result_(result), event_(true, false) {
+ }
+
+ void WaitForCompletion() {
+ event_.Wait();
+ }
+
+ // --------------------------------------------------------------------------
+ // RequestProxy event hooks that run on the IO thread:
+
+ virtual void OnReceivedRedirect(
+ const GURL& new_url,
+ const ResourceResponseInfo& info,
+ bool* defer_redirect) OVERRIDE {
+ // TODO(darin): It would be much better if this could live in WebCore, but
+ // doing so requires API changes at all levels. Similar code exists in
+ // WebCore/platform/network/cf/ResourceHandleCFNet.cpp :-(
+ if (new_url.GetOrigin() != result_->url.GetOrigin()) {
+ DLOG(WARNING) << "Cross origin redirect denied";
+ Cancel();
+ return;
+ }
+ result_->url = new_url;
+ }
+
+ virtual void OnReceivedResponse(const ResourceResponseInfo& info) OVERRIDE {
+ *static_cast<ResourceResponseInfo*>(result_) = info;
+ }
+
+ virtual void OnReceivedData(int bytes_read) OVERRIDE {
+ if (download_to_file_)
+ file_stream_->WriteSync(buf_->data(), bytes_read);
+ else
+ result_->data.append(buf_->data(), bytes_read);
+ AsyncReadData(); // read more (may recurse)
+ }
+
+ virtual void OnCompletedRequest(
+ int error_code,
+ const std::string& security_info,
+ const base::TimeTicks& complete_time) OVERRIDE {
+ if (download_to_file_)
+ file_stream_.reset();
+ result_->error_code = error_code;
+ event_.Signal();
+ }
+
+ protected:
+ virtual ~SyncRequestProxy() {}
+
+ private:
+ ResourceLoaderBridge::SyncLoadResponse* result_;
+ base::WaitableEvent event_;
+};
+
+//-----------------------------------------------------------------------------
+
+class ResourceLoaderBridgeImpl : public ResourceLoaderBridge {
+ public:
+ ResourceLoaderBridgeImpl(
+ const webkit_glue::ResourceLoaderBridge::RequestInfo& request_info)
+ : params_(new RequestParams),
+ proxy_(NULL) {
+ params_->method = request_info.method;
+ params_->url = request_info.url;
+ params_->first_party_for_cookies = request_info.first_party_for_cookies;
+ params_->referrer = request_info.referrer;
+ params_->referrer_policy = request_info.referrer_policy;
+ params_->headers = request_info.headers;
+ params_->load_flags = request_info.load_flags;
+ params_->request_type = request_info.request_type;
+ params_->appcache_host_id = request_info.appcache_host_id;
+ params_->download_to_file = request_info.download_to_file;
+ }
+
+ virtual ~ResourceLoaderBridgeImpl() {
+ if (proxy_) {
+ proxy_->DropPeer();
+ // Let the proxy die on the IO thread
+ g_io_thread->message_loop()->ReleaseSoon(FROM_HERE, proxy_);
+ }
+ }
+
+ // --------------------------------------------------------------------------
+ // ResourceLoaderBridge implementation:
+
+ virtual void SetRequestBody(ResourceRequestBody* request_body) OVERRIDE {
+ DCHECK(params_.get());
+ DCHECK(!params_->request_body.get());
+ params_->request_body = request_body;
+ }
+
+ virtual bool Start(Peer* peer) OVERRIDE {
+ DCHECK(!proxy_);
+
+ if (!SimpleResourceLoaderBridge::EnsureIOThread())
+ return false;
+
+ proxy_ = new RequestProxy();
+ proxy_->AddRef();
+
+ proxy_->Start(peer, params_.release());
+
+ return true; // Any errors will be reported asynchronously.
+ }
+
+ virtual void Cancel() OVERRIDE {
+ DCHECK(proxy_);
+ proxy_->Cancel();
+ }
+
+ virtual void SetDefersLoading(bool value) OVERRIDE {
+ // TODO(darin): implement me
+ }
+
+ virtual void SyncLoad(SyncLoadResponse* response) OVERRIDE {
+ DCHECK(!proxy_);
+
+ if (!SimpleResourceLoaderBridge::EnsureIOThread())
+ return;
+
+ // this may change as the result of a redirect
+ response->url = params_->url;
+
+ proxy_ = new SyncRequestProxy(response);
+ proxy_->AddRef();
+
+ proxy_->Start(NULL, params_.release());
+
+ static_cast<SyncRequestProxy*>(proxy_)->WaitForCompletion();
+ }
+
+ virtual void DidChangePriority(net::RequestPriority new_priority) OVERRIDE {
+ // Not really needed for DRT.
+ }
+
+ private:
+ // Ownership of params_ is transfered to the proxy when the proxy is created.
+ scoped_ptr<RequestParams> params_;
+
+ // The request proxy is allocated when we start the request, and then it
+ // sticks around until this ResourceLoaderBridge is destroyed.
+ RequestProxy* proxy_;
+};
+
+//-----------------------------------------------------------------------------
+
+class CookieSetter : public base::RefCountedThreadSafe<CookieSetter> {
+ public:
+ void Set(const GURL& url, const std::string& cookie) {
+ DCHECK(base::MessageLoop::current() == g_io_thread->message_loop());
+ g_request_context->cookie_store()->SetCookieWithOptionsAsync(
+ url, cookie, net::CookieOptions(),
+ net::CookieStore::SetCookiesCallback());
+ }
+
+ private:
+ friend class base::RefCountedThreadSafe<CookieSetter>;
+ ~CookieSetter() {}
+};
+
+class CookieGetter : public base::RefCountedThreadSafe<CookieGetter> {
+ public:
+ CookieGetter() : event_(false, false) {
+ }
+
+ void Get(const GURL& url) {
+ g_request_context->cookie_store()->GetCookiesWithOptionsAsync(
+ url, net::CookieOptions(),
+ base::Bind(&CookieGetter::OnGetCookies, this));
+ }
+
+ std::string GetResult() {
+ event_.Wait();
+ return result_;
+ }
+
+ private:
+ friend class base::RefCountedThreadSafe<CookieGetter>;
+ ~CookieGetter() {}
+
+ void OnGetCookies(const std::string& cookie_line) {
+ result_ = cookie_line;
+ event_.Signal();
+ }
+
+ base::WaitableEvent event_;
+ std::string result_;
+};
+
+} // anonymous namespace
+
+//-----------------------------------------------------------------------------
+
+// static
+void SimpleResourceLoaderBridge::Init(
+ const base::FilePath& cache_path,
+ net::HttpCache::Mode cache_mode,
+ bool no_proxy) {
+ // Make sure to stop any existing IO thread since it may be using the
+ // current request context.
+ Shutdown();
+
+ DCHECK(!g_request_context_params);
+ DCHECK(!g_request_context);
+ DCHECK(!g_network_delegate);
+ DCHECK(!g_io_thread);
+
+ g_request_context_params = new TestShellRequestContextParams(
+ cache_path, cache_mode, no_proxy);
+}
+
+// static
+void SimpleResourceLoaderBridge::Shutdown() {
+ if (g_io_thread) {
+ delete g_io_thread;
+ g_io_thread = NULL;
+
+ DCHECK(g_cache_thread);
+ delete g_cache_thread;
+ g_cache_thread = NULL;
+
+ DCHECK(!g_request_context) << "should have been nulled by thread dtor";
+ DCHECK(!g_network_delegate) << "should have been nulled by thread dtor";
+ } else {
+ delete g_request_context_params;
+ g_request_context_params = NULL;
+
+ delete g_file_over_http_mappings;
+ g_file_over_http_mappings = NULL;
+ }
+}
+
+// static
+void SimpleResourceLoaderBridge::SetCookie(const GURL& url,
+ const GURL& first_party_for_cookies,
+ const std::string& cookie) {
+ // Proxy to IO thread to synchronize w/ network loading.
+
+ if (!EnsureIOThread()) {
+ NOTREACHED();
+ return;
+ }
+
+ scoped_refptr<CookieSetter> cookie_setter(new CookieSetter());
+ g_io_thread->message_loop()->PostTask(
+ FROM_HERE,
+ base::Bind(&CookieSetter::Set, cookie_setter.get(), url, cookie));
+}
+
+// static
+std::string SimpleResourceLoaderBridge::GetCookies(
+ const GURL& url, const GURL& first_party_for_cookies) {
+ // Proxy to IO thread to synchronize w/ network loading
+
+ if (!EnsureIOThread()) {
+ NOTREACHED();
+ return std::string();
+ }
+
+ scoped_refptr<CookieGetter> getter(new CookieGetter());
+
+ g_io_thread->message_loop()->PostTask(
+ FROM_HERE,
+ base::Bind(&CookieGetter::Get, getter.get(), url));
+
+ return getter->GetResult();
+}
+
+// static
+bool SimpleResourceLoaderBridge::EnsureIOThread() {
+ if (g_io_thread)
+ return true;
+
+#if defined(OS_MACOSX) || defined(OS_WIN)
+ // We want to be sure to init NSPR on the main thread.
+ crypto::EnsureNSPRInit();
+#endif
+
+ // Create the cache thread. We want the cache thread to outlive the IO thread,
+ // so its lifetime is bonded to the IO thread lifetime.
+ DCHECK(!g_cache_thread);
+ g_cache_thread = new base::Thread("cache");
+ CHECK(g_cache_thread->StartWithOptions(
+ base::Thread::Options(base::MessageLoop::TYPE_IO, 0)));
+
+ g_io_thread = new IOThread();
+ base::Thread::Options options;
+ options.message_loop_type = base::MessageLoop::TYPE_IO;
+ return g_io_thread->StartWithOptions(options);
+}
+
+// static
+void SimpleResourceLoaderBridge::SetAcceptAllCookies(bool accept_all_cookies) {
+ g_accept_all_cookies = accept_all_cookies;
+}
+
+// static
+scoped_refptr<base::MessageLoopProxy>
+ SimpleResourceLoaderBridge::GetCacheThread() {
+ return g_cache_thread->message_loop_proxy();
+}
+
+// static
+scoped_refptr<base::MessageLoopProxy>
+ SimpleResourceLoaderBridge::GetIoThread() {
+ if (!EnsureIOThread()) {
+ LOG(DFATAL) << "Failed to create IO thread.";
+ return NULL;
+ }
+ return g_io_thread->message_loop_proxy();
+}
+
+// static
+void SimpleResourceLoaderBridge::AllowFileOverHTTP(
+ const std::string& file_path_template, const GURL& http_prefix) {
+ DCHECK(!file_path_template.empty());
+ DCHECK(http_prefix.is_valid() &&
+ (http_prefix.SchemeIs("http") || http_prefix.SchemeIs("https")));
+ if (!g_file_over_http_mappings)
+ g_file_over_http_mappings = new FileOverHTTPPathMappings();
+ g_file_over_http_mappings->AddMapping(file_path_template, http_prefix);
+}
+
+// static
+webkit_glue::ResourceLoaderBridge* SimpleResourceLoaderBridge::Create(
+ const webkit_glue::ResourceLoaderBridge::RequestInfo& request_info) {
+ return new ResourceLoaderBridgeImpl(request_info);
+}
diff --git a/webkit/support/simple_resource_loader_bridge.h b/webkit/support/simple_resource_loader_bridge.h
new file mode 100644
index 0000000..ea73ee7
--- /dev/null
+++ b/webkit/support/simple_resource_loader_bridge.h
@@ -0,0 +1,61 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef WEBKIT_SUPPORT_SIMPLE_RESOURCE_LOADER_BRIDGE_H__
+#define WEBKIT_SUPPORT_SIMPLE_RESOURCE_LOADER_BRIDGE_H__
+
+#include <string>
+#include "base/message_loop_proxy.h"
+#include "net/http/http_cache.h"
+#include "webkit/glue/resource_loader_bridge.h"
+
+class GURL;
+
+namespace base {
+class FilePath;
+}
+
+class SimpleResourceLoaderBridge {
+ public:
+ // Call this function to initialize the simple resource loader bridge.
+ // It is safe to call this function multiple times.
+ //
+ // NOTE: If this function is not called, then a default request context will
+ // be initialized lazily.
+ //
+ static void Init(const base::FilePath& cache_path,
+ net::HttpCache::Mode cache_mode,
+ bool no_proxy);
+
+ // Call this function to shutdown the simple resource loader bridge.
+ static void Shutdown();
+
+ // May only be called after Init.
+ static void SetCookie(const GURL& url,
+ const GURL& first_party_for_cookies,
+ const std::string& cookie);
+ static std::string GetCookies(const GURL& url,
+ const GURL& first_party_for_cookies);
+ static bool EnsureIOThread();
+ static void SetAcceptAllCookies(bool accept_all_cookies);
+
+ // These methods should only be called after Init(), and before
+ // Shutdown(). The MessageLoops get replaced upon each call to
+ // Init(), and destroyed upon a call to ShutDown().
+ static scoped_refptr<base::MessageLoopProxy> GetCacheThread();
+ static scoped_refptr<base::MessageLoopProxy> GetIoThread();
+
+ // Call this function to set up a redirection using the file-over-http
+ // feature. If redirections are set up, request using the file scheme which
+ // match |file_path_template| will be rewritten to the |http_prefix| plus
+ // the path that follows after the |file_path_template| in the request.
+ static void AllowFileOverHTTP(const std::string& file_path_template,
+ const GURL& http_prefix);
+
+ // Creates a ResourceLoaderBridge instance.
+ static webkit_glue::ResourceLoaderBridge* Create(
+ const webkit_glue::ResourceLoaderBridge::RequestInfo& request_info);
+};
+
+#endif // WEBKIT_SUPPORT_SIMPLE_RESOURCE_LOADER_BRIDGE_H__
diff --git a/webkit/support/simple_socket_stream_bridge.cc b/webkit/support/simple_socket_stream_bridge.cc
new file mode 100644
index 0000000..0dce0c0
--- /dev/null
+++ b/webkit/support/simple_socket_stream_bridge.cc
@@ -0,0 +1,259 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "webkit/support/simple_socket_stream_bridge.h"
+
+#include <vector>
+
+#include "base/atomicops.h"
+#include "base/bind.h"
+#include "base/memory/ref_counted.h"
+#include "base/message_loop.h"
+#include "base/utf_string_conversions.h"
+#include "googleurl/src/gurl.h"
+#include "net/socket_stream/socket_stream_job.h"
+#include "net/url_request/url_request_context.h"
+#include "net/websockets/websocket_job.h"
+#include "third_party/WebKit/public/platform/WebSocketStreamHandle.h"
+#include "webkit/glue/websocketstreamhandle_bridge.h"
+#include "webkit/glue/websocketstreamhandle_delegate.h"
+
+using webkit_glue::WebSocketStreamHandleBridge;
+
+const int kNoSocketId = 0;
+
+namespace {
+
+base::MessageLoop* g_io_thread;
+net::URLRequestContext* g_request_context;
+
+class WebSocketStreamHandleBridgeImpl
+ : public WebSocketStreamHandleBridge,
+ public net::SocketStream::Delegate {
+ public:
+ WebSocketStreamHandleBridgeImpl(
+ WebKit::WebSocketStreamHandle* handle,
+ webkit_glue::WebSocketStreamHandleDelegate* delegate);
+
+ // WebSocketStreamHandleBridge methods.
+ virtual void Connect(const GURL& url) OVERRIDE;
+ virtual bool Send(const std::vector<char>& data) OVERRIDE;
+ virtual void Close() OVERRIDE;
+
+ // net::SocketStream::Delegate methods.
+ virtual void OnConnected(net::SocketStream* req,
+ int max_pending_send_allowed) OVERRIDE;
+ virtual void OnSentData(net::SocketStream* req,
+ int amount_sent) OVERRIDE;
+ virtual void OnReceivedData(net::SocketStream* req,
+ const char* data, int len) OVERRIDE;
+ virtual void OnClose(net::SocketStream* req) OVERRIDE;
+ virtual void OnError(const net::SocketStream* req, int error_code) OVERRIDE;
+
+ private:
+ virtual ~WebSocketStreamHandleBridgeImpl();
+
+ // Runs on |g_io_thread|;
+ void DoConnect(const GURL& url);
+ void DoSend(std::vector<char>* data);
+ void DoClose();
+
+ // Runs on |message_loop_|;
+ void DoOnConnected(int max_amount_send_allowed);
+ void DoOnSentData(int amount_sent);
+ void DoOnReceivedData(std::vector<char>* data);
+ void DoOnClose();
+ void DoOnError(int error_code, const char* error_msg);
+
+ int socket_id_;
+ base::MessageLoop* message_loop_;
+ WebKit::WebSocketStreamHandle* handle_;
+ webkit_glue::WebSocketStreamHandleDelegate* delegate_;
+
+ scoped_refptr<net::SocketStreamJob> socket_;
+ // Number of pending tasks to handle net::SocketStream::Delegate methods.
+ base::subtle::Atomic32 num_pending_tasks_;
+
+ DISALLOW_COPY_AND_ASSIGN(WebSocketStreamHandleBridgeImpl);
+};
+
+WebSocketStreamHandleBridgeImpl::WebSocketStreamHandleBridgeImpl(
+ WebKit::WebSocketStreamHandle* handle,
+ webkit_glue::WebSocketStreamHandleDelegate* delegate)
+ : socket_id_(kNoSocketId),
+ message_loop_(base::MessageLoop::current()),
+ handle_(handle),
+ delegate_(delegate),
+ num_pending_tasks_(0) {
+ net::WebSocketJob::EnsureInit();
+}
+
+WebSocketStreamHandleBridgeImpl::~WebSocketStreamHandleBridgeImpl() {
+ DCHECK_EQ(socket_id_, kNoSocketId);
+}
+
+void WebSocketStreamHandleBridgeImpl::Connect(const GURL& url) {
+ DCHECK(g_io_thread);
+ AddRef(); // Released in DoOnClose().
+ g_io_thread->PostTask(
+ FROM_HERE,
+ base::Bind(&WebSocketStreamHandleBridgeImpl::DoConnect, this, url));
+ if (delegate_)
+ delegate_->WillOpenStream(handle_, url);
+}
+
+bool WebSocketStreamHandleBridgeImpl::Send(
+ const std::vector<char>& data) {
+ DCHECK(g_io_thread);
+ g_io_thread->PostTask(
+ FROM_HERE,
+ base::Bind(&WebSocketStreamHandleBridgeImpl::DoSend, this,
+ new std::vector<char>(data)));
+ return true;
+}
+
+void WebSocketStreamHandleBridgeImpl::Close() {
+ DCHECK(g_io_thread);
+ g_io_thread->PostTask(
+ FROM_HERE,
+ base::Bind(&WebSocketStreamHandleBridgeImpl::DoClose, this));
+}
+
+void WebSocketStreamHandleBridgeImpl::OnConnected(
+ net::SocketStream* socket, int max_pending_send_allowed) {
+ base::subtle::NoBarrier_AtomicIncrement(&num_pending_tasks_, 1);
+ message_loop_->PostTask(
+ FROM_HERE,
+ base::Bind(&WebSocketStreamHandleBridgeImpl::DoOnConnected, this,
+ max_pending_send_allowed));
+}
+
+void WebSocketStreamHandleBridgeImpl::OnSentData(
+ net::SocketStream* socket, int amount_sent) {
+ base::subtle::NoBarrier_AtomicIncrement(&num_pending_tasks_, 1);
+ message_loop_->PostTask(
+ FROM_HERE,
+ base::Bind(&WebSocketStreamHandleBridgeImpl::DoOnSentData, this,
+ amount_sent));
+}
+
+void WebSocketStreamHandleBridgeImpl::OnReceivedData(
+ net::SocketStream* socket, const char* data, int len) {
+ base::subtle::NoBarrier_AtomicIncrement(&num_pending_tasks_, 1);
+ message_loop_->PostTask(
+ FROM_HERE,
+ base::Bind(&WebSocketStreamHandleBridgeImpl::DoOnReceivedData, this,
+ new std::vector<char>(data, data + len)));
+}
+
+void WebSocketStreamHandleBridgeImpl::OnClose(net::SocketStream* socket) {
+ base::subtle::NoBarrier_AtomicIncrement(&num_pending_tasks_, 1);
+ // Release socket_ on IO thread.
+ socket_ = NULL;
+ socket_id_ = kNoSocketId;
+ message_loop_->PostTask(
+ FROM_HERE,
+ base::Bind(&WebSocketStreamHandleBridgeImpl::DoOnClose, this));
+}
+
+void WebSocketStreamHandleBridgeImpl::OnError(
+ const net::SocketStream* socket, int error_code) {
+ base::subtle::NoBarrier_AtomicIncrement(&num_pending_tasks_, 1);
+ message_loop_->PostTask(
+ FROM_HERE,
+ base::Bind(&WebSocketStreamHandleBridgeImpl::DoOnError, this,
+ error_code, net::ErrorToString(error_code)));
+}
+
+void WebSocketStreamHandleBridgeImpl::DoConnect(const GURL& url) {
+ DCHECK(base::MessageLoop::current() == g_io_thread);
+ socket_ = net::SocketStreamJob::CreateSocketStreamJob(
+ url, this, g_request_context->transport_security_state(),
+ g_request_context->ssl_config_service());
+ socket_->set_context(g_request_context);
+ socket_->Connect();
+}
+
+void WebSocketStreamHandleBridgeImpl::DoSend(std::vector<char>* data) {
+ DCHECK(base::MessageLoop::current() == g_io_thread);
+ scoped_ptr<std::vector<char> > scoped_data(data);
+ if (!socket_.get())
+ return;
+ if (!socket_->SendData(&(data->at(0)), data->size()))
+ socket_->Close();
+}
+
+void WebSocketStreamHandleBridgeImpl::DoClose() {
+ DCHECK(base::MessageLoop::current() == g_io_thread);
+ if (!socket_.get())
+ return;
+ socket_->Close();
+}
+
+void WebSocketStreamHandleBridgeImpl::DoOnConnected(
+ int max_pending_send_allowed) {
+ DCHECK(base::MessageLoop::current() == message_loop_);
+ base::subtle::NoBarrier_AtomicIncrement(&num_pending_tasks_, -1);
+ if (delegate_)
+ delegate_->DidOpenStream(handle_, max_pending_send_allowed);
+}
+
+void WebSocketStreamHandleBridgeImpl::DoOnSentData(int amount_sent) {
+ DCHECK(base::MessageLoop::current() == message_loop_);
+ base::subtle::NoBarrier_AtomicIncrement(&num_pending_tasks_, -1);
+ if (delegate_)
+ delegate_->DidSendData(handle_, amount_sent);
+}
+
+void WebSocketStreamHandleBridgeImpl::DoOnReceivedData(
+ std::vector<char>* data) {
+ DCHECK(base::MessageLoop::current() == message_loop_);
+ base::subtle::NoBarrier_AtomicIncrement(&num_pending_tasks_, -1);
+ scoped_ptr<std::vector<char> > scoped_data(data);
+ if (delegate_)
+ delegate_->DidReceiveData(handle_, &(data->at(0)), data->size());
+}
+
+void WebSocketStreamHandleBridgeImpl::DoOnClose() {
+ DCHECK(base::MessageLoop::current() == message_loop_);
+ base::subtle::NoBarrier_AtomicIncrement(&num_pending_tasks_, -1);
+ // Don't handle OnClose if there are pending tasks.
+ DCHECK_EQ(num_pending_tasks_, 0);
+ DCHECK(!socket_.get());
+ DCHECK_EQ(socket_id_, kNoSocketId);
+ webkit_glue::WebSocketStreamHandleDelegate* delegate = delegate_;
+ delegate_ = NULL;
+ if (delegate)
+ delegate->DidClose(handle_);
+ Release();
+}
+
+void WebSocketStreamHandleBridgeImpl::DoOnError(
+ int error_code, const char* error_msg) {
+ DCHECK(base::MessageLoop::current() == message_loop_);
+ base::subtle::NoBarrier_AtomicIncrement(&num_pending_tasks_, -1);
+ if (delegate_)
+ delegate_->DidFail(handle_, error_code, ASCIIToUTF16(error_msg));
+}
+
+} // namespace
+
+/* static */
+void SimpleSocketStreamBridge::InitializeOnIOThread(
+ net::URLRequestContext* request_context) {
+ g_io_thread = base::MessageLoop::current();
+ g_request_context = request_context;
+}
+
+void SimpleSocketStreamBridge::Cleanup() {
+ g_io_thread = NULL;
+ g_request_context = NULL;
+}
+
+/* static */
+webkit_glue::WebSocketStreamHandleBridge* SimpleSocketStreamBridge::Create(
+ WebKit::WebSocketStreamHandle* handle,
+ webkit_glue::WebSocketStreamHandleDelegate* delegate) {
+ return new WebSocketStreamHandleBridgeImpl(handle, delegate);
+}
diff --git a/webkit/support/simple_socket_stream_bridge.h b/webkit/support/simple_socket_stream_bridge.h
new file mode 100644
index 0000000..a68e3f1
--- /dev/null
+++ b/webkit/support/simple_socket_stream_bridge.h
@@ -0,0 +1,35 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef WEBKIT_SUPPORT_SIMPLE_SOCKET_STREAM_BRIDGE_H_
+#define WEBKIT_SUPPORT_SIMPLE_SOCKET_STREAM_BRIDGE_H_
+
+#include "base/basictypes.h"
+
+namespace net {
+class URLRequestContext;
+} // namespace net
+
+namespace WebKit {
+class WebSocketStreamHandle;
+} // namespace WebKit
+
+namespace webkit_glue {
+class WebSocketStreamHandleDelegate;
+class WebSocketStreamHandleBridge;
+} // namespace webkit_glue
+
+class SimpleSocketStreamBridge {
+ public:
+ static void InitializeOnIOThread(net::URLRequestContext* request_context);
+ static void Cleanup();
+ static webkit_glue::WebSocketStreamHandleBridge* Create(
+ WebKit::WebSocketStreamHandle* handle,
+ webkit_glue::WebSocketStreamHandleDelegate* delegate);
+
+ private:
+ DISALLOW_IMPLICIT_CONSTRUCTORS(SimpleSocketStreamBridge);
+};
+
+#endif // WEBKIT_SUPPORT_SIMPLE_SOCKET_STREAM_BRIDGE_H_
diff --git a/webkit/support/simple_webcookiejar_impl.cc b/webkit/support/simple_webcookiejar_impl.cc
new file mode 100644
index 0000000..771d6f4
--- /dev/null
+++ b/webkit/support/simple_webcookiejar_impl.cc
@@ -0,0 +1,25 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "webkit/support/simple_webcookiejar_impl.h"
+
+#include "third_party/WebKit/public/platform/WebURL.h"
+#include "webkit/support/simple_resource_loader_bridge.h"
+
+using WebKit::WebString;
+using WebKit::WebURL;
+
+void SimpleWebCookieJarImpl::setCookie(const WebURL& url,
+ const WebURL& first_party_for_cookies,
+ const WebString& value) {
+ SimpleResourceLoaderBridge::SetCookie(
+ url, first_party_for_cookies, value.utf8());
+}
+
+WebString SimpleWebCookieJarImpl::cookies(
+ const WebURL& url,
+ const WebURL& first_party_for_cookies) {
+ return WebString::fromUTF8(
+ SimpleResourceLoaderBridge::GetCookies(url, first_party_for_cookies));
+}
diff --git a/webkit/support/simple_webcookiejar_impl.h b/webkit/support/simple_webcookiejar_impl.h
new file mode 100644
index 0000000..cb89d03
--- /dev/null
+++ b/webkit/support/simple_webcookiejar_impl.h
@@ -0,0 +1,22 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef WEBKIT_SUPPORT_SIMPLE_WEBCOOKIEJAR_IMPL_H_
+#define WEBKIT_SUPPORT_SIMPLE_WEBCOOKIEJAR_IMPL_H_
+
+// TODO(darin): WebCookieJar.h is missing a WebString.h include!
+#include "third_party/WebKit/public/platform/WebCookieJar.h"
+#include "third_party/WebKit/public/platform/WebString.h"
+
+class SimpleWebCookieJarImpl : public WebKit::WebCookieJar {
+ public:
+ // WebKit::WebCookieJar methods:
+ virtual void setCookie(
+ const WebKit::WebURL& url, const WebKit::WebURL& first_party_for_cookies,
+ const WebKit::WebString& cookie);
+ virtual WebKit::WebString cookies(
+ const WebKit::WebURL& url, const WebKit::WebURL& first_party_for_cookies);
+};
+
+#endif // WEBKIT_SUPPORT_SIMPLE_WEBCOOKIEJAR_IMPL_H_
diff --git a/webkit/support/test_shell_dummy.cc b/webkit/support/test_shell_dummy.cc
new file mode 100644
index 0000000..e1a88a9
--- /dev/null
+++ b/webkit/support/test_shell_dummy.cc
@@ -0,0 +1,7 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// TODO(darin): Delete this once the build masters stop referencing test_shell.
+void Dummy() {
+}
diff --git a/webkit/support/test_shell_request_context.cc b/webkit/support/test_shell_request_context.cc
new file mode 100644
index 0000000..f2c31ba
--- /dev/null
+++ b/webkit/support/test_shell_request_context.cc
@@ -0,0 +1,140 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "webkit/support/test_shell_request_context.h"
+
+#include "base/compiler_specific.h"
+#include "base/files/file_path.h"
+#include "base/thread_task_runner_handle.h"
+#include "base/threading/worker_pool.h"
+#include "build/build_config.h"
+#include "net/base/cache_type.h"
+#include "net/cert/cert_verifier.h"
+#include "net/cookies/cookie_monster.h"
+#include "net/dns/host_resolver.h"
+#include "net/http/http_auth_handler_factory.h"
+#include "net/http/http_network_session.h"
+#include "net/http/http_server_properties_impl.h"
+#include "net/proxy/proxy_config_service.h"
+#include "net/proxy/proxy_config_service_fixed.h"
+#include "net/proxy/proxy_service.h"
+#include "net/ssl/default_server_bound_cert_store.h"
+#include "net/ssl/server_bound_cert_service.h"
+#include "net/ssl/ssl_config_service_defaults.h"
+#include "net/url_request/data_protocol_handler.h"
+#include "net/url_request/file_protocol_handler.h"
+#include "net/url_request/http_user_agent_settings.h"
+#include "net/url_request/url_request_job_factory_impl.h"
+#include "third_party/WebKit/public/platform/Platform.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebKit.h"
+#include "webkit/browser/blob/blob_storage_controller.h"
+#include "webkit/browser/blob/blob_url_request_job_factory.h"
+#include "webkit/browser/fileapi/file_system_context.h"
+#include "webkit/browser/fileapi/file_system_url_request_job_factory.h"
+#include "webkit/common/user_agent/user_agent.h"
+#include "webkit/support/simple_file_system.h"
+#include "webkit/support/simple_resource_loader_bridge.h"
+
+class TestShellHttpUserAgentSettings : public net::HttpUserAgentSettings {
+ public:
+ TestShellHttpUserAgentSettings() {}
+ virtual ~TestShellHttpUserAgentSettings() {}
+
+ // Hard-code Accept-Language for test shells.
+ virtual std::string GetAcceptLanguage() const OVERRIDE {
+ return "en-us,en";
+ }
+
+ virtual std::string GetUserAgent(const GURL& url) const OVERRIDE {
+ return webkit_glue::GetUserAgent(url);
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TestShellHttpUserAgentSettings);
+};
+
+TestShellRequestContext::TestShellRequestContext()
+ : storage_(this) {
+ Init(base::FilePath(), net::HttpCache::NORMAL, false);
+}
+
+TestShellRequestContext::TestShellRequestContext(
+ const base::FilePath& cache_path,
+ net::HttpCache::Mode cache_mode,
+ bool no_proxy)
+ : storage_(this) {
+ Init(cache_path, cache_mode, no_proxy);
+}
+
+void TestShellRequestContext::Init(
+ const base::FilePath& cache_path,
+ net::HttpCache::Mode cache_mode,
+ bool no_proxy) {
+ storage_.set_cookie_store(new net::CookieMonster(NULL, NULL));
+ storage_.set_server_bound_cert_service(new net::ServerBoundCertService(
+ new net::DefaultServerBoundCertStore(NULL),
+ base::WorkerPool::GetTaskRunner(true)));
+
+ storage_.set_http_user_agent_settings(new TestShellHttpUserAgentSettings);
+
+ // Use no proxy; it's not needed for testing and just breaks things.
+ scoped_ptr<net::ProxyConfigService> proxy_config_service(
+ new net::ProxyConfigServiceFixed(net::ProxyConfig()));
+
+ storage_.set_host_resolver(net::HostResolver::CreateDefaultResolver(NULL));
+ storage_.set_cert_verifier(net::CertVerifier::CreateDefault());
+ storage_.set_proxy_service(net::ProxyService::CreateUsingSystemProxyResolver(
+ proxy_config_service.release(), 0, NULL));
+ storage_.set_ssl_config_service(
+ new net::SSLConfigServiceDefaults);
+
+ storage_.set_http_auth_handler_factory(
+ net::HttpAuthHandlerFactory::CreateDefault(host_resolver()));
+ storage_.set_http_server_properties(
+ new net::HttpServerPropertiesImpl);
+
+ net::HttpCache::DefaultBackend* backend = new net::HttpCache::DefaultBackend(
+ cache_path.empty() ? net::MEMORY_CACHE : net::DISK_CACHE,
+ net::CACHE_BACKEND_DEFAULT, cache_path, 0,
+ SimpleResourceLoaderBridge::GetCacheThread());
+
+ net::HttpNetworkSession::Params network_session_params;
+ network_session_params.host_resolver = host_resolver();
+ network_session_params.cert_verifier = cert_verifier();
+ network_session_params.server_bound_cert_service =
+ server_bound_cert_service();
+ network_session_params.proxy_service = proxy_service();
+ network_session_params.ssl_config_service = ssl_config_service();
+ network_session_params.http_auth_handler_factory =
+ http_auth_handler_factory();
+ network_session_params.http_server_properties = http_server_properties();
+ network_session_params.host_resolver = host_resolver();
+
+ net::HttpCache* cache = new net::HttpCache(
+ network_session_params, backend);
+ cache->set_mode(cache_mode);
+ storage_.set_http_transaction_factory(cache);
+
+ blob_storage_controller_.reset(new webkit_blob::BlobStorageController());
+ file_system_context_ = static_cast<SimpleFileSystem*>(
+ WebKit::Platform::current()->fileSystem())->file_system_context();
+
+ net::URLRequestJobFactoryImpl* job_factory =
+ new net::URLRequestJobFactoryImpl();
+ job_factory->SetProtocolHandler(
+ "blob",
+ new webkit_blob::BlobProtocolHandler(
+ blob_storage_controller_.get(),
+ file_system_context_.get(),
+ SimpleResourceLoaderBridge::GetIoThread()));
+ job_factory->SetProtocolHandler(
+ "filesystem",
+ fileapi::CreateFileSystemProtocolHandler(file_system_context_.get()));
+ job_factory->SetProtocolHandler("data", new net::DataProtocolHandler);
+ job_factory->SetProtocolHandler("file", new net::FileProtocolHandler);
+ storage_.set_job_factory(job_factory);
+}
+
+TestShellRequestContext::~TestShellRequestContext() {
+}
diff --git a/webkit/support/test_shell_request_context.h b/webkit/support/test_shell_request_context.h
new file mode 100644
index 0000000..40d36f5
--- /dev/null
+++ b/webkit/support/test_shell_request_context.h
@@ -0,0 +1,56 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef WEBKIT_SUPPORT_TEST_SHELL_REQUEST_CONTEXT_H_
+#define WEBKIT_SUPPORT_TEST_SHELL_REQUEST_CONTEXT_H_
+
+#include "base/threading/thread.h"
+#include "net/http/http_cache.h"
+#include "net/url_request/url_request_context.h"
+#include "net/url_request/url_request_context_storage.h"
+
+namespace base {
+class FilePath;
+}
+
+namespace fileapi {
+class FileSystemContext;
+}
+
+namespace webkit_blob {
+class BlobStorageController;
+}
+
+// A basic net::URLRequestContext that only provides an in-memory cookie store.
+class TestShellRequestContext : public net::URLRequestContext {
+ public:
+ // Use an in-memory cache
+ TestShellRequestContext();
+
+ // Use an on-disk cache at the specified location. Optionally, use the cache
+ // in playback or record mode.
+ TestShellRequestContext(const base::FilePath& cache_path,
+ net::HttpCache::Mode cache_mode,
+ bool no_proxy);
+
+ virtual ~TestShellRequestContext();
+
+ webkit_blob::BlobStorageController* blob_storage_controller() const {
+ return blob_storage_controller_.get();
+ }
+
+ fileapi::FileSystemContext* file_system_context() const {
+ return file_system_context_.get();
+ }
+
+ private:
+ void Init(const base::FilePath& cache_path, net::HttpCache::Mode cache_mode,
+ bool no_proxy);
+
+ net::URLRequestContextStorage storage_;
+ scoped_ptr<webkit_blob::BlobStorageController> blob_storage_controller_;
+ scoped_refptr<fileapi::FileSystemContext> file_system_context_;
+};
+
+#endif // WEBKIT_SUPPORT_TEST_SHELL_REQUEST_CONTEXT_H_
diff --git a/webkit/support/test_shell_webblobregistry_impl.cc b/webkit/support/test_shell_webblobregistry_impl.cc
new file mode 100644
index 0000000..4228915
--- /dev/null
+++ b/webkit/support/test_shell_webblobregistry_impl.cc
@@ -0,0 +1,124 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "webkit/support/test_shell_webblobregistry_impl.h"
+
+#include "base/bind.h"
+#include "base/message_loop.h"
+#include "googleurl/src/gurl.h"
+#include "third_party/WebKit/public/platform/WebBlobData.h"
+#include "third_party/WebKit/public/platform/WebURL.h"
+#include "webkit/base/file_path_string_conversions.h"
+#include "webkit/browser/blob/blob_storage_controller.h"
+#include "webkit/common/blob/blob_data.h"
+
+using WebKit::WebBlobData;
+using WebKit::WebURL;
+using webkit_blob::BlobData;
+
+namespace {
+
+base::MessageLoop* g_io_thread;
+webkit_blob::BlobStorageController* g_blob_storage_controller;
+
+// Creates a new BlobData from WebBlobData.
+BlobData* NewBlobData(const WebBlobData& data) {
+ BlobData* blob = new BlobData;
+ size_t i = 0;
+ WebBlobData::Item item;
+ while (data.itemAt(i++, item)) {
+ switch (item.type) {
+ case WebBlobData::Item::TypeData:
+ if (!item.data.isEmpty()) {
+ // WebBlobData does not allow partial data.
+ DCHECK(!item.offset && item.length == -1);
+ blob->AppendData(item.data);
+ }
+ break;
+ case WebBlobData::Item::TypeFile:
+ if (item.length) {
+ blob->AppendFile(
+ webkit_base::WebStringToFilePath(item.filePath),
+ static_cast<uint64>(item.offset),
+ static_cast<uint64>(item.length),
+ base::Time::FromDoubleT(item.expectedModificationTime));
+ }
+ break;
+ case WebBlobData::Item::TypeBlob:
+ if (item.length) {
+ blob->AppendBlob(
+ item.blobURL,
+ static_cast<uint64>(item.offset),
+ static_cast<uint64>(item.length));
+ }
+ break;
+ default:
+ NOTREACHED();
+ }
+ }
+ blob->set_content_type(data.contentType().utf8().data());
+ blob->set_content_disposition(data.contentDisposition().utf8().data());
+ return blob;
+}
+
+} // namespace
+
+/* static */
+void TestShellWebBlobRegistryImpl::InitializeOnIOThread(
+ webkit_blob::BlobStorageController* blob_storage_controller) {
+ g_io_thread = base::MessageLoop::current();
+ g_blob_storage_controller = blob_storage_controller;
+}
+
+/* static */
+void TestShellWebBlobRegistryImpl::Cleanup() {
+ g_io_thread = NULL;
+ g_blob_storage_controller = NULL;
+}
+
+void TestShellWebBlobRegistryImpl::registerBlobURL(
+ const WebURL& url, WebBlobData& data) {
+ DCHECK(g_io_thread);
+ GURL thread_safe_url = url; // WebURL uses refcounted strings.
+ g_io_thread->PostTask(FROM_HERE, base::Bind(
+ &TestShellWebBlobRegistryImpl::AddFinishedBlob, this,
+ thread_safe_url, make_scoped_refptr(NewBlobData(data))));
+}
+
+void TestShellWebBlobRegistryImpl::registerBlobURL(
+ const WebURL& url, const WebURL& src_url) {
+ DCHECK(g_io_thread);
+ GURL thread_safe_url = url;
+ GURL thread_safe_src_url = src_url;
+ g_io_thread->PostTask(FROM_HERE, base::Bind(
+ &TestShellWebBlobRegistryImpl::CloneBlob, this,
+ thread_safe_url, thread_safe_src_url));
+}
+
+void TestShellWebBlobRegistryImpl::unregisterBlobURL(const WebURL& url) {
+ DCHECK(g_io_thread);
+ GURL thread_safe_url = url;
+ g_io_thread->PostTask(FROM_HERE, base::Bind(
+ &TestShellWebBlobRegistryImpl::RemoveBlob, this,
+ thread_safe_url));
+}
+
+TestShellWebBlobRegistryImpl::TestShellWebBlobRegistryImpl() {}
+
+void TestShellWebBlobRegistryImpl::AddFinishedBlob(
+ const GURL& url, BlobData* blob_data) {
+ DCHECK(g_blob_storage_controller);
+ g_blob_storage_controller->AddFinishedBlob(url, blob_data);
+}
+
+void TestShellWebBlobRegistryImpl::CloneBlob(
+ const GURL& url, const GURL& src_url) {
+ DCHECK(g_blob_storage_controller);
+ g_blob_storage_controller->CloneBlob(url, src_url);
+}
+
+void TestShellWebBlobRegistryImpl::RemoveBlob(const GURL& url) {
+ DCHECK(g_blob_storage_controller);
+ g_blob_storage_controller->RemoveBlob(url);
+}
diff --git a/webkit/support/test_shell_webblobregistry_impl.h b/webkit/support/test_shell_webblobregistry_impl.h
new file mode 100644
index 0000000..278ee1c
--- /dev/null
+++ b/webkit/support/test_shell_webblobregistry_impl.h
@@ -0,0 +1,49 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef WEBKIT_SUPPORT_TEST_SHELL_WEBBLOBREGISTRY_IMPL_H_
+#define WEBKIT_SUPPORT_TEST_SHELL_WEBBLOBREGISTRY_IMPL_H_
+
+#include "base/memory/ref_counted.h"
+#include "third_party/WebKit/public/platform/WebBlobRegistry.h"
+
+class GURL;
+
+namespace webkit_blob {
+class BlobData;
+class BlobStorageController;
+}
+
+class TestShellWebBlobRegistryImpl
+ : public WebKit::WebBlobRegistry,
+ public base::RefCountedThreadSafe<TestShellWebBlobRegistryImpl> {
+ public:
+ static void InitializeOnIOThread(
+ webkit_blob::BlobStorageController* blob_storage_controller);
+ static void Cleanup();
+
+ TestShellWebBlobRegistryImpl();
+
+ // See WebBlobRegistry.h for documentation on these functions.
+ virtual void registerBlobURL(const WebKit::WebURL& url,
+ WebKit::WebBlobData& data);
+ virtual void registerBlobURL(const WebKit::WebURL& url,
+ const WebKit::WebURL& src_url);
+ virtual void unregisterBlobURL(const WebKit::WebURL& url);
+
+ protected:
+ virtual ~TestShellWebBlobRegistryImpl() {}
+
+ private:
+ friend class base::RefCountedThreadSafe<TestShellWebBlobRegistryImpl>;
+
+ // Run on I/O thread.
+ void AddFinishedBlob(const GURL& url, webkit_blob::BlobData* blob_data);
+ void CloneBlob(const GURL& url, const GURL& src_url);
+ void RemoveBlob(const GURL& url);
+
+ DISALLOW_COPY_AND_ASSIGN(TestShellWebBlobRegistryImpl);
+};
+
+#endif // WEBKIT_SUPPORT_TEST_SHELL_WEBBLOBREGISTRY_IMPL_H_
diff --git a/webkit/support/test_shell_webmimeregistry_impl.cc b/webkit/support/test_shell_webmimeregistry_impl.cc
new file mode 100644
index 0000000..eab4b25
--- /dev/null
+++ b/webkit/support/test_shell_webmimeregistry_impl.cc
@@ -0,0 +1,70 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "webkit/support/test_shell_webmimeregistry_impl.h"
+
+#include "base/basictypes.h"
+#include "base/string_util.h"
+#include "net/base/mime_util.h"
+#include "third_party/WebKit/public/platform/WebString.h"
+
+using WebKit::WebString;
+using WebKit::WebMimeRegistry;
+
+namespace {
+
+// Convert a WebString to ASCII, falling back on an empty string in the case
+// of a non-ASCII string.
+std::string ToASCIIOrEmpty(const WebString& string) {
+ return IsStringASCII(string) ? UTF16ToASCII(string) : std::string();
+}
+
+} // namespace
+
+TestShellWebMimeRegistryImpl::TestShellWebMimeRegistryImpl() {
+ net::GetMediaTypesBlacklistedForTests(&blacklisted_media_types_);
+
+ net::GetMediaCodecsBlacklistedForTests(&blacklisted_media_codecs_);
+}
+
+TestShellWebMimeRegistryImpl::~TestShellWebMimeRegistryImpl() {}
+
+// Returns IsNotSupported if mime_type or any of the codecs are not supported.
+// Otherwse, defers to the real registry.
+WebMimeRegistry::SupportsType
+TestShellWebMimeRegistryImpl::supportsMediaMIMEType(
+ const WebString& mime_type,
+ const WebString& codecs,
+ const WebKit::WebString& key_system) {
+ if (IsBlacklistedMediaMimeType(ToASCIIOrEmpty(mime_type)))
+ return IsNotSupported;
+
+ std::vector<std::string> parsed_codecs;
+ net::ParseCodecString(ToASCIIOrEmpty(codecs), &parsed_codecs, true);
+ if (HasBlacklistedMediaCodecs(parsed_codecs))
+ return IsNotSupported;
+
+ return SimpleWebMimeRegistryImpl::supportsMediaMIMEType(
+ mime_type, codecs, key_system);
+}
+
+bool TestShellWebMimeRegistryImpl::IsBlacklistedMediaMimeType(
+ const std::string& mime_type) {
+ for (size_t i = 0; i < blacklisted_media_types_.size(); ++i) {
+ if (blacklisted_media_types_[i] == mime_type)
+ return true;
+ }
+ return false;
+}
+
+bool TestShellWebMimeRegistryImpl::HasBlacklistedMediaCodecs(
+ const std::vector<std::string>& codecs) {
+ for (size_t i = 0; i < codecs.size(); ++i) {
+ for (size_t j = 0; j < blacklisted_media_codecs_.size(); ++j) {
+ if (blacklisted_media_codecs_[j] == codecs[i])
+ return true;
+ }
+ }
+ return false;
+}
diff --git a/webkit/support/test_shell_webmimeregistry_impl.h b/webkit/support/test_shell_webmimeregistry_impl.h
new file mode 100644
index 0000000..b6e876d
--- /dev/null
+++ b/webkit/support/test_shell_webmimeregistry_impl.h
@@ -0,0 +1,45 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef WEBKIT_SUPPORT_TEST_SHELL_WEBMIMEREGISTRY_IMPL_H_
+#define WEBKIT_SUPPORT_TEST_SHELL_WEBMIMEREGISTRY_IMPL_H_
+
+#include <string>
+#include <vector>
+
+#include "base/compiler_specific.h"
+#include "base/hash_tables.h"
+#include "webkit/glue/simple_webmimeregistry_impl.h"
+
+class TestShellWebMimeRegistryImpl
+ : public webkit_glue::SimpleWebMimeRegistryImpl {
+ public:
+ TestShellWebMimeRegistryImpl();
+ virtual ~TestShellWebMimeRegistryImpl();
+
+ // Override to force that we only support types and codecs that are supported
+ // by all variations of Chromium.
+ //
+ // Media layout tests use canPlayType() to determine the test input files.
+ // Different flavours of Chromium support different codecs, which has an
+ // impact on how canPlayType() behaves. Since Chromium's baselines and
+ // expectations are generated against the common set of types, we need to
+ // prevent canPlayType() from indicating it supports other types when running
+ // layout tests.
+ virtual WebKit::WebMimeRegistry::SupportsType supportsMediaMIMEType(
+ const WebKit::WebString&,
+ const WebKit::WebString&,
+ const WebKit::WebString&) OVERRIDE;
+
+ private:
+ bool IsBlacklistedMediaMimeType(const std::string& mime_type);
+ bool HasBlacklistedMediaCodecs(const std::vector<std::string>& codecs);
+
+ std::vector<std::string> blacklisted_media_types_;
+ std::vector<std::string> blacklisted_media_codecs_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestShellWebMimeRegistryImpl);
+};
+
+#endif // WEBKIT_SUPPORT_TEST_SHELL_WEBMIMEREGISTRY_IMPL_H_
diff --git a/webkit/support/test_webkit_platform_support.cc b/webkit/support/test_webkit_platform_support.cc
index 28cee799..6e352e1 100644
--- a/webkit/support/test_webkit_platform_support.cc
+++ b/webkit/support/test_webkit_platform_support.cc
@@ -43,21 +43,21 @@
#include "webkit/plugins/npapi/plugin_list.h"
#include "webkit/renderer/compositor_bindings/web_compositor_support_impl.h"
#include "webkit/support/gc_extension.h"
+#include "webkit/support/mock_webclipboard_impl.h"
+#include "webkit/support/simple_appcache_system.h"
#include "webkit/support/simple_database_system.h"
+#include "webkit/support/simple_file_system.h"
+#include "webkit/support/simple_resource_loader_bridge.h"
+#include "webkit/support/simple_socket_stream_bridge.h"
+#include "webkit/support/simple_webcookiejar_impl.h"
+#include "webkit/support/test_shell_request_context.h"
+#include "webkit/support/test_shell_webblobregistry_impl.h"
#include "webkit/support/test_webmessageportchannel.h"
#include "webkit/support/web_audio_device_mock.h"
#include "webkit/support/web_gesture_curve_mock.h"
#include "webkit/support/web_layer_tree_view_impl_for_testing.h"
#include "webkit/support/webkit_support.h"
#include "webkit/support/weburl_loader_mock_factory.h"
-#include "webkit/tools/test_shell/mock_webclipboard_impl.h"
-#include "webkit/tools/test_shell/simple_appcache_system.h"
-#include "webkit/tools/test_shell/simple_file_system.h"
-#include "webkit/tools/test_shell/simple_resource_loader_bridge.h"
-#include "webkit/tools/test_shell/simple_socket_stream_bridge.h"
-#include "webkit/tools/test_shell/simple_webcookiejar_impl.h"
-#include "webkit/tools/test_shell/test_shell_request_context.h"
-#include "webkit/tools/test_shell/test_shell_webblobregistry_impl.h"
#if defined(OS_WIN)
#include "third_party/WebKit/public/platform/win/WebThemeEngine.h"
diff --git a/webkit/support/test_webkit_platform_support.h b/webkit/support/test_webkit_platform_support.h
index adc02c4..1a85dfa 100644
--- a/webkit/support/test_webkit_platform_support.h
+++ b/webkit/support/test_webkit_platform_support.h
@@ -13,14 +13,14 @@
#include "webkit/glue/webkitplatformsupport_impl.h"
#include "webkit/mocks/mock_webhyphenator.h"
#include "webkit/renderer/compositor_bindings/web_compositor_support_impl.h"
+#include "webkit/support/mock_webclipboard_impl.h"
+#include "webkit/support/simple_appcache_system.h"
#include "webkit/support/simple_database_system.h"
+#include "webkit/support/simple_dom_storage_system.h"
+#include "webkit/support/simple_file_system.h"
+#include "webkit/support/simple_webcookiejar_impl.h"
+#include "webkit/support/test_shell_webmimeregistry_impl.h"
#include "webkit/support/weburl_loader_mock_factory.h"
-#include "webkit/tools/test_shell/mock_webclipboard_impl.h"
-#include "webkit/tools/test_shell/simple_appcache_system.h"
-#include "webkit/tools/test_shell/simple_dom_storage_system.h"
-#include "webkit/tools/test_shell/simple_file_system.h"
-#include "webkit/tools/test_shell/simple_webcookiejar_impl.h"
-#include "webkit/tools/test_shell/test_shell_webmimeregistry_impl.h"
class TestShellWebBlobRegistryImpl;
diff --git a/webkit/support/webkit_support.cc b/webkit/support/webkit_support.cc
index 059586c..0da75ba 100644
--- a/webkit/support/webkit_support.cc
+++ b/webkit/support/webkit_support.cc
@@ -71,15 +71,15 @@
#include "webkit/renderer/media/webmediaplayer_ms.h"
#include "webkit/renderer/media/webmediaplayer_params.h"
#include "webkit/support/platform_support.h"
+#include "webkit/support/simple_appcache_system.h"
#include "webkit/support/simple_database_system.h"
+#include "webkit/support/simple_dom_storage_system.h"
+#include "webkit/support/simple_file_system.h"
+#include "webkit/support/simple_resource_loader_bridge.h"
#include "webkit/support/test_webidbfactory.h"
#include "webkit/support/test_webkit_platform_support.h"
#include "webkit/support/test_webplugin_page_delegate.h"
#include "webkit/support/web_layer_tree_view_impl_for_testing.h"
-#include "webkit/tools/test_shell/simple_appcache_system.h"
-#include "webkit/tools/test_shell/simple_dom_storage_system.h"
-#include "webkit/tools/test_shell/simple_file_system.h"
-#include "webkit/tools/test_shell/simple_resource_loader_bridge.h"
#if defined(OS_ANDROID)
#include "base/test/test_support_android.h"
diff --git a/webkit/support/webkit_support.gypi b/webkit/support/webkit_support.gypi
index a3c1f5a..a949875 100644
--- a/webkit/support/webkit_support.gypi
+++ b/webkit/support/webkit_support.gypi
@@ -25,12 +25,12 @@
'<(DEPTH)/ui/ui.gyp:ui',
'<(DEPTH)/webkit/common/gpu/webkit_gpu.gyp:webkit_gpu',
'<(DEPTH)/webkit/common/user_agent/webkit_user_agent.gyp:user_agent',
+ '<(DEPTH)/webkit/plugins/webkit_plugins.gyp:plugins_common',
'<(DEPTH)/webkit/renderer/compositor_bindings/compositor_bindings.gyp:webkit_compositor_bindings',
'<(DEPTH)/webkit/renderer/compositor_bindings/compositor_bindings.gyp:webkit_compositor_support',
'glue',
'glue_common',
'plugins',
- 'plugins_common',
'webkit_base',
'webkit_common',
'webkit_media',
@@ -130,31 +130,31 @@
'<(DEPTH)/webkit/browser/fileapi/mock_file_system_options.h',
'<(DEPTH)/webkit/browser/quota/mock_special_storage_policy.cc',
'<(DEPTH)/webkit/browser/quota/mock_special_storage_policy.h',
- '<(DEPTH)/webkit/tools/test_shell/mac/DumpRenderTreePasteboard.h',
- '<(DEPTH)/webkit/tools/test_shell/mac/DumpRenderTreePasteboard.m',
- '<(DEPTH)/webkit/tools/test_shell/mock_webclipboard_impl.cc',
- '<(DEPTH)/webkit/tools/test_shell/mock_webclipboard_impl.h',
- '<(DEPTH)/webkit/tools/test_shell/simple_appcache_system.cc',
- '<(DEPTH)/webkit/tools/test_shell/simple_appcache_system.h',
- '<(DEPTH)/webkit/tools/test_shell/simple_clipboard_impl.cc',
- '<(DEPTH)/webkit/tools/test_shell/simple_dom_storage_system.cc',
- '<(DEPTH)/webkit/tools/test_shell/simple_dom_storage_system.h',
- '<(DEPTH)/webkit/tools/test_shell/simple_file_system.cc',
- '<(DEPTH)/webkit/tools/test_shell/simple_file_system.h',
- '<(DEPTH)/webkit/tools/test_shell/simple_file_writer.cc',
- '<(DEPTH)/webkit/tools/test_shell/simple_file_writer.h',
- '<(DEPTH)/webkit/tools/test_shell/simple_resource_loader_bridge.cc',
- '<(DEPTH)/webkit/tools/test_shell/simple_resource_loader_bridge.h',
- '<(DEPTH)/webkit/tools/test_shell/simple_socket_stream_bridge.cc',
- '<(DEPTH)/webkit/tools/test_shell/simple_socket_stream_bridge.h',
- '<(DEPTH)/webkit/tools/test_shell/simple_webcookiejar_impl.cc',
- '<(DEPTH)/webkit/tools/test_shell/simple_webcookiejar_impl.h',
- '<(DEPTH)/webkit/tools/test_shell/test_shell_request_context.cc',
- '<(DEPTH)/webkit/tools/test_shell/test_shell_request_context.h',
- '<(DEPTH)/webkit/tools/test_shell/test_shell_webblobregistry_impl.cc',
- '<(DEPTH)/webkit/tools/test_shell/test_shell_webblobregistry_impl.h',
- '<(DEPTH)/webkit/tools/test_shell/test_shell_webmimeregistry_impl.cc',
- '<(DEPTH)/webkit/tools/test_shell/test_shell_webmimeregistry_impl.h',
+ '<(DEPTH)/webkit/support/mac/DumpRenderTreePasteboard.h',
+ '<(DEPTH)/webkit/support/mac/DumpRenderTreePasteboard.m',
+ '<(DEPTH)/webkit/support/mock_webclipboard_impl.cc',
+ '<(DEPTH)/webkit/support/mock_webclipboard_impl.h',
+ '<(DEPTH)/webkit/support/simple_appcache_system.cc',
+ '<(DEPTH)/webkit/support/simple_appcache_system.h',
+ '<(DEPTH)/webkit/support/simple_clipboard_impl.cc',
+ '<(DEPTH)/webkit/support/simple_dom_storage_system.cc',
+ '<(DEPTH)/webkit/support/simple_dom_storage_system.h',
+ '<(DEPTH)/webkit/support/simple_file_system.cc',
+ '<(DEPTH)/webkit/support/simple_file_system.h',
+ '<(DEPTH)/webkit/support/simple_file_writer.cc',
+ '<(DEPTH)/webkit/support/simple_file_writer.h',
+ '<(DEPTH)/webkit/support/simple_resource_loader_bridge.cc',
+ '<(DEPTH)/webkit/support/simple_resource_loader_bridge.h',
+ '<(DEPTH)/webkit/support/simple_socket_stream_bridge.cc',
+ '<(DEPTH)/webkit/support/simple_socket_stream_bridge.h',
+ '<(DEPTH)/webkit/support/simple_webcookiejar_impl.cc',
+ '<(DEPTH)/webkit/support/simple_webcookiejar_impl.h',
+ '<(DEPTH)/webkit/support/test_shell_request_context.cc',
+ '<(DEPTH)/webkit/support/test_shell_request_context.h',
+ '<(DEPTH)/webkit/support/test_shell_webblobregistry_impl.cc',
+ '<(DEPTH)/webkit/support/test_shell_webblobregistry_impl.h',
+ '<(DEPTH)/webkit/support/test_shell_webmimeregistry_impl.cc',
+ '<(DEPTH)/webkit/support/test_shell_webmimeregistry_impl.h',
'<(DEPTH)/webkit/mocks/mock_webhyphenator.cc',
'<(DEPTH)/webkit/mocks/mock_webhyphenator.h',
'<(DEPTH)/webkit/mocks/test_media_stream_client.cc',