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

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: Switch to using local http server 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 "mojo/common/data_pipe_utils.h"
10 #include "mojo/public/cpp/application/connect.h"
11 #include "mojo/public/cpp/bindings/strong_binding.h"
12 #include "mojo/public/cpp/utility/run_loop.h"
13 #include "mojo/services/http_server/public/cpp/http_server_util.h"
14 #include "mojo/services/http_server/public/interfaces/http_server.mojom.h"
15 #include "mojo/services/http_server/public/interfaces/http_server_factory.mojom. h"
16 #include "third_party/zlib/google/zip_reader.h"
17
18 namespace sky_packaged_app_viewer {
19
20 class HttpHandler : public http_server::HttpHandler {
21 public:
22 HttpHandler(const base::Callback<void(uint16_t)>& handler_ready_callback,
23 base::FilePath package_root,
24 http_server::HttpServerFactoryPtr http_server_factory)
25 : binding_(this),
26 handler_ready_callback_(handler_ready_callback),
27 package_root_(package_root) {
28 http_server::HttpHandlerPtr http_handler_ptr;
29 binding_.Bind(GetProxy(&http_handler_ptr));
30
31 http_server_factory->CreateHttpServer(GetProxy(&http_server_).Pass(),
32 nullptr);
33 http_server_->SetHandler(
34 "/.*", http_handler_ptr.Pass(),
35 base::Bind(&HttpHandler::AddHandlerCallback, base::Unretained(this)));
36 }
37
38 ~HttpHandler() override {}
39
40 // http_server::HttpHandler:
41 void HandleRequest(http_server::HttpRequestPtr request,
42 const mojo::Callback<void(http_server::HttpResponsePtr)>&
43 callback) override {
44 std::string relative_path = request->relative_url.get().substr(1);
45
46 // TODO(blundell): Add logic into creating sky_packaged_applications to
47 // make it unnecessary to strip off the "packages/" prefix, namely,
48 // putting all the dependent packages under "packages/".
49 std::string packages_prefix = "packages/";
50 if (!relative_path.compare(0, packages_prefix.size(), packages_prefix))
51 relative_path.erase(0, packages_prefix.size());
52
53 base::FilePath entry_path = package_root_.Append(relative_path);
54 std::string contents;
55 if (!base::ReadFileToString(entry_path, &contents)) {
56 NOTREACHED();
57 return;
58 }
59
60 callback.Run(http_server::CreateHttpResponse(200, contents));
61 }
62
63 void AddHandlerCallback(bool result) {
64 CHECK(result);
65 http_server_->GetPort(
66 base::Bind(&HttpHandler::GetPortCallback, base::Unretained(this)));
67 }
68
69 void GetPortCallback(uint16_t port) { handler_ready_callback_.Run(port); }
70
71 mojo::Binding<http_server::HttpHandler> binding_;
72 base::Callback<void(uint16_t)> handler_ready_callback_;
73 base::FilePath package_root_;
74 http_server::HttpServerPtr http_server_;
75
76 DISALLOW_COPY_AND_ASSIGN(HttpHandler);
77 };
78
79 class SkyPackagedApplication : public mojo::Application {
80 public:
81 SkyPackagedApplication(mojo::InterfaceRequest<mojo::Application> application,
82 mojo::URLResponsePtr response)
83 : binding_(this, application.Pass()),
84 initial_response_(response.Pass()),
85 port_(0) {}
86
87 void Initialize(mojo::ShellPtr shell,
88 mojo::Array<mojo::String> args,
89 const mojo::String& url) override {
90 shell_ = shell.Pass();
91 }
92
93 void AcceptConnection(const mojo::String& requestor_url,
94 mojo::InterfaceRequest<mojo::ServiceProvider> services,
95 mojo::ServiceProviderPtr exposed_services,
96 const mojo::String& url) override {
97 if (initial_response_) {
98 // TODO(blundell): Once I'm saving pending requests, can just add
99 // |services| and |exposed_services| to pending requests list instead of
100 // threading them through.
101 OnResponseReceived(mojo::URLLoaderPtr(), services.Pass(),
102 exposed_services.Pass(), initial_response_.Pass());
103 } else {
104 if (port_) {
105 ConnectToSkyApplication(services.Pass(), exposed_services.Pass());
106 } else {
107 // TODO(blundell): If the handler ready isn't yet, need to save
108 // |services| and |exposed_services| and connect once the handler is
109 // ready.
110 DCHECK(0);
111 }
112 }
113 }
114
115 void RequestQuit() override { mojo::RunLoop::current()->Quit(); }
116
117 private:
118 void OnHandlerReady(mojo::InterfaceRequest<mojo::ServiceProvider> services,
119 mojo::ServiceProviderPtr exposed_services,
120 uint16_t port) {
121 port_ = port;
122 ConnectToSkyApplication(services.Pass(), exposed_services.Pass());
123 }
124
125 void ConnectToSkyApplication(
126 mojo::InterfaceRequest<mojo::ServiceProvider> services,
127 mojo::ServiceProviderPtr exposed_services) {
128 shell_->ConnectToApplication(
129 "http://localhost:" + std::to_string(port_) + "/main.sky",
eseidel 2015/04/15 19:45:04 We're eventually going to remove the main.sky and
130 services.Pass(), exposed_services.Pass());
qsr 2015/04/15 21:56:29 I think we should not do this. Application identit
131 }
132
133 void OnResponseReceived(
134 mojo::URLLoaderPtr loader,
135 mojo::InterfaceRequest<mojo::ServiceProvider> services,
136 mojo::ServiceProviderPtr exposed_services,
137 mojo::URLResponsePtr response) {
138 // Extract the application.
139 CHECK(unpacked_app_directory_.CreateUniqueTempDir());
140 ExtractApplication(response.Pass());
eseidel 2015/04/15 19:45:04 Eventually one could just serve straight out of th
141 base::FilePath package_root = unpacked_app_directory_.path();
142
143 // Start up the http handler that will serve the application.
144 mojo::ServiceProviderPtr service_provider;
145 shell_->ConnectToApplication("mojo:http_server",
146 mojo::GetProxy(&service_provider), nullptr);
147 http_server::HttpServerFactoryPtr http_server_factory;
148 mojo::ConnectToService(service_provider.get(), &http_server_factory);
149
150 http_handler_.reset(new HttpHandler(
151 base::Bind(&SkyPackagedApplication::OnHandlerReady,
152 base::Unretained(this), base::Passed(&services),
153 base::Passed(&exposed_services)),
154 package_root, http_server_factory.Pass()));
155 }
156
157 // TODO(blundell): The below two functions should be moved into a utility
158 // file somewhere where they can be shared by this file, the Dart content
159 // handler, and the Python content handler.
160 void ExtractApplication(mojo::URLResponsePtr response) {
161 zip::ZipReader reader;
162 const std::string input_data = CopyToString(response->body.Pass());
163 CHECK(reader.OpenFromString(input_data));
164 base::FilePath temp_dir_path = unpacked_app_directory_.path();
165 while (reader.HasMore()) {
166 CHECK(reader.OpenCurrentEntryInZip());
167 CHECK(reader.ExtractCurrentEntryIntoDirectory(temp_dir_path));
168 CHECK(reader.AdvanceToNextEntry());
169 }
170 }
171
172 std::string CopyToString(mojo::ScopedDataPipeConsumerHandle body) {
173 std::string body_str;
174 bool result = mojo::common::BlockingCopyToString(body.Pass(), &body_str);
175 DCHECK(result);
176 return body_str;
177 }
178
179 mojo::StrongBinding<mojo::Application> binding_;
180 scoped_ptr<HttpHandler> http_handler_;
181 mojo::ShellPtr shell_;
182 mojo::URLResponsePtr initial_response_;
183 uint16_t port_;
184 base::ScopedTempDir unpacked_app_directory_;
185 };
186
187 ContentHandlerImpl::ContentHandlerImpl(
188 mojo::InterfaceRequest<mojo::ContentHandler> request)
189 : binding_(this, request.Pass()) {
190 }
191
192 ContentHandlerImpl::~ContentHandlerImpl() {
193 }
194
195 void ContentHandlerImpl::StartApplication(
196 mojo::InterfaceRequest<mojo::Application> application,
197 mojo::URLResponsePtr response) {
198 new SkyPackagedApplication(application.Pass(), response.Pass());
199 }
200
201 } // 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