Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1076)

Unified Diff: services/sky_packaged_app_viewer/content_handler_impl.cc

Issue 1085853002: Introduce Sky packaged apps. (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Response to qsr's review Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: services/sky_packaged_app_viewer/content_handler_impl.cc
diff --git a/services/sky_packaged_app_viewer/content_handler_impl.cc b/services/sky_packaged_app_viewer/content_handler_impl.cc
new file mode 100644
index 0000000000000000000000000000000000000000..b53eac819d562edb23f9a110df11df02c94df69c
--- /dev/null
+++ b/services/sky_packaged_app_viewer/content_handler_impl.cc
@@ -0,0 +1,211 @@
+// 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 "services/sky_packaged_app_viewer/content_handler_impl.h"
+
+#include "base/bind.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/memory/scoped_vector.h"
+#include "base/strings/stringprintf.h"
+#include "mojo/common/data_pipe_utils.h"
+#include "mojo/public/cpp/application/connect.h"
+#include "mojo/public/cpp/bindings/strong_binding.h"
+#include "mojo/public/cpp/utility/run_loop.h"
+#include "mojo/services/http_server/public/cpp/http_server_util.h"
+#include "mojo/services/http_server/public/interfaces/http_server.mojom.h"
+#include "mojo/services/http_server/public/interfaces/http_server_factory.mojom.h"
+#include "sky/viewer/sky_loader.h"
+#include "third_party/zlib/google/zip_reader.h"
+
+namespace sky_packaged_app_viewer {
+
+class PendingRequest {
+ public:
+ PendingRequest(mojo::InterfaceRequest<mojo::ServiceProvider> services,
+ mojo::ServiceProviderPtr exposed_services)
+ : services(services.Pass()), exposed_services(exposed_services.Pass()) {}
+
+ mojo::InterfaceRequest<mojo::ServiceProvider> services;
+ mojo::ServiceProviderPtr exposed_services;
+};
+
+class HttpHandler : public http_server::HttpHandler {
+ public:
+ HttpHandler(const base::Callback<void(uint16_t)>& handler_ready_callback,
+ base::FilePath package_root,
+ http_server::HttpServerFactoryPtr http_server_factory)
+ : binding_(this),
+ handler_ready_callback_(handler_ready_callback),
+ package_root_(package_root) {
+ http_server::HttpHandlerPtr http_handler_ptr;
+ binding_.Bind(GetProxy(&http_handler_ptr));
+
+ http_server_factory->CreateHttpServer(GetProxy(&http_server_).Pass(),
+ nullptr);
+ http_server_->SetHandler(
+ "/.*", http_handler_ptr.Pass(),
+ base::Bind(&HttpHandler::AddHandlerCallback, base::Unretained(this)));
+ }
+
+ ~HttpHandler() override {}
+
+ // http_server::HttpHandler:
+ void HandleRequest(http_server::HttpRequestPtr request,
+ const mojo::Callback<void(http_server::HttpResponsePtr)>&
+ callback) override {
+ std::string relative_path = request->relative_url.get().substr(1);
+
+ // TODO(blundell): Add logic into creating sky_packaged_applications to
+ // make it unnecessary to strip off the "packages/" prefix, namely,
+ // putting all the dependent packages under "packages/".
+ std::string packages_prefix = "packages/";
+ if (!relative_path.compare(0, packages_prefix.size(), packages_prefix))
+ relative_path.erase(0, packages_prefix.size());
+
+ base::FilePath entry_path = package_root_.Append(relative_path);
+ std::string contents;
+ if (!base::ReadFileToString(entry_path, &contents)) {
+ NOTREACHED();
+ return;
+ }
+
+ callback.Run(http_server::CreateHttpResponse(200, contents));
+ }
+
+ void AddHandlerCallback(bool result) {
+ CHECK(result);
+ http_server_->GetPort(
+ base::Bind(&HttpHandler::GetPortCallback, base::Unretained(this)));
+ }
+
+ void GetPortCallback(uint16_t port) { handler_ready_callback_.Run(port); }
+
+ mojo::Binding<http_server::HttpHandler> binding_;
+ base::Callback<void(uint16_t)> handler_ready_callback_;
+ base::FilePath package_root_;
+ http_server::HttpServerPtr http_server_;
+
+ DISALLOW_COPY_AND_ASSIGN(HttpHandler);
+};
+
+class SkyPackagedApplication : public mojo::Application {
+ public:
+ SkyPackagedApplication(mojo::InterfaceRequest<mojo::Application> application,
+ mojo::URLResponsePtr response)
+ : binding_(this, application.Pass()),
+ initial_response_(response.Pass()) {}
+
+ void Initialize(mojo::ShellPtr shell,
+ mojo::Array<mojo::String> args,
+ const mojo::String& url) override {
+ shell_ = shell.Pass();
+ sky_loader_.reset(new sky::SkyLoader(shell_.get(), mojo::URLResponsePtr()));
+ }
+
+ void AcceptConnection(const mojo::String& requestor_url,
+ mojo::InterfaceRequest<mojo::ServiceProvider> services,
+ mojo::ServiceProviderPtr exposed_services,
+ const mojo::String& url) override {
+ if (local_entrypoint_url_ != "") {
+ DCHECK(!initial_response_);
+ sky_loader_->LoadApplication(
+ services.Pass(), exposed_services.Pass(), local_entrypoint_url_);
+ return;
+ }
+
+ PendingRequest* request =
+ new PendingRequest(services.Pass(), exposed_services.Pass());
+ pending_requests_.push_back(request);
+
+ if (initial_response_)
+ ExtractAndSetUpSkyApplication(initial_response_.Pass());
+ }
+
+ void RequestQuit() override { mojo::RunLoop::current()->Quit(); }
+
+ private:
+ void OnHandlerReady(uint16_t port) {
+ local_entrypoint_url_ =
+ base::StringPrintf("http://localhost:%hu/main.sky", port);
+ for (PendingRequest* pending_request : pending_requests_) {
+ sky_loader_->LoadApplication(pending_request->services.Pass(),
+ pending_request->exposed_services.Pass(),
+ local_entrypoint_url_);
+ }
+ pending_requests_.clear();
+ }
+
+ void ConnectToSkyApplication(
+ mojo::InterfaceRequest<mojo::ServiceProvider> services,
+ mojo::ServiceProviderPtr exposed_services) {
+ sky_loader_->LoadApplication(
+ services.Pass(), exposed_services.Pass(), local_entrypoint_url_);
+ }
+
+ void ExtractAndSetUpSkyApplication(mojo::URLResponsePtr response) {
+ // Extract the application.
+ CHECK(unpacked_app_directory_.CreateUniqueTempDir());
+ ExtractApplication(response.Pass());
+ base::FilePath package_root = unpacked_app_directory_.path();
+
+ // Start up the http handler that will serve the application.
+ mojo::ServiceProviderPtr service_provider;
+ shell_->ConnectToApplication("mojo:http_server",
+ mojo::GetProxy(&service_provider), nullptr);
+ http_server::HttpServerFactoryPtr http_server_factory;
+ mojo::ConnectToService(service_provider.get(), &http_server_factory);
+
+ http_handler_.reset(
+ new HttpHandler(base::Bind(&SkyPackagedApplication::OnHandlerReady,
+ base::Unretained(this)),
+ package_root, http_server_factory.Pass()));
+ }
+
+ // TODO(blundell): The below two functions should be moved into a utility
+ // file somewhere where they can be shared by this file, the Dart content
+ // handler, and the Python content handler.
+ void ExtractApplication(mojo::URLResponsePtr response) {
+ zip::ZipReader reader;
+ const std::string input_data = CopyToString(response->body.Pass());
+ CHECK(reader.OpenFromString(input_data));
+ base::FilePath temp_dir_path = unpacked_app_directory_.path();
+ while (reader.HasMore()) {
+ CHECK(reader.OpenCurrentEntryInZip());
+ CHECK(reader.ExtractCurrentEntryIntoDirectory(temp_dir_path));
+ CHECK(reader.AdvanceToNextEntry());
+ }
+ }
+
+ std::string CopyToString(mojo::ScopedDataPipeConsumerHandle body) {
+ std::string body_str;
+ bool result = mojo::common::BlockingCopyToString(body.Pass(), &body_str);
+ DCHECK(result);
+ return body_str;
+ }
+
+ mojo::StrongBinding<mojo::Application> binding_;
+ scoped_ptr<HttpHandler> http_handler_;
+ mojo::ShellPtr shell_;
+ mojo::URLResponsePtr initial_response_;
+ ScopedVector<PendingRequest> pending_requests_;
+ base::ScopedTempDir unpacked_app_directory_;
+ scoped_ptr<sky::SkyLoader> sky_loader_;
+ std::string local_entrypoint_url_;
+};
+
+ContentHandlerImpl::ContentHandlerImpl(
+ mojo::InterfaceRequest<mojo::ContentHandler> request)
+ : binding_(this, request.Pass()) {
+}
+
+ContentHandlerImpl::~ContentHandlerImpl() {
+}
+
+void ContentHandlerImpl::StartApplication(
+ mojo::InterfaceRequest<mojo::Application> application,
+ mojo::URLResponsePtr response) {
+ new SkyPackagedApplication(application.Pass(), response.Pass());
+}
+
+} // namespace sky_packaged_app_viewer
« no previous file with comments | « services/sky_packaged_app_viewer/content_handler_impl.h ('k') | services/sky_packaged_app_viewer/sky_packaged_app_viewer.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698