summaryrefslogtreecommitdiffstats
path: root/chrome/browser/download/download_crx_util.cc
blob: d8b298f38e98853c02d0da6fab3704aa0cc2fb7e (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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
// 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.
//
// Download code which handles CRX files (extensions, themes, apps, ...).

#include "chrome/browser/download/download_util.h"
#include "chrome/browser/extensions/crx_installer.h"
#include "chrome/browser/extensions/extension_install_prompt.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_system.h"
#include "chrome/browser/extensions/webstore_installer.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/common/chrome_notification_types.h"
#include "chrome/common/extensions/extension_switch_utils.h"
#include "content/public/browser/download_item.h"
#include "content/public/browser/notification_service.h"

using content::BrowserThread;
using content::DownloadItem;
using extensions::WebstoreInstaller;

namespace download_crx_util {

namespace {

// Hold a mock ExtensionInstallPrompt object that will be used when the
// download system opens a CRX.
ExtensionInstallPrompt* mock_install_prompt_for_testing = NULL;

// Called to get an extension install UI object.  In tests, will return
// a mock if the test calls download_util::SetMockInstallUIForTesting()
// to set one.
ExtensionInstallPrompt* CreateExtensionInstallPrompt(Profile* profile) {
  // Use a mock if one is present.  Otherwise, create a real extensions
  // install UI.
  ExtensionInstallPrompt* result = NULL;
  if (mock_install_prompt_for_testing) {
    result = mock_install_prompt_for_testing;
    mock_install_prompt_for_testing = NULL;
  } else {
    Browser* browser = browser::FindLastActiveWithProfile(profile);
    result = chrome::CreateExtensionInstallPromptWithBrowser(browser);
  }

  return result;
}

bool OffStoreInstallAllowedByPrefs(Profile* profile, const DownloadItem& item) {
  extensions::ExtensionPrefs* prefs = extensions::ExtensionSystem::Get(
      profile)->extension_service()->extension_prefs();
  CHECK(prefs);

  URLPatternSet url_patterns = prefs->GetAllowedInstallSites();

  // TODO(aa): RefererURL is cleared in some cases, for example when going
  // between secure and non-secure URLs. It would be better if DownloadItem
  // tracked the initiating page explicitly.
  return url_patterns.MatchesURL(item.GetURL()) &&
      url_patterns.MatchesURL(item.GetReferrerUrl());
}

}  // namespace

// Tests can call this method to inject a mock ExtensionInstallPrompt
// to be used to confirm permissions on a downloaded CRX.
void SetMockInstallPromptForTesting(ExtensionInstallPrompt* mock_prompt) {
  mock_install_prompt_for_testing = mock_prompt;
}

scoped_refptr<extensions::CrxInstaller> OpenChromeExtension(
    Profile* profile,
    const DownloadItem& download_item) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));

  ExtensionService* service = profile->GetExtensionService();
  CHECK(service);

  scoped_refptr<extensions::CrxInstaller> installer(
      extensions::CrxInstaller::Create(
          service,
          CreateExtensionInstallPrompt(profile),
          WebstoreInstaller::GetAssociatedApproval(download_item)));

  installer->set_error_on_unsupported_requirements(true);
  installer->set_delete_source(true);
  installer->set_install_cause(extension_misc::INSTALL_CAUSE_USER_DOWNLOAD);

  if (OffStoreInstallAllowedByPrefs(profile, download_item)) {
    installer->set_off_store_install_allow_reason(
        extensions::CrxInstaller::OffStoreInstallAllowedBecausePref);
  }

  if (extensions::UserScript::IsURLUserScript(download_item.GetURL(),
                                              download_item.GetMimeType())) {
    installer->InstallUserScript(download_item.GetFullPath(),
                                 download_item.GetURL());
  } else {
    bool is_gallery_download =
        WebstoreInstaller::GetAssociatedApproval(download_item) != NULL;
    installer->set_original_mime_type(download_item.GetOriginalMimeType());
    installer->set_apps_require_extension_mime_type(true);
    installer->set_download_url(download_item.GetURL());
    installer->set_is_gallery_install(is_gallery_download);
    if (is_gallery_download)
      installer->set_original_download_url(download_item.GetOriginalUrl());
    installer->set_allow_silent_install(is_gallery_download);
    installer->InstallCrx(download_item.GetFullPath());
  }

  return installer;
}

bool IsExtensionDownload(const DownloadItem& download_item) {
  if (download_item.GetTargetDisposition() ==
      DownloadItem::TARGET_DISPOSITION_PROMPT)
    return false;

  if (download_item.GetMimeType() == extensions::Extension::kMimeType ||
      extensions::UserScript::IsURLUserScript(download_item.GetURL(),
                                              download_item.GetMimeType())) {
    return true;
  } else {
    return false;
  }
}

}  // namespace download_crx_util