15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/plugins/plugin_installer.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind_helpers.h"
9bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch#include "base/process/process.h"
107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "base/strings/stringprintf.h"
11ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "chrome/browser/download/download_stats.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/platform_util.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/plugins/plugin_installer_observer.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_context.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/download_item.h"
160529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "content/public/browser/download_manager.h"
175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/public/browser/download_url_parameters.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_contents.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::DownloadItem;
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PluginInstaller::PluginInstaller()
23424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    : state_(INSTALLER_STATE_IDLE),
24424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      strong_observer_count_(0) {
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PluginInstaller::~PluginInstaller() {
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PluginInstaller::OnDownloadUpdated(DownloadItem* download) {
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DownloadItem::DownloadState state = download->GetState();
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (state) {
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case DownloadItem::IN_PROGRESS:
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case DownloadItem::COMPLETE: {
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DCHECK_EQ(INSTALLER_STATE_DOWNLOADING, state_);
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      state_ = INSTALLER_STATE_IDLE;
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FOR_EACH_OBSERVER(PluginInstallerObserver, observers_,
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        DownloadFinished());
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case DownloadItem::CANCELLED: {
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DownloadCancelled();
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case DownloadItem::INTERRUPTED: {
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content::DownloadInterruptReason reason = download->GetLastReason();
485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      DownloadError(content::DownloadInterruptReasonToString(reason));
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case DownloadItem::MAX_DOWNLOAD_STATE: {
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED();
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  download->RemoveObserver(this);
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PluginInstaller::OnDownloadDestroyed(DownloadItem* download) {
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(INSTALLER_STATE_DOWNLOADING, state_);
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  state_ = INSTALLER_STATE_IDLE;
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  download->RemoveObserver(this);
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PluginInstaller::AddObserver(PluginInstallerObserver* observer) {
66424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  strong_observer_count_++;
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  observers_.AddObserver(observer);
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PluginInstaller::RemoveObserver(PluginInstallerObserver* observer) {
71424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  strong_observer_count_--;
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  observers_.RemoveObserver(observer);
73424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (strong_observer_count_ == 0) {
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FOR_EACH_OBSERVER(WeakPluginInstallerObserver, weak_observers_,
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      OnlyWeakObserversLeft());
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PluginInstaller::AddWeakObserver(WeakPluginInstallerObserver* observer) {
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  weak_observers_.AddObserver(observer);
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PluginInstaller::RemoveWeakObserver(
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WeakPluginInstallerObserver* observer) {
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  weak_observers_.RemoveObserver(observer);
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PluginInstaller::StartInstalling(const GURL& plugin_url,
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      content::WebContents* web_contents) {
900529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  content::DownloadManager* download_manager =
910529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      content::BrowserContext::GetDownloadManager(
920529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          web_contents->GetBrowserContext());
930529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  StartInstallingWithDownloadManager(
940529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      plugin_url, web_contents, download_manager);
950529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
960529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
970529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid PluginInstaller::StartInstallingWithDownloadManager(
980529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    const GURL& plugin_url,
990529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    content::WebContents* web_contents,
1000529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    content::DownloadManager* download_manager) {
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(INSTALLER_STATE_IDLE, state_);
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  state_ = INSTALLER_STATE_DOWNLOADING;
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FOR_EACH_OBSERVER(PluginInstallerObserver, observers_, DownloadStarted());
1040529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  scoped_ptr<content::DownloadUrlParameters> download_parameters(
1050529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      content::DownloadUrlParameters::FromWebContents(web_contents,
1060529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                                                      plugin_url));
1070529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  download_parameters->set_callback(
1080529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      base::Bind(&PluginInstaller::DownloadStarted, base::Unretained(this)));
109ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  RecordDownloadSource(DOWNLOAD_INITIATED_BY_PLUGIN_INSTALLER);
1100529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  download_manager->DownloadUrl(download_parameters.Pass());
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void PluginInstaller::DownloadStarted(
1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    content::DownloadItem* item,
1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    content::DownloadInterruptReason interrupt_reason) {
1160529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (interrupt_reason != content::DOWNLOAD_INTERRUPT_REASON_NONE) {
1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    std::string msg = base::StringPrintf(
1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        "Error %d: %s",
1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        interrupt_reason,
1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        content::DownloadInterruptReasonToString(interrupt_reason).c_str());
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DownloadError(msg);
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  item->SetOpenWhenComplete(true);
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  item->AddObserver(this);
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PluginInstaller::OpenDownloadURL(const GURL& plugin_url,
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      content::WebContents* web_contents) {
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(INSTALLER_STATE_IDLE, state_);
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  web_contents->OpenURL(content::OpenURLParams(
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      plugin_url,
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content::Referrer(web_contents->GetURL(),
134f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                        blink::WebReferrerPolicyDefault),
1351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      NEW_FOREGROUND_TAB, ui::PAGE_TRANSITION_TYPED, false));
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FOR_EACH_OBSERVER(PluginInstallerObserver, observers_, DownloadFinished());
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PluginInstaller::DownloadError(const std::string& msg) {
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(INSTALLER_STATE_DOWNLOADING, state_);
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  state_ = INSTALLER_STATE_IDLE;
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FOR_EACH_OBSERVER(PluginInstallerObserver, observers_, DownloadError(msg));
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PluginInstaller::DownloadCancelled() {
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(INSTALLER_STATE_DOWNLOADING, state_);
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  state_ = INSTALLER_STATE_IDLE;
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FOR_EACH_OBSERVER(PluginInstallerObserver, observers_, DownloadCancelled());
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
150