diff options
Diffstat (limited to 'webkit/support')
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, ¬used); +} + +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', |