Initial commit

This commit is contained in:
Adam Roben 2013-03-13 15:12:05 -04:00
commit e451d92121
29 changed files with 1359 additions and 0 deletions

2
brightray/.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
/brightray.xcodeproj/
/build/

3
brightray/.gitmodules vendored Normal file
View file

@ -0,0 +1,3 @@
[submodule "vendor/libchromiumcontent"]
path = vendor/libchromiumcontent
url = https://github.com/aroben/libchromiumcontent

19
brightray/LICENSE Normal file
View file

@ -0,0 +1,19 @@
Copyright (c) 2013 Adam Roben <adam@roben.org>
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View file

@ -0,0 +1,27 @@
// Copyright (c) 2013 The Chromium Authors. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * 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.
// * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
// OWNER OR 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.

34
brightray/README.md Normal file
View file

@ -0,0 +1,34 @@
# Brightray
Brightray is a static library that makes
[libchromiumcontent](https://github.com/aroben/libchromiumcontent) easier to
use in applications.
## Using it in your app
See [brightray_example](https://github.com/aroben/brightray_example) for a
sample application written using Brightray.
## Development
### One-time setup
You must previously have built and uploaded libchromiumcontent using its
`script/upload` script.
$ script/bootstrap http://base.url.com/used/by/script/upload
### Building
$ script/build
Building Brightray on its own isnt all that interesting, since its just a
static library. Building it into an application (like
[brightray_example](https://github.com/aroben/brightray_example)) is the only
way to test it.
## License
In general, everything is covered by the [`LICENSE`](LICENSE) file. Some files
specify at the top that they are covered by the
[`LICENSE-CHROMIUM`](LICENSE-CHROMIUM) file instead.

47
brightray/brightray.gyp Normal file
View file

@ -0,0 +1,47 @@
{
'includes': [
'brightray.gypi',
],
'targets': [
{
'target_name': 'brightray',
'type': 'static_library',
'include_dirs': [
'<(libchromiumcontent_include_dir)',
],
'direct_dependent_settings': {
'include_dirs': [
'<(libchromiumcontent_include_dir)',
],
},
'sources': [
'browser/browser_client.cc',
'browser/browser_client.h',
'browser/browser_context.cc',
'browser/browser_context.h',
'browser/browser_main_parts.cc',
'browser/browser_main_parts.h',
'browser/browser_main_parts_mac.mm',
'browser/mac/bry_application.h',
'browser/mac/bry_application.mm',
'browser/network_delegate.cc',
'browser/network_delegate.h',
'browser/url_request_context_getter.cc',
'browser/url_request_context_getter.h',
'common/main_delegate.cc',
'common/main_delegate.h',
'common/main_delegate_mac.mm',
],
'conditions': [
['OS=="mac"', {
'link_settings': {
'libraries': [
'libchromiumcontent.dylib',
'$(SDKROOT)/System/Library/Frameworks/AppKit.framework',
],
},
}],
],
},
],
}

39
brightray/brightray.gypi Normal file
View file

@ -0,0 +1,39 @@
{
'variables': {
'libchromiumcontent_dir': 'vendor/download/libchromiumcontent',
'libchromiumcontent_library_dir': '<(libchromiumcontent_dir)/Release',
'libchromiumcontent_include_dir': '<(libchromiumcontent_dir)/include',
'libchromiumcontent_resources_dir': '<(libchromiumcontent_library_dir)',
},
'target_defaults': {
'defines': [
'NDEBUG',
],
'xcode_settings': {
'CLANG_CXX_LANGUAGE_STANDARD': 'gnu++11',
'CLANG_CXX_LIBRARY': 'libstdc++',
'COMBINE_HIDPI_IMAGES': 'YES',
'GCC_ENABLE_CPP_RTTI': 'NO',
'GCC_TREAT_WARNINGS_AS_ERRORS': 'YES',
'MACOSX_DEPLOYMENT_TARGET': '10.7',
'RUN_CLANG_STATIC_ANALYZER': 'YES',
'SDKROOT': 'macosx10.7',
'WARNING_CFLAGS': [
'-Wall',
'-Wextra',
'-Wno-unused-parameter',
'-Wno-missing-field-initializers',
],
},
'configurations': {
'Debug': {
'xcode_settings': {
'COPY_PHASE_STRIP': 'NO',
'GCC_OPTIMIZATION_LEVEL': '0',
},
},
'Release': {
},
},
},
}

View file

@ -0,0 +1,35 @@
// 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-CHROMIUM file.
#include "browser_client.h"
#include "browser_context.h"
#include "browser_main_parts.h"
namespace brightray {
BrowserClient::BrowserClient() {
}
BrowserClient::~BrowserClient() {
}
BrowserContext* BrowserClient::browser_context() {
return browser_main_parts_->browser_context();
}
BrowserMainParts* BrowserClient::OverrideCreateBrowserMainParts(const content::MainFunctionParams&) {
return new BrowserMainParts;
}
content::BrowserMainParts* BrowserClient::CreateBrowserMainParts(const content::MainFunctionParams& parameters) {
browser_main_parts_.reset(OverrideCreateBrowserMainParts(parameters));
return browser_main_parts_.get();
}
net::URLRequestContextGetter* BrowserClient::CreateRequestContext(content::BrowserContext* browser_context, content::ProtocolHandlerMap* protocol_handlers) {
return static_cast<BrowserContext*>(browser_context)->CreateRequestContext(protocol_handlers);
}
}

View file

@ -0,0 +1,39 @@
// 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-CHROMIUM file.
#ifndef __brightray__browser_client__
#define __brightray__browser_client__
#include "content/public/browser/content_browser_client.h"
namespace brightray {
class BrowserContext;
class BrowserMainParts;
class BrowserClient : public content::ContentBrowserClient {
public:
BrowserClient();
~BrowserClient();
BrowserContext* browser_context();
BrowserMainParts* browser_main_parts() { return browser_main_parts_.get(); }
protected:
// Subclasses should override this to provide their own BrowserMainParts implementation. The
// lifetime of the returned instance is managed by the caller.
virtual BrowserMainParts* OverrideCreateBrowserMainParts(const content::MainFunctionParams&);
private:
virtual content::BrowserMainParts* CreateBrowserMainParts(const content::MainFunctionParams&) OVERRIDE;
virtual net::URLRequestContextGetter* CreateRequestContext(content::BrowserContext*, content::ProtocolHandlerMap*) OVERRIDE;
scoped_ptr<BrowserMainParts> browser_main_parts_;
DISALLOW_COPY_AND_ASSIGN(BrowserClient);
};
}
#endif /* defined(__brightray__browser_client__) */

View file

@ -0,0 +1,106 @@
// 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-CHROMIUM file.
#include "browser_context.h"
#include "base/files/file_path.h"
#include "base/path_service.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/resource_context.h"
#include "content/public/browser/storage_partition.h"
#include "net/base/host_resolver.h"
#include "url_request_context_getter.h"
namespace brightray {
class BrowserContext::ResourceContext : public content::ResourceContext {
public:
ResourceContext() : getter_(nullptr) {}
void set_url_request_context_getter(URLRequestContextGetter* getter) {
getter_ = getter;
}
private:
virtual net::HostResolver* GetHostResolver() OVERRIDE {
return getter_->host_resolver();
}
virtual net::URLRequestContext* GetRequestContext() OVERRIDE {
return getter_->GetURLRequestContext();
}
URLRequestContextGetter* getter_;
scoped_ptr<net::HostResolver> host_resolver_;
};
BrowserContext::BrowserContext() : resource_context_(new ResourceContext) {
}
BrowserContext::~BrowserContext() {
}
net::URLRequestContextGetter* BrowserContext::CreateRequestContext(content::ProtocolHandlerMap* protocol_handlers) {
DCHECK(!url_request_getter_);
url_request_getter_.reset(new URLRequestContextGetter(
GetPath(),
content::BrowserThread::UnsafeGetMessageLoopForThread(content::BrowserThread::IO),
content::BrowserThread::UnsafeGetMessageLoopForThread(content::BrowserThread::FILE),
protocol_handlers));
resource_context_->set_url_request_context_getter(url_request_getter_.get());
return url_request_getter_.get();
}
base::FilePath BrowserContext::GetPath() {
// FIXME: This should be an application-specific path.
base::FilePath path;
CHECK(PathService::Get(base::DIR_APP_DATA, &path));
return path.Append("Brightray");
}
bool BrowserContext::IsOffTheRecord() const {
return false;
}
net::URLRequestContextGetter* BrowserContext::GetRequestContext() {
return GetDefaultStoragePartition(this)->GetURLRequestContext();
}
net::URLRequestContextGetter* BrowserContext::GetRequestContextForRenderProcess(int renderer_child_id) {
return GetRequestContext();
}
net::URLRequestContextGetter* BrowserContext::GetMediaRequestContext() {
return GetRequestContext();
}
net::URLRequestContextGetter* BrowserContext::GetMediaRequestContextForRenderProcess(int renderer_child_id) {
return GetRequestContext();
}
net::URLRequestContextGetter* BrowserContext::GetMediaRequestContextForStoragePartition(const base::FilePath& partition_path, bool in_memory) {
return GetRequestContext();
}
content::ResourceContext* BrowserContext::GetResourceContext() {
return resource_context_.get();
}
content::DownloadManagerDelegate* BrowserContext::GetDownloadManagerDelegate() {
return nullptr;
}
content::GeolocationPermissionContext* BrowserContext::GetGeolocationPermissionContext() {
return nullptr;
}
content::SpeechRecognitionPreferences* BrowserContext::GetSpeechRecognitionPreferences() {
return nullptr;
}
quota::SpecialStoragePolicy* BrowserContext::GetSpecialStoragePolicy() {
return nullptr;
}
}

View file

@ -0,0 +1,46 @@
// 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-CHROMIUM file.
#ifndef __brightray__browser_context__
#define __brightray__browser_context__
#include "content/public/browser/browser_context.h"
#include "content/public/browser/content_browser_client.h"
namespace brightray {
class URLRequestContextGetter;
class BrowserContext : public content::BrowserContext {
public:
BrowserContext();
~BrowserContext();
net::URLRequestContextGetter* CreateRequestContext(content::ProtocolHandlerMap*);
private:
class ResourceContext;
virtual base::FilePath GetPath() OVERRIDE;
virtual bool IsOffTheRecord() const OVERRIDE;
virtual net::URLRequestContextGetter* GetRequestContext() OVERRIDE;
virtual net::URLRequestContextGetter* GetRequestContextForRenderProcess(int renderer_child_id);
virtual net::URLRequestContextGetter* GetMediaRequestContext() OVERRIDE;
virtual net::URLRequestContextGetter* GetMediaRequestContextForRenderProcess(int renderer_child_id) OVERRIDE;
virtual net::URLRequestContextGetter* GetMediaRequestContextForStoragePartition(const base::FilePath& partition_path, bool in_memory);
virtual content::ResourceContext* GetResourceContext() OVERRIDE;
virtual content::DownloadManagerDelegate* GetDownloadManagerDelegate() OVERRIDE;
virtual content::GeolocationPermissionContext* GetGeolocationPermissionContext() OVERRIDE;
virtual content::SpeechRecognitionPreferences* GetSpeechRecognitionPreferences() OVERRIDE;
virtual quota::SpecialStoragePolicy* GetSpecialStoragePolicy() OVERRIDE;
scoped_ptr<ResourceContext> resource_context_;
scoped_ptr<URLRequestContextGetter> url_request_getter_;
DISALLOW_COPY_AND_ASSIGN(BrowserContext);
};
}
#endif /* defined(__brightray__browser_context__) */

View file

@ -0,0 +1,21 @@
// 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-CHROMIUM file.
#include "browser_main_parts.h"
#include "browser_context.h"
namespace brightray {
BrowserMainParts::BrowserMainParts() {
}
BrowserMainParts::~BrowserMainParts() {
}
void BrowserMainParts::PreMainMessageLoopRun() {
browser_context_.reset(new BrowserContext);
}
}

View file

@ -0,0 +1,38 @@
// 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-CHROMIUM file.
#ifndef __brightray__main_parts__
#define __brightray__main_parts__
#include "base/compiler_specific.h"
#include "base/memory/scoped_ptr.h"
#include "content/public/browser/browser_main_parts.h"
namespace brightray {
class BrowserContext;
class BrowserMainParts : public content::BrowserMainParts {
public:
BrowserMainParts();
~BrowserMainParts();
BrowserContext* browser_context() { return browser_context_.get(); }
protected:
#if defined(OS_MACOSX)
virtual void PreMainMessageLoopStart() OVERRIDE;
#endif
virtual void PreMainMessageLoopRun() OVERRIDE;
private:
scoped_ptr<BrowserContext> browser_context_;
DISALLOW_COPY_AND_ASSIGN(BrowserMainParts);
};
}
#endif /* defined(__brightray__main_parts__) */

View file

@ -0,0 +1,21 @@
#import "browser_main_parts.h"
#import "base/mac/bundle_locations.h"
#import <AppKit/AppKit.h>
namespace brightray {
// Replicates NSApplicationMain, but doesn't start a run loop.
void BrowserMainParts::PreMainMessageLoopStart() {
auto infoDictionary = base::mac::OuterBundle().infoDictionary;
auto principalClass = NSClassFromString([infoDictionary objectForKey:@"NSPrincipalClass"]);
auto application = [principalClass sharedApplication];
NSString *mainNibName = [infoDictionary objectForKey:@"NSMainNibFile"];
auto mainNib = [[NSNib alloc] initWithNibNamed:mainNibName bundle:base::mac::FrameworkBundle()];
[mainNib instantiateNibWithOwner:application topLevelObjects:nil];
[mainNib release];
}
}

View file

@ -0,0 +1,7 @@
#import "base/mac/scoped_sending_event.h"
@interface BRYApplication : NSApplication <CrAppProtocol, CrAppControlProtocol> {
BOOL _handlingSendEvent;
}
@end

View file

@ -0,0 +1,19 @@
#import "bry_application.h"
@interface BRYApplication ()
@property (nonatomic, assign, getter = isHandlingSendEvent) BOOL handlingSendEvent;
@end
@implementation BRYApplication
@synthesize handlingSendEvent = _handlingSendEvent;
- (void)sendEvent:(NSEvent *)theEvent
{
base::mac::ScopedSendingEvent scopedSendingEvent;
[super sendEvent:theEvent];
}
@end

View file

@ -0,0 +1,105 @@
// 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-CHROMIUM file.
#include "network_delegate.h"
#include "net/base/net_errors.h"
namespace brightray {
NetworkDelegate::NetworkDelegate() {
}
NetworkDelegate::~NetworkDelegate() {
}
int NetworkDelegate::OnBeforeURLRequest(
net::URLRequest* request,
const net::CompletionCallback& callback,
GURL* new_url) {
return net::OK;
}
int NetworkDelegate::OnBeforeSendHeaders(
net::URLRequest* request,
const net::CompletionCallback& callback,
net::HttpRequestHeaders* headers) {
return net::OK;
}
void NetworkDelegate::OnSendHeaders(
net::URLRequest* request,
const net::HttpRequestHeaders& headers) {
}
int NetworkDelegate::OnHeadersReceived(
net::URLRequest* request,
const net::CompletionCallback& callback,
const net::HttpResponseHeaders* original_response_headers,
scoped_refptr<net::HttpResponseHeaders>* override_response_headers) {
return net::OK;
}
void NetworkDelegate::OnBeforeRedirect(net::URLRequest* request,
const GURL& new_location) {
}
void NetworkDelegate::OnResponseStarted(net::URLRequest* request) {
}
void NetworkDelegate::OnRawBytesRead(const net::URLRequest& request,
int bytes_read) {
}
void NetworkDelegate::OnCompleted(net::URLRequest* request, bool started) {
}
void NetworkDelegate::OnURLRequestDestroyed(net::URLRequest* request) {
}
void NetworkDelegate::OnPACScriptError(int line_number,
const string16& error) {
}
NetworkDelegate::AuthRequiredResponse NetworkDelegate::OnAuthRequired(
net::URLRequest* request,
const net::AuthChallengeInfo& auth_info,
const AuthCallback& callback,
net::AuthCredentials* credentials) {
return AUTH_REQUIRED_RESPONSE_NO_ACTION;
}
bool NetworkDelegate::OnCanGetCookies(const net::URLRequest& request,
const net::CookieList& cookie_list) {
return true;
}
bool NetworkDelegate::OnCanSetCookie(const net::URLRequest& request,
const std::string& cookie_line,
net::CookieOptions* options) {
return true;
}
bool NetworkDelegate::OnCanAccessFile(const net::URLRequest& request,
const base::FilePath& path) const {
return true;
}
bool NetworkDelegate::OnCanThrottleRequest(
const net::URLRequest& request) const {
return false;
}
int NetworkDelegate::OnBeforeSocketStreamConnect(
net::SocketStream* socket,
const net::CompletionCallback& callback) {
return net::OK;
}
void NetworkDelegate::OnRequestWaitStateChange(
const net::URLRequest& request,
RequestWaitState waiting) {
}
}

View file

@ -0,0 +1,41 @@
// 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-CHROMIUM file.
#ifndef __brightray__network_delegate__
#define __brightray__network_delegate__
#include "net/base/network_delegate.h"
namespace brightray {
class NetworkDelegate : public net::NetworkDelegate {
public:
NetworkDelegate();
virtual ~NetworkDelegate();
private:
virtual int OnBeforeURLRequest(net::URLRequest* request, const net::CompletionCallback& callback, GURL* new_url) OVERRIDE;
virtual int OnBeforeSendHeaders(net::URLRequest* request, const net::CompletionCallback& callback, net::HttpRequestHeaders* headers) OVERRIDE;
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;
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 string16& error) OVERRIDE;
virtual AuthRequiredResponse OnAuthRequired(net::URLRequest* request, const net::AuthChallengeInfo& auth_info, const AuthCallback& callback, net::AuthCredentials* credentials) OVERRIDE;
virtual bool OnCanGetCookies(const net::URLRequest& request, const net::CookieList& cookie_list) OVERRIDE;
virtual bool OnCanSetCookie(const net::URLRequest& request, const std::string& cookie_line, net::CookieOptions* options) OVERRIDE;
virtual bool OnCanAccessFile(const net::URLRequest& request, const base::FilePath& path) const OVERRIDE;
virtual bool OnCanThrottleRequest(const net::URLRequest& request) const OVERRIDE;
virtual int OnBeforeSocketStreamConnect(net::SocketStream* stream, const net::CompletionCallback& callback) OVERRIDE;
virtual void OnRequestWaitStateChange(const net::URLRequest& request, RequestWaitState state) OVERRIDE;
DISALLOW_COPY_AND_ASSIGN(NetworkDelegate);
};
}
#endif /* defined(__brightray__network_delegate__) */

View file

@ -0,0 +1,137 @@
// 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-CHROMIUM file.
#include "url_request_context_getter.h"
#include "network_delegate.h"
#include "base/string_util.h"
#include "base/threading/worker_pool.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/url_constants.h"
#include "net/base/cert_verifier.h"
#include "net/base/default_server_bound_cert_store.h"
#include "net/base/server_bound_cert_service.h"
#include "net/base/ssl_config_service_defaults.h"
#include "net/cookies/cookie_monster.h"
#include "net/http/http_auth_handler_factory.h"
#include "net/http/http_cache.h"
#include "net/http/http_server_properties_impl.h"
#include "net/proxy/proxy_service.h"
#include "net/url_request/static_http_user_agent_settings.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_storage.h"
#include "net/url_request/url_request_job_factory_impl.h"
namespace brightray {
URLRequestContextGetter::URLRequestContextGetter(
const base::FilePath& base_path,
MessageLoop* io_loop,
MessageLoop* file_loop,
content::ProtocolHandlerMap* protocol_handlers)
: base_path_(base_path),
io_loop_(io_loop),
file_loop_(file_loop) {
// Must first be created on the UI thread.
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
std::swap(protocol_handlers_, *protocol_handlers);
proxy_config_service_.reset(net::ProxyService::CreateSystemProxyConfigService(io_loop_->message_loop_proxy(), file_loop_));
}
URLRequestContextGetter::~URLRequestContextGetter() {
}
net::HostResolver* URLRequestContextGetter::host_resolver() {
return url_request_context_->host_resolver();
}
net::URLRequestContext* URLRequestContextGetter::GetURLRequestContext()
{
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
if (!url_request_context_.get()) {
url_request_context_.reset(new net::URLRequestContext());
network_delegate_.reset(new NetworkDelegate);
url_request_context_->set_network_delegate(network_delegate_.get());
storage_.reset(
new net::URLRequestContextStorage(url_request_context_.get()));
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 net::StaticHttpUserAgentSettings(
"en-us,en", "iso-8859-1,*,utf-8", EmptyString()));
scoped_ptr<net::HostResolver> host_resolver(
net::HostResolver::CreateDefaultResolver(NULL));
storage_->set_cert_verifier(net::CertVerifier::CreateDefault());
// TODO(jam): use v8 if possible, look at chrome code.
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.get()));
storage_->set_http_server_properties(new net::HttpServerPropertiesImpl);
base::FilePath cache_path = base_path_.Append(FILE_PATH_LITERAL("Cache"));
net::HttpCache::DefaultBackend* main_backend =
new net::HttpCache::DefaultBackend(
net::DISK_CACHE,
cache_path,
0,
content::BrowserThread::GetMessageLoopProxyForThread(
content::BrowserThread::CACHE));
net::HttpNetworkSession::Params network_session_params;
network_session_params.cert_verifier =
url_request_context_->cert_verifier();
network_session_params.server_bound_cert_service =
url_request_context_->server_bound_cert_service();
network_session_params.proxy_service =
url_request_context_->proxy_service();
network_session_params.ssl_config_service =
url_request_context_->ssl_config_service();
network_session_params.http_auth_handler_factory =
url_request_context_->http_auth_handler_factory();
network_session_params.network_delegate =
url_request_context_->network_delegate();
network_session_params.http_server_properties =
url_request_context_->http_server_properties();
network_session_params.ignore_certificate_errors = false;
// Give |storage_| ownership at the end in case it's |mapped_host_resolver|.
storage_->set_host_resolver(host_resolver.Pass());
network_session_params.host_resolver =
url_request_context_->host_resolver();
net::HttpCache* main_cache = new net::HttpCache(
network_session_params, main_backend);
storage_->set_http_transaction_factory(main_cache);
scoped_ptr<net::URLRequestJobFactoryImpl> job_factory(
new net::URLRequestJobFactoryImpl());
for (auto& it : protocol_handlers_) {
bool set_protocol = job_factory->SetProtocolHandler(it.first, it.second.release());
DCHECK(set_protocol);
}
protocol_handlers_.clear();
storage_->set_job_factory(job_factory.release());
}
return url_request_context_.get();
}
scoped_refptr<base::SingleThreadTaskRunner> URLRequestContextGetter::GetNetworkTaskRunner() const
{
return content::BrowserThread::GetMessageLoopProxyForThread(content::BrowserThread::IO);
}
}

View file

@ -0,0 +1,54 @@
// 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-CHROMIUM file.
#ifndef __brightray__url_request_context_getter__
#define __brightray__url_request_context_getter__
#include "base/files/file_path.h"
#include "base/memory/scoped_ptr.h"
#include "content/public/browser/content_browser_client.h"
#include "net/url_request/url_request_context_getter.h"
class MessageLoop;
namespace net {
class HostResolver;
class NetworkDelegate;
class ProxyConfigService;
class URLRequestContextStorage;
}
namespace brightray {
class URLRequestContextGetter : public net::URLRequestContextGetter {
public:
URLRequestContextGetter(
const base::FilePath& base_path,
MessageLoop* io_loop,
MessageLoop* file_loop,
content::ProtocolHandlerMap*);
virtual ~URLRequestContextGetter();
net::HostResolver* host_resolver();
virtual net::URLRequestContext* GetURLRequestContext() OVERRIDE;
private:
virtual scoped_refptr<base::SingleThreadTaskRunner> GetNetworkTaskRunner() const OVERRIDE;
base::FilePath base_path_;
MessageLoop* io_loop_;
MessageLoop* file_loop_;
scoped_ptr<net::ProxyConfigService> proxy_config_service_;
scoped_ptr<net::NetworkDelegate> network_delegate_;
scoped_ptr<net::URLRequestContextStorage> storage_;
scoped_ptr<net::URLRequestContext> url_request_context_;
content::ProtocolHandlerMap protocol_handlers_;
DISALLOW_COPY_AND_ASSIGN(URLRequestContextGetter);
};
}
#endif /* defined(__brightray__url_request_context_getter__) */

View file

@ -0,0 +1,29 @@
// 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-CHROMIUM file.
#include "main_delegate.h"
#include "browser_client.h"
#include "base/command_line.h"
#include "content/public/common/content_switches.h"
namespace brightray {
MainDelegate::MainDelegate() {
}
MainDelegate::~MainDelegate() {
}
void MainDelegate::PreSandboxStartup() {
// FIXME: We don't currently support running sandboxed.
CommandLine::ForCurrentProcess()->AppendSwitch(switches::kNoSandbox);
#if defined(OS_MACOSX)
OverrideChildProcessPath();
OverrideFrameworkBundlePath();
#endif
}
}

View file

@ -0,0 +1,31 @@
// 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-CHROMIUM file.
#ifndef __brightray__main_delegate__
#define __brightray__main_delegate__
#include "base/compiler_specific.h"
#include "base/memory/scoped_ptr.h"
#include "content/public/app/content_main_delegate.h"
namespace brightray {
class MainDelegate : public content::ContentMainDelegate {
public:
MainDelegate();
~MainDelegate();
private:
#if defined(OS_MACOSX)
static void OverrideChildProcessPath();
static void OverrideFrameworkBundlePath();
#endif
virtual void PreSandboxStartup() OVERRIDE;
DISALLOW_COPY_AND_ASSIGN(MainDelegate);
};
}
#endif /* defined(__brightray__main_delegate__) */

View file

@ -0,0 +1,59 @@
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Copyright (c) 2013 Adam Roben <adam@roben.org>. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE-CHROMIUM file.
#import "main_delegate.h"
#include "base/mac/bundle_locations.h"
#include "base/mac/foundation_util.h"
#include "base/path_service.h"
#include "content/public/common/content_paths.h"
namespace brightray {
namespace {
base::FilePath GetFrameworksPath() {
// Start out with the path to the running executable.
base::FilePath path;
PathService::Get(base::FILE_EXE, &path);
// Up to Contents.
if (base::mac::IsBackgroundOnlyProcess()) {
// The running executable is the helper. Go up five steps:
// Contents/Frameworks/Helper.app/Contents/MacOS/Helper
// ^ to here ^ from here
path = path.DirName().DirName().DirName().DirName().DirName();
} else {
// One step up to MacOS, another to Contents.
path = path.DirName().DirName();
}
DCHECK_EQ(path.BaseName().value(), "Contents");
// Go into the frameworks directory.
return path.Append("Frameworks");
}
std::string OuterBundleName() {
return [[base::mac::OuterBundle().infoDictionary objectForKey:base::mac::CFToNSCast(kCFBundleNameKey)] UTF8String];
}
}
void MainDelegate::OverrideFrameworkBundlePath() {
base::FilePath helper_path = GetFrameworksPath().Append(OuterBundleName() + ".framework");
base::mac::SetOverrideFrameworkBundlePath(helper_path);
}
void MainDelegate::OverrideChildProcessPath() {
base::FilePath helper_path = GetFrameworksPath().Append(OuterBundleName() + " Helper.app")
.Append("Contents")
.Append("MacOS")
.Append(OuterBundleName() + " Helper");
PathService::Override(content::CHILD_PROCESS_EXE, helper_path);
}
}

26
brightray/script/bootstrap Executable file
View file

@ -0,0 +1,26 @@
#!/bin/sh
#/ Usage: bootstrap https://base.url.com/from/libchromiumcontent/script/upload
#/ Bootstrap this project.
set -e
usage() {
grep '^#/' <"$0"| cut -c4-
}
BASE_URL="${1}"
if [ -z "${BASE_URL}" ]; then
usage
exit 1
fi
cd "$(dirname "$0")/.."
git submodule sync --quiet
git submodule update --init --recursive
SOURCE_ROOT="$(pwd -P)"
DOWNLOAD_DIR="${SOURCE_ROOT}/vendor/download"
mkdir -p "${DOWNLOAD_DIR}"
vendor/libchromiumcontent/script/download "${BASE_URL}" "${DOWNLOAD_DIR}/libchromiumcontent"

8
brightray/script/build Executable file
View file

@ -0,0 +1,8 @@
#!/bin/sh
set -e
cd "$(dirname "$0")/.."
gyp --depth . brightray.gyp
xcodebuild

View file

@ -0,0 +1,273 @@
#!/usr/bin/env python
# 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-CHROMIUM file.
"""Usage: change_mach_o_flags.py [--executable-heap] [--no-pie] <executablepath>
Arranges for the executable at |executable_path| to have its data (heap)
pages protected to prevent execution on Mac OS X 10.7 ("Lion"), and to have
the PIE (position independent executable) bit set to enable ASLR (address
space layout randomization). With --executable-heap or --no-pie, the
respective bits are cleared instead of set, making the heap executable or
disabling PIE/ASLR.
This script is able to operate on thin (single-architecture) Mach-O files
and fat (universal, multi-architecture) files. When operating on fat files,
it will set or clear the bits for each architecture contained therein.
NON-EXECUTABLE HEAP
Traditionally in Mac OS X, 32-bit processes did not have data pages set to
prohibit execution. Although user programs could call mprotect and
mach_vm_protect to deny execution of code in data pages, the kernel would
silently ignore such requests without updating the page tables, and the
hardware would happily execute code on such pages. 64-bit processes were
always given proper hardware protection of data pages. This behavior was
controllable on a system-wide level via the vm.allow_data_exec sysctl, which
is set by default to 1. The bit with value 1 (set by default) allows code
execution on data pages for 32-bit processes, and the bit with value 2
(clear by default) does the same for 64-bit processes.
In Mac OS X 10.7, executables can "opt in" to having hardware protection
against code execution on data pages applied. This is done by setting a new
bit in the |flags| field of an executable's |mach_header|. When
MH_NO_HEAP_EXECUTION is set, proper protections will be applied, regardless
of the setting of vm.allow_data_exec. See xnu-1699.22.73/osfmk/vm/vm_map.c
override_nx and xnu-1699.22.73/bsd/kern/mach_loader.c load_machfile.
The Apple toolchain has been revised to set the MH_NO_HEAP_EXECUTION when
producing executables, provided that -allow_heap_execute is not specified
at link time. Only linkers shipping with Xcode 4.0 and later (ld64-123.2 and
later) have this ability. See ld64-123.2.1/src/ld/Options.cpp
Options::reconfigureDefaults() and
ld64-123.2.1/src/ld/HeaderAndLoadCommands.hpp
HeaderAndLoadCommandsAtom<A>::flags().
This script sets the MH_NO_HEAP_EXECUTION bit on Mach-O executables. It is
intended for use with executables produced by a linker that predates Apple's
modifications to set this bit itself. It is also useful for setting this bit
for non-i386 executables, including x86_64 executables. Apple's linker only
sets it for 32-bit i386 executables, presumably under the assumption that
the value of vm.allow_data_exec is set in stone. However, if someone were to
change vm.allow_data_exec to 2 or 3, 64-bit x86_64 executables would run
without hardware protection against code execution on data pages. This
script can set the bit for x86_64 executables, guaranteeing that they run
with appropriate protection even when vm.allow_data_exec has been tampered
with.
POSITION-INDEPENDENT EXECUTABLES/ADDRESS SPACE LAYOUT RANDOMIZATION
This script sets or clears the MH_PIE bit in an executable's Mach-O header,
enabling or disabling position independence on Mac OS X 10.5 and later.
Processes running position-independent executables have varying levels of
ASLR protection depending on the OS release. The main executable's load
address, shared library load addresess, and the heap and stack base
addresses may be randomized. Position-independent executables are produced
by supplying the -pie flag to the linker (or defeated by supplying -no_pie).
Executables linked with a deployment target of 10.7 or higher have PIE on
by default.
This script is never strictly needed during the build to enable PIE, as all
linkers used are recent enough to support -pie. However, it's used to
disable the PIE bit as needed on already-linked executables.
"""
import optparse
import os
import struct
import sys
# <mach-o/fat.h>
FAT_MAGIC = 0xcafebabe
FAT_CIGAM = 0xbebafeca
# <mach-o/loader.h>
MH_MAGIC = 0xfeedface
MH_CIGAM = 0xcefaedfe
MH_MAGIC_64 = 0xfeedfacf
MH_CIGAM_64 = 0xcffaedfe
MH_EXECUTE = 0x2
MH_PIE = 0x00200000
MH_NO_HEAP_EXECUTION = 0x01000000
class MachOError(Exception):
"""A class for exceptions thrown by this module."""
pass
def CheckedSeek(file, offset):
"""Seeks the file-like object at |file| to offset |offset| and raises a
MachOError if anything funny happens."""
file.seek(offset, os.SEEK_SET)
new_offset = file.tell()
if new_offset != offset:
raise MachOError, \
'seek: expected offset %d, observed %d' % (offset, new_offset)
def CheckedRead(file, count):
"""Reads |count| bytes from the file-like |file| object, raising a
MachOError if any other number of bytes is read."""
bytes = file.read(count)
if len(bytes) != count:
raise MachOError, \
'read: expected length %d, observed %d' % (count, len(bytes))
return bytes
def ReadUInt32(file, endian):
"""Reads an unsinged 32-bit integer from the file-like |file| object,
treating it as having endianness specified by |endian| (per the |struct|
module), and returns it as a number. Raises a MachOError if the proper
length of data can't be read from |file|."""
bytes = CheckedRead(file, 4)
(uint32,) = struct.unpack(endian + 'I', bytes)
return uint32
def ReadMachHeader(file, endian):
"""Reads an entire |mach_header| structure (<mach-o/loader.h>) from the
file-like |file| object, treating it as having endianness specified by
|endian| (per the |struct| module), and returns a 7-tuple of its members
as numbers. Raises a MachOError if the proper length of data can't be read
from |file|."""
bytes = CheckedRead(file, 28)
magic, cputype, cpusubtype, filetype, ncmds, sizeofcmds, flags = \
struct.unpack(endian + '7I', bytes)
return magic, cputype, cpusubtype, filetype, ncmds, sizeofcmds, flags
def ReadFatArch(file):
"""Reads an entire |fat_arch| structure (<mach-o/fat.h>) from the file-like
|file| object, treating it as having endianness specified by |endian|
(per the |struct| module), and returns a 5-tuple of its members as numbers.
Raises a MachOError if the proper length of data can't be read from
|file|."""
bytes = CheckedRead(file, 20)
cputype, cpusubtype, offset, size, align = struct.unpack('>5I', bytes)
return cputype, cpusubtype, offset, size, align
def WriteUInt32(file, uint32, endian):
"""Writes |uint32| as an unsinged 32-bit integer to the file-like |file|
object, treating it as having endianness specified by |endian| (per the
|struct| module)."""
bytes = struct.pack(endian + 'I', uint32)
assert len(bytes) == 4
file.write(bytes)
def HandleMachOFile(file, options, offset=0):
"""Seeks the file-like |file| object to |offset|, reads its |mach_header|,
and rewrites the header's |flags| field if appropriate. The header's
endianness is detected. Both 32-bit and 64-bit Mach-O headers are supported
(mach_header and mach_header_64). Raises MachOError if used on a header that
does not have a known magic number or is not of type MH_EXECUTE. The
MH_PIE and MH_NO_HEAP_EXECUTION bits are set or cleared in the |flags| field
according to |options| and written to |file| if any changes need to be made.
If already set or clear as specified by |options|, nothing is written."""
CheckedSeek(file, offset)
magic = ReadUInt32(file, '<')
if magic == MH_MAGIC or magic == MH_MAGIC_64:
endian = '<'
elif magic == MH_CIGAM or magic == MH_CIGAM_64:
endian = '>'
else:
raise MachOError, \
'Mach-O file at offset %d has illusion of magic' % offset
CheckedSeek(file, offset)
magic, cputype, cpusubtype, filetype, ncmds, sizeofcmds, flags = \
ReadMachHeader(file, endian)
assert magic == MH_MAGIC or magic == MH_MAGIC_64
if filetype != MH_EXECUTE:
raise MachOError, \
'Mach-O file at offset %d is type 0x%x, expected MH_EXECUTE' % \
(offset, filetype)
original_flags = flags
if options.no_heap_execution:
flags |= MH_NO_HEAP_EXECUTION
else:
flags &= ~MH_NO_HEAP_EXECUTION
if options.pie:
flags |= MH_PIE
else:
flags &= ~MH_PIE
if flags != original_flags:
CheckedSeek(file, offset + 24)
WriteUInt32(file, flags, endian)
def HandleFatFile(file, options, fat_offset=0):
"""Seeks the file-like |file| object to |offset| and loops over its
|fat_header| entries, calling HandleMachOFile for each."""
CheckedSeek(file, fat_offset)
magic = ReadUInt32(file, '>')
assert magic == FAT_MAGIC
nfat_arch = ReadUInt32(file, '>')
for index in xrange(0, nfat_arch):
cputype, cpusubtype, offset, size, align = ReadFatArch(file)
assert size >= 28
# HandleMachOFile will seek around. Come back here after calling it, in
# case it sought.
fat_arch_offset = file.tell()
HandleMachOFile(file, options, offset)
CheckedSeek(file, fat_arch_offset)
def main(me, args):
parser = optparse.OptionParser('%prog [options] <executable_path>')
parser.add_option('--executable-heap', action='store_false',
dest='no_heap_execution', default=True,
help='Clear the MH_NO_HEAP_EXECUTION bit')
parser.add_option('--no-pie', action='store_false',
dest='pie', default=True,
help='Clear the MH_PIE bit')
(options, loose_args) = parser.parse_args(args)
if len(loose_args) != 1:
parser.print_usage()
return 1
executable_path = loose_args[0]
executable_file = open(executable_path, 'rb+')
magic = ReadUInt32(executable_file, '<')
if magic == FAT_CIGAM:
# Check FAT_CIGAM and not FAT_MAGIC because the read was little-endian.
HandleFatFile(executable_file, options)
elif magic == MH_MAGIC or magic == MH_CIGAM or \
magic == MH_MAGIC_64 or magic == MH_CIGAM_64:
HandleMachOFile(executable_file, options)
else:
raise MachOError, '%s is not a Mach-O or fat file' % executable_file
executable_file.close()
return 0
if __name__ == '__main__':
sys.exit(main(sys.argv[0], sys.argv[1:]))

View file

@ -0,0 +1,91 @@
#!/bin/bash
# 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-CHROMIUM file.
# Usage: make_more_helpers.sh <directory_within_contents> <app_name>
#
# This script creates additional helper .app bundles for Chromium, based on
# the existing helper .app bundle, changing their Mach-O header's flags to
# enable and disable various features. Based on Chromium Helper.app, it will
# create Chromium Helper EH.app, which has the MH_NO_HEAP_EXECUTION bit
# cleared to support Chromium child processes that require an executable heap,
# and Chromium Helper NP.app, which has the MH_PIE bit cleared to support
# Chromium child processes that cannot tolerate ASLR.
#
# This script expects to be called from the chrome_exe target as a postbuild,
# and operates directly within the built-up browser app's versioned directory.
#
# Each helper is adjusted by giving it the proper bundle name, renaming the
# executable, adjusting several Info.plist keys, and changing the executable's
# Mach-O flags.
set -eu
make_helper() {
local containing_dir="${1}"
local app_name="${2}"
local feature="${3}"
local flags="${4}"
local helper_name="${app_name} Helper"
local helper_stem="${containing_dir}/${helper_name}"
local original_helper="${helper_stem}.app"
if [[ ! -d "${original_helper}" ]]; then
echo "${0}: error: ${original_helper} is a required directory" >& 2
exit 1
fi
local original_helper_exe="${original_helper}/Contents/MacOS/${helper_name}"
if [[ ! -f "${original_helper_exe}" ]]; then
echo "${0}: error: ${original_helper_exe} is a required file" >& 2
exit 1
fi
local feature_helper="${helper_stem} ${feature}.app"
rsync -acC --delete --include '*.so' "${original_helper}/" "${feature_helper}"
local helper_feature="${helper_name} ${feature}"
local helper_feature_exe="${feature_helper}/Contents/MacOS/${helper_feature}"
mv "${feature_helper}/Contents/MacOS/${helper_name}" "${helper_feature_exe}"
local change_flags="$(dirname "${0}")/change_mach_o_flags.py"
"${change_flags}" ${flags} "${helper_feature_exe}"
local feature_info="${feature_helper}/Contents/Info"
local feature_info_plist="${feature_info}.plist"
defaults write "${feature_info}" "CFBundleDisplayName" "${helper_feature}"
defaults write "${feature_info}" "CFBundleExecutable" "${helper_feature}"
cfbundleid="$(defaults read "${feature_info}" "CFBundleIdentifier")"
feature_cfbundleid="${cfbundleid}.${feature}"
defaults write "${feature_info}" "CFBundleIdentifier" "${feature_cfbundleid}"
cfbundlename="$(defaults read "${feature_info}" "CFBundleName")"
feature_cfbundlename="${cfbundlename} ${feature}"
defaults write "${feature_info}" "CFBundleName" "${feature_cfbundlename}"
# As usual, defaults might have put the plist into whatever format excites
# it, but Info.plists get converted back to the expected XML format.
plutil -convert xml1 "${feature_info_plist}"
# `defaults` also changes the file permissions, so make the file
# world-readable again.
chmod a+r "${feature_info_plist}"
}
if [[ ${#} -ne 2 ]]; then
echo "usage: ${0} <directory_within_contents> <app_name>" >& 2
exit 1
fi
DIRECTORY_WITHIN_CONTENTS="${1}"
APP_NAME="${2}"
CONTENTS_DIR="${BUILT_PRODUCTS_DIR}/${CONTENTS_FOLDER_PATH}"
CONTAINING_DIR="${CONTENTS_DIR}/${DIRECTORY_WITHIN_CONTENTS}"
make_helper "${CONTAINING_DIR}" "${APP_NAME}" "EH" "--executable-heap"
make_helper "${CONTAINING_DIR}" "${APP_NAME}" "NP" "--no-pie"

1
brightray/vendor/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
/download/

@ -0,0 +1 @@
Subproject commit 3f6f01c46be61f36b4e25456bf2c0539ef4d77f3