Chromium Code Reviews| Index: sky/viewer/content_handler_impl.cc |
| diff --git a/sky/viewer/content_handler_impl.cc b/sky/viewer/content_handler_impl.cc |
| index b36e4f7cbdc66e0cd07a0be2a9ea2a565da58dc8..3a1f48654789fc530b7a2472ecd13e25c708d4b4 100644 |
| --- a/sky/viewer/content_handler_impl.cc |
| +++ b/sky/viewer/content_handler_impl.cc |
| @@ -5,11 +5,14 @@ |
| #include "sky/viewer/content_handler_impl.h" |
| #include "base/bind.h" |
| +#include "base/files/scoped_temp_dir.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/network/public/interfaces/network_service.mojom.h" |
| #include "sky/viewer/document_view.h" |
| +#include "third_party/zlib/google/zip_reader.h" |
| namespace sky { |
| @@ -18,7 +21,8 @@ class SkyApplication : public mojo::Application { |
| SkyApplication(mojo::InterfaceRequest<mojo::Application> application, |
| mojo::URLResponsePtr response) |
| : binding_(this, application.Pass()), |
| - initial_response_(response.Pass()) {} |
| + initial_response_(response.Pass()), |
| + is_packaged_application_(false) {} |
| void Initialize(mojo::ShellPtr shell, |
| mojo::Array<mojo::String> args, |
| @@ -34,6 +38,9 @@ class SkyApplication : public mojo::Application { |
| mojo::InterfaceRequest<mojo::ServiceProvider> services, |
| mojo::ServiceProviderPtr exposed_services, |
| const mojo::String& url) override { |
| + if (url.get().rfind(".mojo") == url.size() - 5) { |
|
tonyg
2015/04/14 14:36:57
Maybe just a TODO in this patch, but it seems like
|
| + is_packaged_application_ = true; |
| + } |
| if (initial_response_) { |
| OnResponseReceived(mojo::URLLoaderPtr(), services.Pass(), |
| exposed_services.Pass(), initial_response_.Pass()); |
| @@ -66,14 +73,64 @@ class SkyApplication : public mojo::Application { |
| mojo::InterfaceRequest<mojo::ServiceProvider> services, |
| mojo::ServiceProviderPtr exposed_services, |
| mojo::URLResponsePtr response) { |
| - new DocumentView(services.Pass(), exposed_services.Pass(), response.Pass(), |
| + mojo::URLResponsePtr entrypoint = mojo::URLResponse::New(); |
| + if (is_packaged_application_) { |
| + CHECK(unpacked_app_directory_.CreateUniqueTempDir()); |
| + ExtractApplication(response.Pass()); |
| + base::FilePath package_root = unpacked_app_directory_.path(); |
| + |
| + base::FilePath entry_path = package_root.Append("main.sky"); |
|
tonyg
2015/04/14 14:36:56
Is it a good idea to enforce the "main.sky" name?
|
| + std::string url = "file://" + entry_path.value(); |
| + entrypoint->url = url; |
| + |
| + // TODO(blundell): This should use |mojo::common::CopyFromFile()| on a |
| + // background thread to do the file read asynchronously. |
| + std::string source; |
| + if (!base::ReadFileToString(entry_path, &source)) { |
| + NOTREACHED(); |
| + return; |
| + } |
| + mojo::ScopedDataPipeProducerHandle producer_handle; |
| + mojo::CreateDataPipe(NULL, &producer_handle, &entrypoint->body); |
| + DCHECK(mojo::common::BlockingCopyFromString(source, producer_handle)); |
| + producer_handle.reset(); |
| + } else { |
| + entrypoint = response.Pass(); |
| + } |
| + |
| + new DocumentView(services.Pass(), exposed_services.Pass(), |
| + entrypoint.Pass(), |
| shell_.get()); |
| } |
| + // 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()); |
|
tonyg
2015/04/14 14:36:57
This seems worthy of a comment about a background
|
| + CHECK(reader.OpenFromString(input_data)); |
|
tonyg
2015/04/14 14:36:57
Do we really want to crash upon corrupted .mojo fi
|
| + 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_; |
| mojo::ShellPtr shell_; |
| mojo::NetworkServicePtr network_service_; |
| mojo::URLResponsePtr initial_response_; |
| + bool is_packaged_application_; |
| + base::ScopedTempDir unpacked_app_directory_; |
| }; |
| ContentHandlerImpl::ContentHandlerImpl( |