Home | History | Annotate | Download | only in package_manager
      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_fetcher.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/files/file_path.h"
      9 #include "base/files/file_util.h"
     10 #include "mojo/services/public/interfaces/network/url_loader.mojom.h"
     11 
     12 namespace mojo {
     13 
     14 PackageFetcher::PackageFetcher(NetworkService* network_service,
     15                                PackageFetcherDelegate* delegate,
     16                                const GURL& url)
     17     : delegate_(delegate),
     18       url_(url) {
     19   network_service->CreateURLLoader(Get(&loader_));
     20 
     21   URLRequestPtr request(URLRequest::New());
     22   request->url = url.spec();
     23   request->auto_follow_redirects = true;
     24 
     25   loader_->Start(request.Pass(),
     26                  base::Bind(&PackageFetcher::OnReceivedResponse,
     27                             base::Unretained(this)));
     28 }
     29 
     30 PackageFetcher::~PackageFetcher() {
     31 }
     32 
     33 void PackageFetcher::OnReceivedResponse(URLResponsePtr response) {
     34   if (response->error) {
     35     printf("Got error %d (%s) for %s\n",
     36            response->error->code,
     37            response->error->description.get().c_str(),
     38            url_.spec().c_str());
     39     delegate_->FetchFailed(url_);
     40     return;
     41   }
     42 
     43   if (!base::CreateTemporaryFile(&output_file_name_)) {
     44     delegate_->FetchFailed(url_);
     45     return;
     46   }
     47   output_file_.Initialize(output_file_name_,
     48       base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);
     49   if (!output_file_.IsValid()) {
     50     base::DeleteFile(output_file_name_, false);
     51     delegate_->FetchFailed(url_);
     52     // Danger: may be deleted now.
     53     return;
     54   }
     55 
     56   body_ = response->body.Pass();
     57   ReadData(MOJO_RESULT_OK);
     58   // Danger: may be deleted now.
     59 }
     60 
     61 void PackageFetcher::ReadData(MojoResult) {
     62   char buf[4096];
     63   uint32_t num_bytes = sizeof(buf);
     64   MojoResult result = ReadDataRaw(body_.get(), buf, &num_bytes,
     65                                   MOJO_READ_DATA_FLAG_NONE);
     66   if (result == MOJO_RESULT_SHOULD_WAIT) {
     67     WaitToReadMore();
     68   } else if (result == MOJO_RESULT_OK) {
     69     if (output_file_.WriteAtCurrentPos(buf, num_bytes) !=
     70         static_cast<int>(num_bytes)) {
     71       // Clean up the output file.
     72       output_file_.Close();
     73       base::DeleteFile(output_file_name_, false);
     74 
     75       delegate_->FetchFailed(url_);
     76       // Danger: may be deleted now.
     77       return;
     78     }
     79     WaitToReadMore();
     80   } else if (result == MOJO_RESULT_FAILED_PRECONDITION) {
     81     // Done.
     82     output_file_.Close();
     83     delegate_->FetchSucceeded(url_, output_file_name_);
     84     // Danger: may be deleted now.
     85   }
     86 }
     87 
     88 void PackageFetcher::WaitToReadMore() {
     89   handle_watcher_.Start(
     90       body_.get(),
     91       MOJO_HANDLE_SIGNAL_READABLE,
     92       MOJO_DEADLINE_INDEFINITE,
     93       base::Bind(&PackageFetcher::ReadData, base::Unretained(this)));
     94 }
     95 
     96 }  // namespace mojo
     97