summaryrefslogtreecommitdiffstats
path: root/chrome/browser/plugin_download_helper.cc
blob: faf17dd8f1f5e639e8c29b7fa3ac362efc7928e6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/plugin_download_helper.h"

#include "base/bind.h"
#include "base/file_util.h"
#include "base/stringprintf.h"
#include "base/message_loop_proxy.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/url_fetcher.h"
#include "net/base/net_errors.h"
#include "net/url_request/url_request_status.h"

using content::BrowserThread;
using content::URLFetcher;

PluginDownloadUrlHelper::PluginDownloadUrlHelper() {
}

PluginDownloadUrlHelper::~PluginDownloadUrlHelper() {
}

void PluginDownloadUrlHelper::InitiateDownload(
    const GURL& download_url,
    net::URLRequestContextGetter* request_context,
    const DownloadFinishedCallback& finished_callback,
    const ErrorCallback& error_callback) {
  download_url_ = download_url;
  download_finished_callback_ = finished_callback;
  error_callback_ = error_callback;
  download_file_fetcher_.reset(URLFetcher::Create(
      download_url_, URLFetcher::GET, this));
  download_file_fetcher_->SetRequestContext(request_context);
  download_file_fetcher_->SaveResponseToTemporaryFile(
      BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE));
  download_file_fetcher_->Start();
}

void PluginDownloadUrlHelper::OnURLFetchComplete(const URLFetcher* source) {
  net::URLRequestStatus status = source->GetStatus();
  if (!status.is_success()) {
    RunErrorCallback(base::StringPrintf("Error %d: %s",
                                        status.error(),
                                        net::ErrorToString(status.error())));
    return;
  }
  int response_code = source->GetResponseCode();
  if (response_code != 200 &&
      response_code != URLFetcher::RESPONSE_CODE_INVALID) {
    // If we don't get a HTTP response code, the URL request either failed
    // (which should be covered by the status check above) or the fetched URL
    // was a file: URL (in unit tests for example), in which case it's fine.
    RunErrorCallback(base::StringPrintf("HTTP status %d", response_code));
    return;
  }
  bool success = source->GetResponseAsFilePath(true, &downloaded_file_);
  DCHECK(success);
  BrowserThread::PostTaskAndReply(
      BrowserThread::FILE, FROM_HERE,
      base::Bind(&PluginDownloadUrlHelper::RenameDownloadedFile,
                 base::Unretained(this)),
      base::Bind(&PluginDownloadUrlHelper::RunFinishedCallback,
                 base::Unretained(this)));
}

void PluginDownloadUrlHelper::RenameDownloadedFile() {
  FilePath new_download_file_path =
      downloaded_file_.DirName().AppendASCII(
          download_file_fetcher_->GetURL().ExtractFileName());

  file_util::Delete(new_download_file_path, false);

  if (file_util::ReplaceFile(downloaded_file_,
                             new_download_file_path)) {
    downloaded_file_ = new_download_file_path;
  } else {
    DPLOG(ERROR) << "Failed to rename file: "
                 << downloaded_file_.value()
                 << " to file: "
                 << new_download_file_path.value();
  }
}

void PluginDownloadUrlHelper::RunFinishedCallback() {
  download_finished_callback_.Run(downloaded_file_);
  delete this;
}

void PluginDownloadUrlHelper::RunErrorCallback(const std::string& msg) {
  error_callback_.Run(msg);
  delete this;
}