1// Copyright 2014 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 "mojo/tools/package_manager/package_manager_application.h"
6
7#include "base/files/file_util.h"
8#include "mojo/tools/package_manager/manifest.h"
9#include "mojo/tools/package_manager/unpacker.h"
10#include "base/message_loop/message_loop.h"
11#include "base/stl_util.h"
12#include "mojo/public/cpp/application/application_impl.h"
13
14namespace mojo {
15
16namespace {
17
18const base::FilePath::CharType kManifestFileName[] =
19    FILE_PATH_LITERAL("manifest.json");
20
21}  // namespace
22
23PackageManagerApplication::PendingLoad::PendingLoad() {
24}
25
26PackageManagerApplication::PendingLoad::~PendingLoad() {
27}
28
29PackageManagerApplication::PackageManagerApplication() {
30}
31
32PackageManagerApplication::~PackageManagerApplication() {
33  STLDeleteContainerPairSecondPointers(pending_.begin(), pending_.end());
34}
35
36void PackageManagerApplication::Initialize(ApplicationImpl* app) {
37  app->ConnectToService("mojo:mojo_network_service", &network_service_);
38
39  printf("Enter URL> ");
40  char buf[1024];
41  if (scanf("%1023s", buf) != 1) {
42    printf("No input, exiting\n");
43    base::MessageLoop::current()->Quit();
44    return;
45  }
46  GURL url(buf);
47  if (!url.is_valid()) {
48    printf("Invalid URL\n");
49    base::MessageLoop::current()->Quit();
50    return;
51  }
52
53  StartLoad(url);
54}
55
56void PackageManagerApplication::StartLoad(const GURL& url) {
57  if (completed_.find(url) != completed_.end() ||
58      pending_.find(url) != pending_.end())
59    return;  // Already loaded or are loading this one.
60
61  PendingLoad* load = new PendingLoad;
62  load->fetcher.reset(new mojo::PackageFetcher(
63      network_service_.get(), this, url));
64  pending_[url] = load;
65}
66
67void PackageManagerApplication::LoadDeps(const Manifest& manifest) {
68  for (size_t i = 0; i < manifest.deps().size(); i++)
69    StartLoad(manifest.deps()[i]);
70}
71
72void PackageManagerApplication::PendingLoadComplete(const GURL& url) {
73  pending_.erase(pending_.find(url));
74  completed_.insert(url);
75  if (pending_.empty())
76    base::MessageLoop::current()->Quit();
77}
78
79void PackageManagerApplication::FetchSucceeded(
80    const GURL& url,
81    const base::FilePath& name) {
82  Unpacker unpacker;
83  if (!unpacker.Unpack(name)) {
84    base::DeleteFile(name, false);
85    printf("Failed to unpack\n");
86    PendingLoadComplete(url);
87    return;
88  }
89  // The downloaded .zip file is no longer necessary.
90  base::DeleteFile(name, false);
91
92  // Load the manifest.
93  base::FilePath manifest_path = unpacker.dir().Append(kManifestFileName);
94  Manifest manifest;
95  std::string err_msg;
96  if (!manifest.ParseFromFile(manifest_path, &err_msg)) {
97    printf("%s\n", err_msg.c_str());
98    PendingLoadComplete(url);
99    return;
100  }
101
102  // Enqueue loads for any deps.
103  LoadDeps(manifest);
104
105  printf("Loaded %s\n", url.spec().c_str());
106  PendingLoadComplete(url);
107}
108
109void PackageManagerApplication::FetchFailed(const GURL& url) {
110  PendingLoadComplete(url);
111}
112
113}  // namespace mojo
114