11320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Copyright 2014 The Chromium Authors. All rights reserved.
21320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Use of this source code is governed by a BSD-style license that can be
31320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// found in the LICENSE file.
41320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
51320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "mojo/tools/package_manager/package_fetcher.h"
61320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
71320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/bind.h"
81320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_path.h"
91320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h"
101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "mojo/services/public/interfaces/network/url_loader.mojom.h"
111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccinamespace mojo {
131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciPackageFetcher::PackageFetcher(NetworkService* network_service,
151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                               PackageFetcherDelegate* delegate,
161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                               const GURL& url)
171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    : delegate_(delegate),
181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      url_(url) {
191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  network_service->CreateURLLoader(Get(&loader_));
201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  URLRequestPtr request(URLRequest::New());
221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  request->url = url.spec();
231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  request->auto_follow_redirects = true;
241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  loader_->Start(request.Pass(),
261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 base::Bind(&PackageFetcher::OnReceivedResponse,
271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                            base::Unretained(this)));
281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciPackageFetcher::~PackageFetcher() {
311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid PackageFetcher::OnReceivedResponse(URLResponsePtr response) {
341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (response->error) {
351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    printf("Got error %d (%s) for %s\n",
361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci           response->error->code,
371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci           response->error->description.get().c_str(),
381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci           url_.spec().c_str());
391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    delegate_->FetchFailed(url_);
401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return;
411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!base::CreateTemporaryFile(&output_file_name_)) {
441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    delegate_->FetchFailed(url_);
451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return;
461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  output_file_.Initialize(output_file_name_,
481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);
491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!output_file_.IsValid()) {
501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    base::DeleteFile(output_file_name_, false);
511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    delegate_->FetchFailed(url_);
521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // Danger: may be deleted now.
531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return;
541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  body_ = response->body.Pass();
571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ReadData(MOJO_RESULT_OK);
581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Danger: may be deleted now.
591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid PackageFetcher::ReadData(MojoResult) {
621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  char buf[4096];
631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  uint32_t num_bytes = sizeof(buf);
641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  MojoResult result = ReadDataRaw(body_.get(), buf, &num_bytes,
651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                  MOJO_READ_DATA_FLAG_NONE);
661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (result == MOJO_RESULT_SHOULD_WAIT) {
671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    WaitToReadMore();
681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  } else if (result == MOJO_RESULT_OK) {
691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (output_file_.WriteAtCurrentPos(buf, num_bytes) !=
701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        static_cast<int>(num_bytes)) {
711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // Clean up the output file.
721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      output_file_.Close();
731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      base::DeleteFile(output_file_name_, false);
741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      delegate_->FetchFailed(url_);
761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // Danger: may be deleted now.
771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return;
781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    }
791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    WaitToReadMore();
801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  } else if (result == MOJO_RESULT_FAILED_PRECONDITION) {
811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // Done.
821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    output_file_.Close();
831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    delegate_->FetchSucceeded(url_, output_file_name_);
841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // Danger: may be deleted now.
851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid PackageFetcher::WaitToReadMore() {
891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  handle_watcher_.Start(
901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      body_.get(),
911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      MOJO_HANDLE_SIGNAL_READABLE,
921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      MOJO_DEADLINE_INDEFINITE,
931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      base::Bind(&PackageFetcher::ReadData, base::Unretained(this)));
941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}  // namespace mojo
97