add initial lesnet source code and tentative build files All the build files are currently symlinked into mojo repo (../src) except this file, which was copied from the mojo repo and modified: mojo/tools/mojob.py (sha1: dd752cf0606cbac8d9bc68c9752e0de27b124686) Change-Id: I217631719c0c720afcf39bfa9413d3431216a649
diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..6fdf1dc --- /dev/null +++ b/.clang-format
@@ -0,0 +1,8 @@ +# Defines the Chromium style for automatic reformatting. +# http://clang.llvm.org/docs/ClangFormatStyleOptions.html +BasedOnStyle: Chromium +# This defaults to 'Auto'. Explicitly set it for a while, so that +# 'vector<vector<int> >' in existing files gets formatted to +# 'vector<vector<int>>'. ('Auto' means that clang-format will only use +# 'int>>' if the file already contains at least one such instance.) +Standard: Cpp11
diff --git a/.gitignore b/.gitignore index 3c9067e..0dc5930 100644 --- a/.gitignore +++ b/.gitignore
@@ -18,3 +18,8 @@ tags Thumbs.db v8.log + +# project-specific stuff +/build/util/LASTCHANGE* +/build/linux/bin/eu-strip +/out/
diff --git a/.gn b/.gn new file mode 100644 index 0000000..a3bd14d --- /dev/null +++ b/.gn
@@ -0,0 +1,10 @@ +# This file is used by the experimental meta-buildsystem in src/tools/gn to +# find the root of the source tree and to set startup options. + +# The location of the build configuration file. +buildconfig = "//build/config/BUILDCONFIG.gn" + +# The secondary source root is a parallel directory tree where +# GN build files are placed when they can not be placed directly +# in the source tree, e.g. for third party source trees. +secondary_source = "//build/secondary/"
diff --git a/BUILD.gn b/BUILD.gn new file mode 100644 index 0000000..fa8f5e8 --- /dev/null +++ b/BUILD.gn
@@ -0,0 +1,5 @@ +group("root") { + deps = [ + "//mojo/services/network", + ] +}
diff --git a/README.md b/README.md new file mode 100644 index 0000000..8c1b6b8 --- /dev/null +++ b/README.md
@@ -0,0 +1,14 @@ +# lesnet network service + +Building lesnet in effenel tree is still a work-in-progress.. + +## Before building first time + +Please run download_prebuilts.sh + +$ sh ./download_prebuilts.sh + +## To build + +$ mojo/tools/mojob gn --release +$ mojo/tools/mojob build --release
diff --git a/base b/base new file mode 120000 index 0000000..90ad92a --- /dev/null +++ b/base
@@ -0,0 +1 @@ +../src/base \ No newline at end of file
diff --git a/build/build_config.h b/build/build_config.h new file mode 120000 index 0000000..38e5e66 --- /dev/null +++ b/build/build_config.h
@@ -0,0 +1 @@ +../../src/build/build_config.h \ No newline at end of file
diff --git a/build/compiler_version.py b/build/compiler_version.py new file mode 120000 index 0000000..0f9a6e2 --- /dev/null +++ b/build/compiler_version.py
@@ -0,0 +1 @@ +../../src/build/compiler_version.py \ No newline at end of file
diff --git a/build/config b/build/config new file mode 120000 index 0000000..5595137 --- /dev/null +++ b/build/config
@@ -0,0 +1 @@ +../../src/build/config \ No newline at end of file
diff --git a/build/gn_helpers.py b/build/gn_helpers.py new file mode 120000 index 0000000..6a2aa60 --- /dev/null +++ b/build/gn_helpers.py
@@ -0,0 +1 @@ +../../src/build/gn_helpers.py \ No newline at end of file
diff --git a/build/gypi_to_gn.py b/build/gypi_to_gn.py new file mode 120000 index 0000000..cd3a34e --- /dev/null +++ b/build/gypi_to_gn.py
@@ -0,0 +1 @@ +../../src/build/gypi_to_gn.py \ No newline at end of file
diff --git a/build/linux b/build/linux new file mode 120000 index 0000000..ab0e9d4 --- /dev/null +++ b/build/linux
@@ -0,0 +1 @@ +../../src/build/linux \ No newline at end of file
diff --git a/build/module_args/dart.gni b/build/module_args/dart.gni new file mode 120000 index 0000000..5a12692 --- /dev/null +++ b/build/module_args/dart.gni
@@ -0,0 +1 @@ +../../../src/build/module_args/dart.gni \ No newline at end of file
diff --git a/build/module_args/mojo.gni b/build/module_args/mojo.gni new file mode 100644 index 0000000..699543a --- /dev/null +++ b/build/module_args/mojo.gni
@@ -0,0 +1,20 @@ +# Copyright 2015 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 variable should point to the parent directory of the Mojo SDK. +mojo_sdk_root = "//third_party/mojo/src" + +# To build the Mojo shell from source, set this variable to true. To use the +# prebuilt shell, omit this variable or set it to false. Note that the prebuilt +# shell will be used only on platforms for which it is published (currently +# Linux and Android). +mojo_build_mojo_shell_from_source = false + +# To build the dart_snapshotter from source, set this variable to true. To use +# the prebuilt dart_snapshotter, omit this variable or set it to false. +mojo_build_dart_snapshotter_from_source = false + +# To build the network service from source, set this variable to true. To use +# the prebuilt network service, omit this variable or set it to false. +mojo_build_network_service_from_source = true
diff --git a/build/module_args/nacl.gni b/build/module_args/nacl.gni new file mode 120000 index 0000000..ffda9b9 --- /dev/null +++ b/build/module_args/nacl.gni
@@ -0,0 +1 @@ +../../../src/build/module_args/nacl.gni \ No newline at end of file
diff --git a/build/module_args/v8.gni b/build/module_args/v8.gni new file mode 120000 index 0000000..93fc75d --- /dev/null +++ b/build/module_args/v8.gni
@@ -0,0 +1 @@ +../../../src/build/module_args/v8.gni \ No newline at end of file
diff --git a/build/sanitizers b/build/sanitizers new file mode 120000 index 0000000..5b4e632 --- /dev/null +++ b/build/sanitizers
@@ -0,0 +1 @@ +../../src/build/sanitizers \ No newline at end of file
diff --git a/build/secondary b/build/secondary new file mode 120000 index 0000000..01205a2 --- /dev/null +++ b/build/secondary
@@ -0,0 +1 @@ +../../src/build/secondary \ No newline at end of file
diff --git a/build/toolchain b/build/toolchain new file mode 120000 index 0000000..d236062 --- /dev/null +++ b/build/toolchain
@@ -0,0 +1 @@ +../../src/build/toolchain \ No newline at end of file
diff --git a/buildtools b/buildtools new file mode 120000 index 0000000..d9620da --- /dev/null +++ b/buildtools
@@ -0,0 +1 @@ +../src/buildtools \ No newline at end of file
diff --git a/download_prebuilts.sh b/download_prebuilts.sh new file mode 100755 index 0000000..dff714a --- /dev/null +++ b/download_prebuilts.sh
@@ -0,0 +1,9 @@ +#!/bin/sh + +./third_party/mojo/src/mojo/public/tools/download_shell_binary.py \ + --tools-directory=../../../../lesnet/tools \ + --version-file=../../../../lesnet/third_party/mojo/MOJO_VERSION + +./third_party/mojo/src/mojo/public/tools/download_dart_snapshotter.py \ + --tools-directory=../../../../lesnet/tools \ + --version-file=../../../../lesnet/third_party/mojo/MOJO_VERSION
diff --git a/mojo/services/network/BUILD.gn b/mojo/services/network/BUILD.gn new file mode 100644 index 0000000..a8d5457 --- /dev/null +++ b/mojo/services/network/BUILD.gn
@@ -0,0 +1,96 @@ +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//third_party/mojo/src/mojo/public/mojo_application.gni") + +if (is_android) { +# TODO(toshik) +} else { + mojo_native_application("network") { + output_name = "network_service" + deps = [ + ":sources", + ] + } + mojo_native_application("network_secure") { + output_name = "network_service-secure" + deps = [ + ":sources_secure", + ] + } +} + +source_set("sources") { + defines = [] + + sources = [ + "main.cc", + "network_service_delegate.cc", + "network_service_delegate.h", + "network_service_impl.cc", + "network_service_impl.h", + "url_loader_impl.cc", + "url_loader_impl.h", + "http_client.h", + "network_error.h", + ] + + include_dirs = [ "//third_party/asio/asio/include" ] + + defines += [ + "ASIO_STANDALONE", + "ASIO_NO_EXCEPTIONS", + "ASIO_NO_TYPEID", + "ASIO_HAS_STD_SYSTEM_ERROR", + ] + + deps = [ + "//base", + "//mojo/services/network/interfaces", + "//third_party/mojo/src/mojo/public/cpp/application", + "//third_party/mojo/src/mojo/public/cpp/application:standalone", + "//third_party/mojo/src/mojo/public/cpp/bindings", + "//third_party/mojo/src/mojo/public/cpp/system", + "//third_party/mojo/src/mojo/public/cpp/utility", + "//third_party/boringssl:boringssl", + ] +} + +source_set("sources_secure") { + defines = [ + "NETWORK_SERVICE_USE_HTTPS", + "NETWORK_SERVICE_HTTPS_CERT_HACK", + ] + + sources = [ + "main.cc", + "network_service_delegate.cc", + "network_service_delegate.h", + "network_service_impl.cc", + "network_service_impl.h", + "url_loader_impl.cc", + "url_loader_impl.h", + "http_client.h", + "network_error.h", + ] + + include_dirs = [ "//third_party/asio/asio/include" ] + + defines += [ + "ASIO_STANDALONE", + "ASIO_NO_EXCEPTIONS", + "ASIO_NO_TYPEID", + "ASIO_HAS_STD_SYSTEM_ERROR", + ] + + deps = [ + "//base", + "//mojo/services/network/interfaces", + "//third_party/mojo/src/mojo/public/cpp/application", + "//third_party/mojo/src/mojo/public/cpp/application:standalone", + "//third_party/mojo/src/mojo/public/cpp/bindings", + "//third_party/mojo/src/mojo/public/cpp/system", + "//third_party/mojo/src/mojo/public/cpp/utility", + "//third_party/boringssl:boringssl", + ] +}
diff --git a/mojo/services/network/http_client.h b/mojo/services/network/http_client.h new file mode 100644 index 0000000..624662e --- /dev/null +++ b/mojo/services/network/http_client.h
@@ -0,0 +1,394 @@ +// Copyright 2015 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 MOJO_SERVICES_NETWORK_HTTP_CLIENT_H_ +#define MOJO_SERVICES_NETWORK_HTTP_CLIENT_H_ + +#include <iostream> +#include "mojo/services/network/network_error.h" + +#include <asio.hpp> +#include <asio/ssl.hpp> + +using asio::ip::tcp; + +namespace mojo { + +typedef asio::ssl::stream<tcp::socket> ssl_socket_t; +typedef tcp::socket nonssl_socket_t; + +template<typename T> +class URLLoaderImpl::HTTPClient { + + static_assert(std::is_same<T, ssl_socket_t>::value || std::is_same<T, nonssl_socket_t>::value, "requires either ssl_socket_t or nonssl_socket_t"); + + public: + HTTPClient<T>(URLLoaderImpl* loader, + asio::io_service& io_service, + asio::ssl::context& context, + const std::string& server, const std::string& port, + const std::string& path); + + HTTPClient<T>(URLLoaderImpl* loader, + asio::io_service& io_service, + const std::string& server, const std::string& port, + const std::string& path); + private: + void CreateRequest(const std::string& server, const std::string& path); + void OnResolve(const asio::error_code& err, + tcp::resolver::iterator endpoint_iterator); + bool OnVerifyCertificate(bool preverified, + asio::ssl::verify_context& ctx); + void OnConnect(const asio::error_code& err); + void OnHandShake(const asio::error_code& err); + void OnWriteRequest(const asio::error_code& err); + void OnReadStatusLine(const asio::error_code& err); + MojoResult SendBody(); + void ParseHeaderField(const std::string& header, std::string& name, std::string& value); + void OnReadHeaders(const asio::error_code& err); + void OnReadBody(const asio::error_code& err); + + public: + unsigned int status_code_; + std::string redirect_location_; + + private: + URLLoaderImpl* loader_; + + tcp::resolver resolver_; + T socket_; + asio::streambuf request_buf_; + asio::streambuf response_buf_; + + std::string http_version_; + std::string status_message_; + + ScopedDataPipeProducerHandle response_body_stream_; +}; + +template<> +void URLLoaderImpl::HTTPClient<ssl_socket_t>::OnResolve(const asio::error_code& err, + tcp::resolver::iterator endpoint_iterator); +template<> +void URLLoaderImpl::HTTPClient<nonssl_socket_t>::OnResolve(const asio::error_code& err, + tcp::resolver::iterator endpoint_iterator); +template<> +void URLLoaderImpl::HTTPClient<ssl_socket_t>::OnConnect(const asio::error_code& err); +template<> +void URLLoaderImpl::HTTPClient<nonssl_socket_t>::OnConnect(const asio::error_code& err); + + +template<> +URLLoaderImpl::HTTPClient<ssl_socket_t>::HTTPClient(URLLoaderImpl* loader, + asio::io_service& io_service, + asio::ssl::context& context, + const std::string& server, const std::string& port, + const std::string& path) + : loader_(loader), + resolver_(io_service), + socket_(io_service, context) { + CreateRequest(server, path); + + tcp::resolver::query query(server, port); + resolver_.async_resolve(query, + std::bind(&HTTPClient<ssl_socket_t>::OnResolve, this, + std::placeholders::_1, + std::placeholders::_2)); +} + +template<> +URLLoaderImpl::HTTPClient<nonssl_socket_t>::HTTPClient(URLLoaderImpl* loader, + asio::io_service& io_service, + const std::string& server, const std::string& port, + const std::string& path) + : loader_(loader), + resolver_(io_service), + socket_(io_service) { + CreateRequest(server, path); + + tcp::resolver::query query(server, port); + resolver_.async_resolve(query, + std::bind(&HTTPClient<nonssl_socket_t>::OnResolve, this, + std::placeholders::_1, + std::placeholders::_2)); +} + +template<typename T> +void URLLoaderImpl::HTTPClient<T>::CreateRequest(const std::string& server, + const std::string& path) +{ + // We specify the "Connection: close" header so that the server will + // close the socket after transmitting the response. This will allow us + // to treat all data up until the EOF as the content. + std::ostream request_stream(&request_buf_); + request_stream << "GET " << path << " HTTP/1.0\r\n"; + request_stream << "Host: " << server << "\r\n"; + request_stream << "Accept: */*\r\n"; + request_stream << "Connection: close\r\n\r\n"; +} + +template<> +void URLLoaderImpl::HTTPClient<ssl_socket_t>::OnResolve(const asio::error_code& err, + tcp::resolver::iterator endpoint_iterator) +{ + if (!err) { + socket_.set_verify_mode(asio::ssl::verify_peer); + socket_.set_verify_callback(std::bind(&HTTPClient<ssl_socket_t>::OnVerifyCertificate, + this, std::placeholders::_1, + std::placeholders::_2)); + asio::async_connect(socket_.lowest_layer(), endpoint_iterator, + std::bind(&HTTPClient<ssl_socket_t>::OnConnect, this, + std::placeholders::_1)); + } else { + std::cout << "Error: Resolve(SSL): " << err.message() << "\n"; + } +} + +template<> +void URLLoaderImpl::HTTPClient<nonssl_socket_t>::OnResolve( + const asio::error_code& err, + tcp::resolver::iterator endpoint_iterator) +{ + if (!err) { + asio::async_connect(socket_, endpoint_iterator, + std::bind(&HTTPClient<nonssl_socket_t>::OnConnect, this, + std::placeholders::_1)); + } else { + std::cout << "Error: Resolve(NonSSL): " << err.message() << "\n"; + } +} + +template<typename T> +bool URLLoaderImpl::HTTPClient<T>::OnVerifyCertificate(bool preverified, + asio::ssl::verify_context& ctx) +{ + // TODO(toshik): RFC 2818 describes the steps involved in doing this for + // HTTPS. + char subject_name[256]; + X509* cert = X509_STORE_CTX_get_current_cert(ctx.native_handle()); + X509_NAME_oneline(X509_get_subject_name(cert), subject_name, 256); + std::cout << "Verifying " << subject_name << "\n"; + +#ifdef NETWORK_SERVICE_HTTPS_CERT_HACK + preverified = true; +#endif + return preverified; +} + +template<> +void URLLoaderImpl::HTTPClient<ssl_socket_t>::OnConnect(const asio::error_code& err) +{ + if (!err) { + socket_.async_handshake(asio::ssl::stream_base::client, + std::bind(&HTTPClient<ssl_socket_t>::OnHandShake, this, + std::placeholders::_1)); + } else { + std::cout << "Error: Connect(SSL): " << err.message() << "\n"; + } +} + +template<> +void URLLoaderImpl::HTTPClient<nonssl_socket_t>::OnConnect(const asio::error_code& err) +{ + if (!err) { + asio::async_write(socket_, request_buf_, + std::bind(&HTTPClient<nonssl_socket_t>::OnWriteRequest, this, + std::placeholders::_1)); + } else { + std::cout << "Error: Connect(NonSSL): " << err.message() << "\n"; + } +} + +template<typename T> +void URLLoaderImpl::HTTPClient<T>::OnHandShake(const asio::error_code& err) +{ + if (!err) { + asio::async_write(socket_, request_buf_, + std::bind(&HTTPClient<T>::OnWriteRequest, this, + std::placeholders::_1)); + } else { + std::cout << "Error: HandShake: " << err.message() << "\n"; + } +} + +template<typename T> +void URLLoaderImpl::HTTPClient<T>::OnWriteRequest(const asio::error_code& err) +{ + if (!err) { + // TODO(toshik): The response_ streambuf will automatically grow + // The growth may be limited by passing a maximum size to the + // streambuf constructor. + asio::async_read_until(socket_, response_buf_, "\r\n", + std::bind(&HTTPClient<T>::OnReadStatusLine, this, + std::placeholders::_1)); + } else { + std::cout << "Error: WriteRequest: " << err.message() << "\n"; + } +} + +template<typename T> +void URLLoaderImpl::HTTPClient<T>::OnReadStatusLine(const asio::error_code& err) +{ + if (!err) { + std::istream response_stream(&response_buf_); + response_stream >> http_version_; + response_stream >> status_code_; + std::string status_message; + std::getline(response_stream, status_message_); + if (!response_stream || http_version_.substr(0, 5) != "HTTP/") { + std::cout << "Error: ReadStatusLine: Invalid response\n"; + return; + } + if (status_code_ != 200 && status_code_ != 301 && status_code_ != 302) { + // TODO(toshik): handle more status codes + std::cout << "Error: ReadStatusLine: Status code "; + std::cout << status_code_ << "\n"; + return; + } + + asio::async_read_until(socket_, response_buf_, "\r\n\r\n", + std::bind(&HTTPClient<T>::OnReadHeaders, this, + std::placeholders::_1)); + } else { + std::cout << "Error: ReadStatusLine: " << err << "\n"; + } +} + +template<typename T> +MojoResult URLLoaderImpl::HTTPClient<T>::SendBody() +{ + if (response_buf_.size() > 0) { + uint32_t size = response_buf_.size(); + + void *buf; + uint32_t num_bytes; + MojoResult result = BeginWriteDataRaw(response_body_stream_.get(), + &buf, &num_bytes, + MOJO_WRITE_DATA_FLAG_NONE); + if (result != MOJO_RESULT_OK) { + std::cout << "Warning: SendBody: BeginWriteDataRAW: result=" + << result << std::endl; + // TODO(toshik): how to handle this? + response_body_stream_.reset(); + response_buf_.consume(size); + return result; + } + + if (num_bytes < size) { + std::cout << "Error: SendBody: Not enough buf (" << num_bytes << " < " + << size << ")" << std::endl; + size = num_bytes; + // TODO(toshik): need to handle buffer-full + } + + std::istream response_stream(&response_buf_); + response_stream.read((char*)buf, size); + + EndWriteDataRaw(response_body_stream_.get(), size); + + response_buf_.consume(size); + } + + return MOJO_RESULT_OK; +} + +template<typename T> +void URLLoaderImpl::HTTPClient<T>::ParseHeaderField(const std::string& header, + std::string& name, + std::string& value) +{ + std::string::const_iterator name_end = std::find(header.begin(), + header.end(), ':'); + name = std::string(header.begin(), name_end); + + std::string::const_iterator value_begin = + std::find_if(name_end + 1, header.end(), [](int c) { return c != ' '; }); + std::string::const_iterator value_end = + std::find_if(name_end + 1, header.end(), [](int c) { return c == '\r'; }); + value = std::string(value_begin, value_end); +} + +template<typename T> +void URLLoaderImpl::HTTPClient<T>::OnReadHeaders(const asio::error_code& err) +{ + if (!err) { + std::istream response_stream(&response_buf_); + std::string header; + + if (status_code_ == 301 || status_code_ == 302) { + redirect_location_.clear(); + + while (std::getline(response_stream, header) && header != "\r") { + HttpHeaderPtr hdr = HttpHeader::New(); + std::string name, value; + ParseHeaderField(header, name, value); + if (name == "Location") { + redirect_location_ = value; + std::cout << "Redirecting to " << redirect_location_ << "\n"; + } + } + } else { + URLResponsePtr response = URLResponse::New(); + + response->status_code = status_code_; + response->status_line = + http_version_ + " " + std::to_string(status_code_) + status_message_; + + while (std::getline(response_stream, header) && header != "\r") { + HttpHeaderPtr hdr = HttpHeader::New(); + std::string name, value; + ParseHeaderField(header, name, value); + hdr->name = name; + hdr->value = value; + response->headers.push_back(hdr.Pass()); + } + + DataPipe data_pipe; + response_body_stream_ = data_pipe.producer_handle.Pass(); + response->body = data_pipe.consumer_handle.Pass(); + + loader_->SendResponse(response.Pass()); + + if (SendBody() != MOJO_RESULT_OK) + return; + + asio::async_read(socket_, response_buf_, + asio::transfer_at_least(1), + std::bind(&HTTPClient<T>::OnReadBody, this, + std::placeholders::_1)); + } + } else { + std::cout << "Error: ReadHeaders: " << err << "\n"; + } +} + +template<typename T> +void URLLoaderImpl::HTTPClient<T>::OnReadBody(const asio::error_code& err) +{ + if (!err) { + if (SendBody() != MOJO_RESULT_OK) + return; + + asio::async_read(socket_, response_buf_, + asio::transfer_at_least(1), + std::bind(&HTTPClient<T>::OnReadBody, this, + std::placeholders::_1)); + } else { + // std::cout << "Error: " << err << std::endl; + // TODO(toshi): handle EOF error + response_body_stream_.reset(); + } +} + +} // namespace mojo + +#if defined(ASIO_NO_EXCEPTIONS) +// ASIO doesn't provide this if exception is not enabled +template <typename Exception> +void asio::detail::throw_exception(const Exception& e) +{ +} +#endif + +#endif /* MOJO_SERVICES_NETWORK_HTTP_CLIENT_H_ */
diff --git a/mojo/services/network/interfaces/BUILD.gn b/mojo/services/network/interfaces/BUILD.gn new file mode 100644 index 0000000..f757f70 --- /dev/null +++ b/mojo/services/network/interfaces/BUILD.gn
@@ -0,0 +1,17 @@ +# Copyright 2015 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. + +import("//build/module_args/mojo.gni") +import("$mojo_sdk_root/mojo/public/tools/bindings/mojom.gni") + +mojom("interfaces") { + sources = [ + "network_service.mojom", + "url_loader.mojom", + ] + + mojo_sdk_deps = [ "mojo/public/interfaces/network" ] + + import_dirs = [ get_path_info("../../../", "abspath") ] +}
diff --git a/mojo/services/network/interfaces/network_service.mojom b/mojo/services/network/interfaces/network_service.mojom new file mode 100644 index 0000000..b378cbc --- /dev/null +++ b/mojo/services/network/interfaces/network_service.mojom
@@ -0,0 +1,13 @@ +// Copyright 2015 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. + +[DartPackage="mojo_services"] +module mojo; + +import "mojo/services/network/interfaces/url_loader.mojom"; + +[ServiceName="mojo::NetworkService"] +interface NetworkService { + CreateURLLoader(URLLoader& loader); +};
diff --git a/mojo/services/network/interfaces/url_loader.mojom b/mojo/services/network/interfaces/url_loader.mojom new file mode 100644 index 0000000..32ea0e6 --- /dev/null +++ b/mojo/services/network/interfaces/url_loader.mojom
@@ -0,0 +1,39 @@ +// Copyright 2015 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. + +[DartPackage="mojo_services"] +module mojo; + +import "mojo/public/interfaces/network/network_error.mojom"; +import "mojo/public/interfaces/network/url_request.mojom"; +import "mojo/public/interfaces/network/url_response.mojom"; + +struct URLLoaderStatus { + // If the loader has failed due to a network level error, this field will be + // set. + NetworkError? error; + + // Set to true if the URLLoader is still working. Set to false once an error + // is encountered or the response body is completely copied to the response + // body stream. + bool is_loading; + + // TODO(darin): Add further details about the stages of loading (e.g., + // "resolving host") that happen prior to receiving bytes. +}; + +interface URLLoader { + // Loads the given |request|, asynchronously producing |response|. Consult + // |response| to determine if the request resulted in an error, was + // redirected, or has a response body to be consumed. + Start(URLRequest request) => (URLResponse response); + + // If the request passed to |Start| had |auto_follow_redirects| set to false, + // then upon receiving an URLResponse with a non-NULL |redirect_url| field, + // |FollowRedirect| may be called to load the URL indicated by the redirect. + FollowRedirect() => (URLResponse response); + + // Query status about the URLLoader. + QueryStatus() => (URLLoaderStatus status); +};
diff --git a/mojo/services/network/main.cc b/mojo/services/network/main.cc new file mode 100644 index 0000000..d528b17 --- /dev/null +++ b/mojo/services/network/main.cc
@@ -0,0 +1,14 @@ +// Copyright 2015 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 "mojo/public/c/system/main.h" +#include "mojo/public/cpp/application/application_connection.h" +#include "mojo/public/cpp/application/application_runner.h" + +#include "network_service_delegate.h" + +MojoResult MojoMain(MojoHandle shell_handle) { + mojo::ApplicationRunner runner(new NetworkServiceDelegate); + return runner.Run(shell_handle); +}
diff --git a/mojo/services/network/network_error.h b/mojo/services/network/network_error.h new file mode 100644 index 0000000..6dcf49d --- /dev/null +++ b/mojo/services/network/network_error.h
@@ -0,0 +1,15 @@ +// Copyright 2015 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 MOJO_SERVICES_NETWORK_NETWORK_ERROR_H_ +#define MOJO_SERVICES_NETWORK_NETWORK_ERROR_H_ + +// TODO(toshik): copied from net/base/net_error_list.h + +enum { + ERR_INVALID_ARGUMENT = -4, + ERR_UNEXPECTED = -9, +}; + +#endif /* MOJO_SERVICES_NETWORK_NETWORK_ERROR_H_ */
diff --git a/mojo/services/network/network_service_delegate.cc b/mojo/services/network/network_service_delegate.cc new file mode 100644 index 0000000..83ecb09 --- /dev/null +++ b/mojo/services/network/network_service_delegate.cc
@@ -0,0 +1,29 @@ +// Copyright 2015 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 "mojo/services/network/network_service_delegate.h" + +#include "mojo/public/cpp/application/application_connection.h" + +NetworkServiceDelegate::NetworkServiceDelegate() {} + +NetworkServiceDelegate::~NetworkServiceDelegate() {} + +void NetworkServiceDelegate::Initialize(mojo::ApplicationImpl* app) { +} + +bool NetworkServiceDelegate::ConfigureIncomingConnection( + mojo::ApplicationConnection* connection) { + connection->AddService(this); + return true; +} + +void NetworkServiceDelegate::Quit() { +} + +void NetworkServiceDelegate::Create( + mojo::ApplicationConnection* connection, + mojo::InterfaceRequest<mojo::NetworkService> request) { + new mojo::NetworkServiceImpl(request.Pass(), connection); +}
diff --git a/mojo/services/network/network_service_delegate.h b/mojo/services/network/network_service_delegate.h new file mode 100644 index 0000000..c17bfe4 --- /dev/null +++ b/mojo/services/network/network_service_delegate.h
@@ -0,0 +1,35 @@ +// Copyright 2015 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 MOJO_SERVICES_NETWORK_NETWORK_SERVICE_DELEGATE_H_ +#define MOJO_SERVICES_NETWORK_NETWORK_SERVICE_DELEGATE_H_ + +#include "mojo/services/network/network_service_impl.h" +#include "mojo/public/cpp/application/application_delegate.h" +#include "mojo/public/cpp/application/application_impl.h" +#include "mojo/public/cpp/bindings/interface_ptr.h" +#include "mojo/public/cpp/application/interface_factory.h" + +class NetworkServiceDelegate + : public mojo::ApplicationDelegate, + public mojo::InterfaceFactory<mojo::NetworkService> { + public: + NetworkServiceDelegate(); + ~NetworkServiceDelegate() override; + + private: + // mojo::ApplicationDelegate implementation. + void Initialize(mojo::ApplicationImpl* app) override; + bool ConfigureIncomingConnection( + mojo::ApplicationConnection* connection) override; + void Quit() override; + + // mojo::InterfaceFactory<mojo::NetworkService> implementation. + void Create(mojo::ApplicationConnection* connection, + mojo::InterfaceRequest<mojo::NetworkService> request) override; + + DISALLOW_COPY_AND_ASSIGN(NetworkServiceDelegate); +}; + +#endif // MOJO_SERVICES_NETWORK_NETWORK_SERVICE_DELEGATE_H_
diff --git a/mojo/services/network/network_service_impl.cc b/mojo/services/network/network_service_impl.cc new file mode 100644 index 0000000..d48fe46 --- /dev/null +++ b/mojo/services/network/network_service_impl.cc
@@ -0,0 +1,24 @@ +// Copyright 2015 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 "mojo/services/network/network_service_impl.h" + +#include "mojo/services/network/url_loader_impl.h" +#include "mojo/public/cpp/application/application_connection.h" + +namespace mojo { + +NetworkServiceImpl::NetworkServiceImpl(InterfaceRequest<NetworkService> request, + ApplicationConnection* connection) + : binding_(this, request.Pass()) { +} + +NetworkServiceImpl::~NetworkServiceImpl() { +} + +void NetworkServiceImpl::CreateURLLoader(InterfaceRequest<URLLoader> loader) { + new URLLoaderImpl(loader.Pass()); +} + +} // namespace mojo
diff --git a/mojo/services/network/network_service_impl.h b/mojo/services/network/network_service_impl.h new file mode 100644 index 0000000..c071979 --- /dev/null +++ b/mojo/services/network/network_service_impl.h
@@ -0,0 +1,32 @@ +// Copyright 2015 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 MOJO_SERVICES_NETWORK_NETWORK_SERVICE_IMPL_H_ +#define MOJO_SERVICES_NETWORK_NETWORK_SERVICE_IMPL_H_ + +//#include "base/compiler_specific.h" +#include "base/macros.h" + +#include "mojo/services/network/interfaces/network_service.mojom.h" +#include "mojo/public/cpp/bindings/strong_binding.h" + +namespace mojo { +class ApplicationConnection; + +class NetworkServiceImpl : public NetworkService { + public: + NetworkServiceImpl(InterfaceRequest<NetworkService> request, + ApplicationConnection* connection); + ~NetworkServiceImpl() override; + + // NetworkService methods: + void CreateURLLoader(InterfaceRequest<URLLoader> loader) override; + + private: + StrongBinding<NetworkService> binding_; +}; + +} // namespace mojo + +#endif // MOJO_SERVICES_NETWORK_NETWORK_SERVICE_IMPL_H_
diff --git a/mojo/services/network/url_loader_impl.cc b/mojo/services/network/url_loader_impl.cc new file mode 100644 index 0000000..bbba168 --- /dev/null +++ b/mojo/services/network/url_loader_impl.cc
@@ -0,0 +1,172 @@ +// Copyright 2015 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 "mojo/services/network/url_loader_impl.h" +#include "mojo/services/network/http_client.h" +#include "mojo/services/network/network_error.h" + +#include <memory> + +#include <iostream> +#include <istream> +#include <ostream> +#include <string> + +namespace mojo { + +NetworkErrorPtr MakeNetworkError(int error_code) { + NetworkErrorPtr error = NetworkError::New(); + error->code = error_code; + return error.Pass(); +} + +URLLoaderImpl::URLLoaderImpl(InterfaceRequest<URLLoader> request) + : binding_(this, request.Pass()), responded_(false) +{ + binding_.set_connection_error_handler([this]() { OnConnectionError(); }); +} + +URLLoaderImpl::~URLLoaderImpl() { +} + +void URLLoaderImpl::Cleanup() { + delete this; +} + +void URLLoaderImpl::Start(URLRequestPtr request, + const Callback<void(URLResponsePtr)>& callback) { + callback_ = callback; + StartInternal(request.Pass()); +} + +void URLLoaderImpl::FollowRedirect( + const Callback<void(URLResponsePtr)>& callback) { + + callback_ = callback; +} + +void URLLoaderImpl::QueryStatus( + const Callback<void(URLLoaderStatusPtr)>& callback) { + URLLoaderStatusPtr status(URLLoaderStatus::New()); + + /* TODO(toshik): fill status */ + callback.Run(status.Pass()); +} + +void URLLoaderImpl::OnConnectionError() { + /* TODO(toshik) */ + binding_.Close(); +} + +void URLLoaderImpl::SendError(int error_code) { + URLResponsePtr response(URLResponse::New()); + response->error = MakeNetworkError(error_code); + SendResponse(response.Pass()); +} + +void URLLoaderImpl::FollowRedirectInternal() { + /* TODO(toshik) */ +} + +void URLLoaderImpl::SendResponse(URLResponsePtr response) { + Callback<void(URLResponsePtr)> callback; + std::swap(callback_, callback); + callback.Run(response.Pass()); + responded_ = true; +} + +bool URLLoaderImpl::ParseURL(const std::string& url, std::string& proto, + std::string& host, std::string& port, + std::string& path) { + std::string delim("://"); + std::string::const_iterator proto_end = + std::search(url.begin(), url.end(), delim.begin(), delim.end()); + if (proto_end == url.end()) { + return false; + } + proto.assign(url.begin(), proto_end); + + std::string::const_iterator host_start = proto_end + delim.length(); + std::string::const_iterator path_start = std::find(host_start, url.end(), '/'); + std::string::const_iterator host_end = std::find(host_start, path_start, ':'); + host.assign(host_start, host_end); + + if (host_end != path_start) + port.assign(host_end + 1, path_start); + else + port = proto; + + if (path_start != url.end()) + path.assign(path_start, url.end()); + else + path.assign("/"); + + if (proto.length() == 0 || host.length() == 0 || port.length() == 0 || + path.length() == 0) + return false; + + return true; +} + +void URLLoaderImpl::StartInternal(URLRequestPtr request) { + std::string url(request->url); + + asio::io_service io_service; + bool redirect = false; + int error_code = ERR_UNEXPECTED; + + do { + std::string proto, host, port, path; + + if (!ParseURL(url, proto, host, port, path)) { + std::cout << "url parse error" << std::endl; + error_code = ERR_INVALID_ARGUMENT; + break; + } + + if (redirect) { + io_service.reset(); + redirect = false; + } + + if (proto == "https") { +#ifdef NETWORK_SERVICE_USE_HTTPS + asio::ssl::context ctx(asio::ssl::context::sslv23); + ctx.set_default_verify_paths(); + + HTTPClient<asio::ssl::stream<tcp::socket>> + c(this, io_service, ctx, host, port, path); + io_service.run(); + + if (c.status_code_ == 301 || c.status_code_ == 302) { + redirect = true; + url = c.redirect_location_; + } +#else + std::cout << "https is not built-in. " + "please build with NETWORK_SERVICE_USE_HTTPS" << std::endl; + error_code = ERR_INVALID_ARGUMENT; + break; +#endif + } else if (proto == "http") { + HTTPClient<tcp::socket> c(this, io_service, host, port, path); + io_service.run(); + + if (c.status_code_ == 301 || c.status_code_ == 302) { + redirect = true; + url = c.redirect_location_; + std::cout << "Redirecting to: " << url << std::endl; + } + } else { + // unknown protocol + error_code = ERR_INVALID_ARGUMENT; + break; + } + } while (redirect); + + if (!responded_) + SendError(error_code); +} + +} // namespace mojo
diff --git a/mojo/services/network/url_loader_impl.h b/mojo/services/network/url_loader_impl.h new file mode 100644 index 0000000..b3c76c6 --- /dev/null +++ b/mojo/services/network/url_loader_impl.h
@@ -0,0 +1,53 @@ +// Copyright 2015 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 MOJO_SERVICES_NETWORK_URL_LOADER_IMPL_H_ +#define MOJO_SERVICES_NETWORK_URL_LOADER_IMPL_H_ + +#include "base/memory/scoped_ptr.h" +//#include "mojo/common/handle_watcher.h" +#include "mojo/services/network/interfaces/url_loader.mojom.h" +#include "mojo/public/cpp/bindings/binding.h" + +namespace mojo { + + //class NetToMojoPendingBuffer; + +class URLLoaderImpl : public URLLoader { + + public: + URLLoaderImpl(InterfaceRequest<URLLoader> request); + ~URLLoaderImpl() override; + + // Called when the associated NetworkContext is going away. + void Cleanup(); + + private: + template<typename T> class HTTPClient; + + // URLLoader methods: + void Start(URLRequestPtr request, + const Callback<void(URLResponsePtr)>& callback) override; + void FollowRedirect(const Callback<void(URLResponsePtr)>& callback) override; + void QueryStatus(const Callback<void(URLLoaderStatusPtr)>& callback) override; + + void OnConnectionError(); + void SendError(int error_code); + void FollowRedirectInternal(); + void SendResponse(URLResponsePtr response); + bool ParseURL(const std::string& url, std::string& scheme, std::string& host, + std::string& port, std::string& path); + void StartInternal(URLRequestPtr request); + + Callback<void(URLResponsePtr)> callback_; + // bool auto_follow_redirects_; + URLLoaderStatusPtr last_status_; + Binding<URLLoader> binding_; + + bool responded_; +}; + +} // namespace mojo + +#endif // MOJO_SERVICES_NETWORK_URL_LOADER_IMPL_H_
diff --git a/mojo/services/public/build/config/BUILD.gn b/mojo/services/public/build/config/BUILD.gn new file mode 100644 index 0000000..c6b13b6 --- /dev/null +++ b/mojo/services/public/build/config/BUILD.gn
@@ -0,0 +1,22 @@ +# Copyright 2015 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. + +# The absolute path to the directory containing the Mojo services produced +# out of Chromium. +mojo_services_root = get_path_info("../../..", "abspath") + +# NOTE: This config name must be in sync with the name of the config used by +# services that developed out of the Mojo repo so that Chromium's services' +# BUILD.gn files can work seamlessly in Chromium and when pulled into Mojo or a +# client repo. +config("mojo_services") { + include_dirs = [ + # Include paths in Chromium Mojo services' client-side code are specified + # relative to the directory holding the services' client-side code. + mojo_services_root, + + # The same goes for files generated from mojoms. + root_gen_dir + mojo_services_root, + ] +}
diff --git a/mojo/tools/get_test_list.py b/mojo/tools/get_test_list.py new file mode 120000 index 0000000..b163995 --- /dev/null +++ b/mojo/tools/get_test_list.py
@@ -0,0 +1 @@ +../../../src/mojo/tools/get_test_list.py \ No newline at end of file
diff --git a/mojo/tools/mojob.py b/mojo/tools/mojob.py new file mode 100755 index 0000000..2df00f5 --- /dev/null +++ b/mojo/tools/mojob.py
@@ -0,0 +1,367 @@ +#!/usr/bin/env python +# Copyright 2014 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. + +"""A simple script to make building/testing Mojo components easier.""" + +import argparse +from copy import deepcopy +import logging +from multiprocessing import cpu_count +import os +import subprocess +import sys + +from get_test_list import GetTestList +from mopy.config import Config +from mopy.paths import Paths +from mopy.gn import GNArgsForConfig, ParseGNConfig, CommandLineForGNArgs +from mopy.log import InitLogging + + +_logger = logging.getLogger() +_verbose_count = 0 + + +def _args_to_config(args): + # Default to host OS. + target_os = None + if args.android: + target_os = Config.OS_ANDROID + elif args.ios: + target_os = Config.OS_IOS + elif args.fnl: + target_os = Config.OS_FNL + + target_cpu = args.target_cpu + + additional_args = {} + + if 'clang' in args: + additional_args['is_clang'] = args.clang + + if 'asan' in args and args.asan: + additional_args['sanitizer'] = Config.SANITIZER_ASAN + + # Additional non-standard config entries: + + if 'goma' in args: + goma_dir = os.environ.get('GOMA_DIR') + goma_home_dir = os.path.join(os.getenv('HOME', ''), 'goma') + if args.goma and goma_dir: + additional_args['use_goma'] = True + additional_args['goma_dir'] = goma_dir + elif args.goma and os.path.exists(goma_home_dir): + additional_args['use_goma'] = True + additional_args['goma_dir'] = goma_home_dir + else: + additional_args['use_goma'] = False + additional_args['goma_dir'] = None + + if 'nacl' in args: + additional_args['use_nacl'] = args.nacl + +# if not ('asan' in args and args.asan): +# go_dir = os.path.join(Paths().src_root, 'third_party', 'go', 'tool') +# if args.android: +# additional_args['mojo_use_go'] = True +# additional_args['go_build_tool'] = os.path.join( +# go_dir, 'android_arm', 'bin', 'go') +# elif target_os is None and Config.GetHostOS() == Config.OS_LINUX: +# additional_args['mojo_use_go'] = True +# additional_args['go_build_tool'] = os.path.join( +# go_dir, 'linux_amd64', 'bin', 'go') + + if 'dry_run' in args: + additional_args['dry_run'] = args.dry_run + + if 'builder_name' in args: + additional_args['builder_name'] = args.builder_name + if 'build_number' in args: + additional_args['build_number'] = args.build_number + if 'master_name' in args: + additional_args['master_name'] = args.master_name + if 'test_results_server' in args: + additional_args['test_results_server'] = args.test_results_server + + if 'gn_args' in args: + additional_args['gn_args'] = args.gn_args + + is_debug = args.debug and not args.official + + if 'target_sysroot' in args and args.target_sysroot: + additional_args['target_sysroot'] = os.path.abspath(args.target_sysroot) + + if 'toolchain_prefix' in args and args.toolchain_prefix: + additional_args['toolchain_prefix'] = args.toolchain_prefix + + if 'package_name' in args: + additional_args['package_name'] = args.package_name + + return Config(target_os=target_os, target_cpu=target_cpu, + is_debug=is_debug, is_official_build=args.official, + dcheck_always_on=args.dcheck_always_on, + is_simulator=args.simulator, **additional_args) + + +def _get_out_dir(config): + """Gets the build output directory (e.g., out/Debug), relative to src, for the + given config.""" + + paths = Paths(config) + return paths.SrcRelPath(paths.build_dir) + + +def _sync(config): # pylint: disable=W0613 + """Runs gclient sync for the given config.""" + + _logger.debug('_sync()') + return subprocess.call(['gclient', 'sync']) + + +def _gn(config): + """Runs gn gen for the given config.""" + + _logger.debug('_gn()') + + command = ['gn', 'gen', '--check'] + + gn_args = CommandLineForGNArgs(GNArgsForConfig(config)) + out_dir = _get_out_dir(config) + command.append(out_dir) + command.append('--args=%s' % ' '.join(gn_args)) + + print 'Running %s %s ...' % (command[0], + ' '.join('\'%s\'' % x for x in command[1:])) + return subprocess.call(command) + + +def _build(config): + """Builds for the given config.""" + + _logger.debug('_build()') + + out_dir = _get_out_dir(config) + gn_args = ParseGNConfig(out_dir) + print 'Building in %s ...' % out_dir + if gn_args.get('use_goma'): + # Use the configured goma directory. + local_goma_dir = gn_args.get('goma_dir') + print 'Ensuring goma (in %s) started ...' % local_goma_dir + command = ['python', + os.path.join(local_goma_dir, 'goma_ctl.py'), + 'ensure_start'] + exit_code = subprocess.call(command) + if exit_code: + return exit_code + + # Goma allows us to run many more jobs in parallel, say 32 per core/thread + # (= 1024 on a 16-core, 32-thread Z620). Limit the load average to 4 per + # core/thread (= 128 on said Z620). + jobs = cpu_count() * 32 + limit = cpu_count() * 4 + return subprocess.call(['ninja', '-j', str(jobs), '-l', str(limit), + '-C', out_dir]) + else: + return subprocess.call(['ninja', '-C', out_dir]) + + +def _run_tests(config, test_types): + """Runs the tests of the given type(s) for the given config.""" + + assert isinstance(test_types, list) + config = deepcopy(config) + config.values['test_types'] = test_types + + test_list = GetTestList(config, verbose_count=_verbose_count) + dry_run = config.values.get('dry_run') + final_exit_code = 0 + failure_list = [] + for entry in test_list: + print 'Running: %s' % entry['name'] + print 'Command: %s' % ' '.join(entry['command']) + if dry_run: + continue + + _logger.info('Starting: %s' % ' '.join(entry['command'])) + exit_code = subprocess.call(entry['command']) + _logger.info('Completed: %s' % ' '.join(entry['command'])) + if exit_code: + if not final_exit_code: + final_exit_code = exit_code + failure_list.append(entry['name']) + + print 72 * '=' + print 'SUMMARY:', + if dry_run: + print 'Dry run: no tests run' + elif not failure_list: + assert not final_exit_code + print 'All tests passed' + else: + assert final_exit_code + print 'The following had failures:', ', '.join(failure_list) + + return final_exit_code + + +def _test(config): + _logger.debug('_test()') + return _run_tests(config, [Config.TEST_TYPE_DEFAULT]) + + +def _perftest(config): + _logger.debug('_perftest()') + return _run_tests(config, [Config.TEST_TYPE_PERF]) + + +def _pytest(config): + _logger.debug('_pytest()') + return _run_tests(config, ['python']) + +def _analyzedart(config): + _logger.debug('_analyzedart()') + command = ['python'] + build_dir = _get_out_dir(config) + command.append(os.path.join("mojo", + "public", + "tools", + "dart_pkg_static_analysis.py")) + command.append("--dart-pkg-dir=" + os.path.join(build_dir, "gen", "dart-pkg")) + command.append("--dart-sdk=" + os.path.join("third_party", + "dart-sdk", "dart-sdk")) + command.append("--package-root=" + os.path.join(build_dir, + "gen", + "dart-pkg", + "packages")) + if config.values.get('package_name'): + command.append(config.values.get('package_name')) + print 'Running %s %s ...' % (command[0], + ' '.join('\'%s\'' % x for x in command[1:])) + return subprocess.call(command) + +def main(): + os.chdir(Paths().src_root) + + parser = argparse.ArgumentParser(description='A script to make building' + '/testing Mojo components easier.') + + parent_parser = argparse.ArgumentParser(add_help=False) + + parent_parser.add_argument('--verbose', + help='Be verbose (multiple times for more)', + default=0, dest='verbose_count', action='count') + + parent_parser.add_argument('--asan', help='Use Address Sanitizer', + action='store_true') + parent_parser.add_argument('--dcheck_always_on', + help='DCHECK and MOJO_DCHECK are fatal even in ' + 'release builds', + action='store_true') + + debug_group = parent_parser.add_mutually_exclusive_group() + debug_group.add_argument('--debug', help='Debug build (default)', + default=True, action='store_true') + debug_group.add_argument('--release', help='Release build', default=False, + dest='debug', action='store_false') + # The official build is a release build suitable for distribution, with a + # different package name. + debug_group.add_argument('--official', help='Official build', default=False, + dest='official', action='store_true') + + os_group = parent_parser.add_mutually_exclusive_group() + os_group.add_argument('--android', help='Build for Android', + action='store_true') + os_group.add_argument('--ios', help='Build for iOS', + action='store_true') + os_group.add_argument('--fnl', help='Build for FNL', + action='store_true') + + parent_parser.add_argument('--simulator', + help='Build for a simulator of the target', + action='store_true') + + parent_parser.add_argument('--target-cpu', + help='CPU architecture to build for.', + choices=['x64', 'x86', 'arm']) + + parent_parser.add_argument('--target-sysroot', + help='Location of sysroot for target', + default='', + dest='target_sysroot') + + parent_parser.add_argument('--toolchain-prefix', + help='Toolchain prefix', + default='', + dest='toolchain_prefix') + + subparsers = parser.add_subparsers() + + sync_parser = subparsers.add_parser('sync', parents=[parent_parser], + help='Sync using gclient (does not run gn).') + sync_parser.set_defaults(func=_sync) + + gn_parser = subparsers.add_parser('gn', parents=[parent_parser], + help='Run gn for mojo (does not sync).') + gn_parser.set_defaults(func=_gn) + gn_parser.add_argument('--args', help='Specify extra args', + default=None, dest='gn_args') + # Note: no default, if nothing is specified on the command line GN decides. + gn_parser.add_argument('--nacl', help='Add in NaCl', action='store_true', + default=argparse.SUPPRESS) + gn_parser.add_argument('--no-nacl', help='Remove NaCl', action='store_false', + default=argparse.SUPPRESS, dest='nacl') + + clang_group = gn_parser.add_mutually_exclusive_group() + clang_group.add_argument('--clang', help='Use Clang (default)', default=None, + action='store_true') + clang_group.add_argument('--gcc', help='Use GCC', + dest='clang', action='store_false') + goma_group = gn_parser.add_mutually_exclusive_group() + goma_group.add_argument('--goma', + help='Use Goma (if $GOMA_DIR is set or $HOME/goma ' + 'exists; default)', + default=True, + action='store_true') + goma_group.add_argument('--no-goma', help='Don\'t use Goma', default=False, + dest='goma', action='store_false') + + build_parser = subparsers.add_parser('build', parents=[parent_parser], + help='Build') + build_parser.set_defaults(func=_build) + + test_parser = subparsers.add_parser('test', parents=[parent_parser], + help='Run unit tests (does not build).') + test_parser.set_defaults(func=_test) + test_parser.add_argument('--dry-run', + help='Print instead of executing commands', + default=False, action='store_true') + + perftest_parser = subparsers.add_parser('perftest', parents=[parent_parser], + help='Run perf tests (does not build).') + perftest_parser.set_defaults(func=_perftest) + + pytest_parser = subparsers.add_parser('pytest', parents=[parent_parser], + help='Run Python unit tests (does not build).') + pytest_parser.set_defaults(func=_pytest) + + analyze_dart_parser = subparsers.add_parser('analyze-dart', + parents=[parent_parser], + help='Run the dart analyzer (does not build.') + analyze_dart_parser.add_argument('package_name', nargs='?', default=None) + analyze_dart_parser.set_defaults(func=_analyzedart) + + args = parser.parse_args() + global _verbose_count + _verbose_count = args.verbose_count + InitLogging(_verbose_count) + + if args.simulator and not args.ios: + sys.exit("Currently, the simulator target is only configured for iOS") + + return args.func(_args_to_config(args)) + + +if __name__ == '__main__': + sys.exit(main())
diff --git a/mojo/tools/mopy b/mojo/tools/mopy new file mode 120000 index 0000000..d8fea8a --- /dev/null +++ b/mojo/tools/mopy
@@ -0,0 +1 @@ +../../../src/mojo/tools/mopy \ No newline at end of file
diff --git a/testing b/testing new file mode 120000 index 0000000..ed614bb --- /dev/null +++ b/testing
@@ -0,0 +1 @@ +../src/testing \ No newline at end of file
diff --git a/third_party/asio b/third_party/asio new file mode 120000 index 0000000..993e6cf --- /dev/null +++ b/third_party/asio
@@ -0,0 +1 @@ +../../src/third_party/asio \ No newline at end of file
diff --git a/third_party/binutils b/third_party/binutils new file mode 120000 index 0000000..1b1c09c --- /dev/null +++ b/third_party/binutils
@@ -0,0 +1 @@ +../../src/third_party/binutils \ No newline at end of file
diff --git a/third_party/boringssl b/third_party/boringssl new file mode 120000 index 0000000..c554834 --- /dev/null +++ b/third_party/boringssl
@@ -0,0 +1 @@ +../../src/third_party/boringssl \ No newline at end of file
diff --git a/third_party/icu b/third_party/icu new file mode 120000 index 0000000..faff30e --- /dev/null +++ b/third_party/icu
@@ -0,0 +1 @@ +../../src/third_party/icu \ No newline at end of file
diff --git a/third_party/libevent b/third_party/libevent new file mode 120000 index 0000000..ab2bbd1 --- /dev/null +++ b/third_party/libevent
@@ -0,0 +1 @@ +../../src/third_party/libevent \ No newline at end of file
diff --git a/third_party/libudev b/third_party/libudev new file mode 120000 index 0000000..0a2f671 --- /dev/null +++ b/third_party/libudev
@@ -0,0 +1 @@ +../../src/third_party/libudev \ No newline at end of file
diff --git a/third_party/libxml b/third_party/libxml new file mode 120000 index 0000000..7649c4e --- /dev/null +++ b/third_party/libxml
@@ -0,0 +1 @@ +../../src/third_party/libxml \ No newline at end of file
diff --git a/third_party/llvm b/third_party/llvm new file mode 120000 index 0000000..84e0479 --- /dev/null +++ b/third_party/llvm
@@ -0,0 +1 @@ +../../src/third_party/llvm \ No newline at end of file
diff --git a/third_party/llvm-build b/third_party/llvm-build new file mode 120000 index 0000000..30c94a7 --- /dev/null +++ b/third_party/llvm-build
@@ -0,0 +1 @@ +../../src/third_party/llvm-build \ No newline at end of file
diff --git a/third_party/modp_b64 b/third_party/modp_b64 new file mode 120000 index 0000000..9288218 --- /dev/null +++ b/third_party/modp_b64
@@ -0,0 +1 @@ +../../src/third_party/modp_b64 \ No newline at end of file
diff --git a/third_party/mojo/MOJO_VERSION b/third_party/mojo/MOJO_VERSION new file mode 100644 index 0000000..90c3ebb --- /dev/null +++ b/third_party/mojo/MOJO_VERSION
@@ -0,0 +1 @@ +b88737ed62969ce3203085748f0d53ff4f09ba5b
diff --git a/third_party/mojo/src/mojo/public b/third_party/mojo/src/mojo/public new file mode 120000 index 0000000..fe8c801 --- /dev/null +++ b/third_party/mojo/src/mojo/public
@@ -0,0 +1 @@ +../../../../../src/mojo/public \ No newline at end of file
diff --git a/third_party/pyelftools b/third_party/pyelftools new file mode 120000 index 0000000..f3bb12b --- /dev/null +++ b/third_party/pyelftools
@@ -0,0 +1 @@ +../../src/third_party/pyelftools \ No newline at end of file
diff --git a/third_party/tcmalloc b/third_party/tcmalloc new file mode 120000 index 0000000..00c634c --- /dev/null +++ b/third_party/tcmalloc
@@ -0,0 +1 @@ +../../src/third_party/tcmalloc \ No newline at end of file
diff --git a/third_party/zlib b/third_party/zlib new file mode 120000 index 0000000..adaa983 --- /dev/null +++ b/third_party/zlib
@@ -0,0 +1 @@ +../../src/third_party/zlib \ No newline at end of file
diff --git a/tools b/tools new file mode 120000 index 0000000..2298617 --- /dev/null +++ b/tools
@@ -0,0 +1 @@ +../src/tools \ No newline at end of file