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

Side by Side 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 unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "services/sky_packaged_app_viewer/content_handler_impl.h"
6
7 #include "base/bind.h"
8 #include "base/files/scoped_temp_dir.h"
9 #include "base/memory/scoped_vector.h"
10 #include "base/strings/stringprintf.h"
11 #include "mojo/common/data_pipe_utils.h"
12 #include "mojo/public/cpp/application/connect.h"
13 #include "mojo/public/cpp/bindings/strong_binding.h"
14 #include "mojo/public/cpp/utility/run_loop.h"
15 #include "mojo/services/http_server/public/cpp/http_server_util.h"
16 #include "mojo/services/http_server/public/interfaces/http_server.mojom.h"
17 #include "mojo/services/http_server/public/interfaces/http_server_factory.mojom. h"
18 #include "sky/viewer/sky_loader.h"
19 #include "third_party/zlib/google/zip_reader.h"
20
21 namespace sky_packaged_app_viewer {
22
23 class PendingRequest {
24 public:
25 PendingRequest(mojo::InterfaceRequest<mojo::ServiceProvider> services,
26 mojo::ServiceProviderPtr exposed_services)
27 : services(services.Pass()), exposed_services(exposed_services.Pass()) {}
28
29 mojo::InterfaceRequest<mojo::ServiceProvider> services;
30 mojo::ServiceProviderPtr exposed_services;
31 };
32
33 class HttpHandler : public http_server::HttpHandler {
34 public:
35 HttpHandler(const base::Callback<void(uint16_t)>& handler_ready_callback,
36 base::FilePath package_root,
37 http_server::HttpServerFactoryPtr http_server_factory)
38 : binding_(this),
39 handler_ready_callback_(handler_ready_callback),
40 package_root_(package_root) {
41 http_server::HttpHandlerPtr http_handler_ptr;
42 binding_.Bind(GetProxy(&http_handler_ptr));
43
44 http_server_factory->CreateHttpServer(GetProxy(&http_server_).Pass(),
45 nullptr);
46 http_server_->SetHandler(
47 "/.*", http_handler_ptr.Pass(),
48 base::Bind(&HttpHandler::AddHandlerCallback, base::Unretained(this)));
49 }
50
51 ~HttpHandler() override {}
52
53 // http_server::HttpHandler:
54 void HandleRequest(http_server::HttpRequestPtr request,
55 const mojo::Callback<void(http_server::HttpResponsePtr)>&
56 callback) override {
57 std::string relative_path = request->relative_url.get().substr(1);
58
59 // TODO(blundell): Add logic into creating sky_packaged_applications to
60 // make it unnecessary to strip off the "packages/" prefix, namely,
61 // putting all the dependent packages under "packages/".
62 std::string packages_prefix = "packages/";
63 if (!relative_path.compare(0, packages_prefix.size(), packages_prefix))
64 relative_path.erase(0, packages_prefix.size());
65
66 base::FilePath entry_path = package_root_.Append(relative_path);
67 std::string contents;
68 if (!base::ReadFileToString(entry_path, &contents)) {
69 NOTREACHED();
70 return;
71 }
72
73 callback.Run(http_server::CreateHttpResponse(200, contents));
74 }
75
76 void AddHandlerCallback(bool result) {
77 CHECK(result);
78 http_server_->GetPort(
79 base::Bind(&HttpHandler::GetPortCallback, base::Unretained(this)));
80 }
81
82 void GetPortCallback(uint16_t port) { handler_ready_callback_.Run(port); }
83
84 mojo::Binding<http_server::HttpHandler> binding_;
85 base::Callback<void(uint16_t)> handler_ready_callback_;
86 base::FilePath package_root_;
87 http_server::HttpServerPtr http_server_;
88
89 DISALLOW_COPY_AND_ASSIGN(HttpHandler);
90 };
91
92 class SkyPackagedApplication : public mojo::Application {
93 public:
94 SkyPackagedApplication(mojo::InterfaceRequest<mojo::Application> application,
95 mojo::URLResponsePtr response)
96 : binding_(this, application.Pass()),
97 initial_response_(response.Pass()) {}
98
99 void Initialize(mojo::ShellPtr shell,
100 mojo::Array<mojo::String> args,
101 const mojo::String& url) override {
102 shell_ = shell.Pass();
103 sky_loader_.reset(new sky::SkyLoader(shell_.get(), mojo::URLResponsePtr()));
104 }
105
106 void AcceptConnection(const mojo::String& requestor_url,
107 mojo::InterfaceRequest<mojo::ServiceProvider> services,
108 mojo::ServiceProviderPtr exposed_services,
109 const mojo::String& url) override {
110 if (local_entrypoint_url_ != "") {
111 DCHECK(!initial_response_);
112 sky_loader_->LoadApplication(
113 services.Pass(), exposed_services.Pass(), local_entrypoint_url_);
114 return;
115 }
116
117 PendingRequest* request =
118 new PendingRequest(services.Pass(), exposed_services.Pass());
119 pending_requests_.push_back(request);
120
121 if (initial_response_)
122 ExtractAndSetUpSkyApplication(initial_response_.Pass());
123 }
124
125 void RequestQuit() override { mojo::RunLoop::current()->Quit(); }
126
127 private:
128 void OnHandlerReady(uint16_t port) {
129 local_entrypoint_url_ =
130 base::StringPrintf("http://localhost:%hu/main.sky", port);
131 for (PendingRequest* pending_request : pending_requests_) {
132 sky_loader_->LoadApplication(pending_request->services.Pass(),
133 pending_request->exposed_services.Pass(),
134 local_entrypoint_url_);
135 }
136 pending_requests_.clear();
137 }
138
139 void ConnectToSkyApplication(
140 mojo::InterfaceRequest<mojo::ServiceProvider> services,
141 mojo::ServiceProviderPtr exposed_services) {
142 sky_loader_->LoadApplication(
143 services.Pass(), exposed_services.Pass(), local_entrypoint_url_);
144 }
145
146 void ExtractAndSetUpSkyApplication(mojo::URLResponsePtr response) {
147 // Extract the application.
148 CHECK(unpacked_app_directory_.CreateUniqueTempDir());
149 ExtractApplication(response.Pass());
150 base::FilePath package_root = unpacked_app_directory_.path();
151
152 // Start up the http handler that will serve the application.
153 mojo::ServiceProviderPtr service_provider;
154 shell_->ConnectToApplication("mojo:http_server",
155 mojo::GetProxy(&service_provider), nullptr);
156 http_server::HttpServerFactoryPtr http_server_factory;
157 mojo::ConnectToService(service_provider.get(), &http_server_factory);
158
159 http_handler_.reset(
160 new HttpHandler(base::Bind(&SkyPackagedApplication::OnHandlerReady,
161 base::Unretained(this)),
162 package_root, http_server_factory.Pass()));
163 }
164
165 // TODO(blundell): The below two functions should be moved into a utility
166 // file somewhere where they can be shared by this file, the Dart content
167 // handler, and the Python content handler.
168 void ExtractApplication(mojo::URLResponsePtr response) {
169 zip::ZipReader reader;
170 const std::string input_data = CopyToString(response->body.Pass());
171 CHECK(reader.OpenFromString(input_data));
172 base::FilePath temp_dir_path = unpacked_app_directory_.path();
173 while (reader.HasMore()) {
174 CHECK(reader.OpenCurrentEntryInZip());
175 CHECK(reader.ExtractCurrentEntryIntoDirectory(temp_dir_path));
176 CHECK(reader.AdvanceToNextEntry());
177 }
178 }
179
180 std::string CopyToString(mojo::ScopedDataPipeConsumerHandle body) {
181 std::string body_str;
182 bool result = mojo::common::BlockingCopyToString(body.Pass(), &body_str);
183 DCHECK(result);
184 return body_str;
185 }
186
187 mojo::StrongBinding<mojo::Application> binding_;
188 scoped_ptr<HttpHandler> http_handler_;
189 mojo::ShellPtr shell_;
190 mojo::URLResponsePtr initial_response_;
191 ScopedVector<PendingRequest> pending_requests_;
192 base::ScopedTempDir unpacked_app_directory_;
193 scoped_ptr<sky::SkyLoader> sky_loader_;
194 std::string local_entrypoint_url_;
195 };
196
197 ContentHandlerImpl::ContentHandlerImpl(
198 mojo::InterfaceRequest<mojo::ContentHandler> request)
199 : binding_(this, request.Pass()) {
200 }
201
202 ContentHandlerImpl::~ContentHandlerImpl() {
203 }
204
205 void ContentHandlerImpl::StartApplication(
206 mojo::InterfaceRequest<mojo::Application> application,
207 mojo::URLResponsePtr response) {
208 new SkyPackagedApplication(application.Pass(), response.Pass());
209 }
210
211 } // namespace sky_packaged_app_viewer
OLDNEW
« 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