blob: a32f4c29c76363eb3280dc3b3b63336a5a4261f5 [file] [log] [blame]
[email protected]655b2b1a2011-10-13 17:13:061// Copyright (c) 2011 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 "chrome/browser/extensions/webstore_installer.h"
6
[email protected]99dfecd2011-10-18 01:11:507#include "base/string_util.h"
[email protected]655b2b1a2011-10-13 17:13:068#include "chrome/browser/browser_process.h"
9#include "chrome/browser/extensions/crx_installer.h"
10#include "chrome/browser/profiles/profile.h"
11#include "chrome/browser/tabs/tab_strip_model.h"
12#include "chrome/browser/ui/browser_list.h"
13#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
14#include "chrome/common/chrome_notification_types.h"
15#include "chrome/common/extensions/extension.h"
[email protected]99dfecd2011-10-18 01:11:5016#include "chrome/common/extensions/extension_constants.h"
[email protected]655b2b1a2011-10-13 17:13:0617#include "content/browser/tab_contents/navigation_controller.h"
[email protected]86ab86b2011-10-19 03:07:5518#include "content/public/browser/notification_details.h"
19#include "content/public/browser/notification_source.h"
[email protected]655b2b1a2011-10-13 17:13:0620#include "googleurl/src/gurl.h"
[email protected]99dfecd2011-10-18 01:11:5021#include "net/base/escape.h"
[email protected]655b2b1a2011-10-13 17:13:0622
23namespace {
24
25const char kInvalidIdError[] = "Invalid id";
26const char kNoBrowserError[] = "No browser found";
27
[email protected]99dfecd2011-10-18 01:11:5028const char kInlineInstallSource[] = "inline";
29const char kDefaultInstallSource[] = "";
30
[email protected]e577c592011-10-25 22:53:3031GURL GetWebstoreInstallURL(
[email protected]99dfecd2011-10-18 01:11:5032 const std::string& extension_id, const std::string& install_source) {
33 std::vector<std::string> params;
34 params.push_back("id=" + extension_id);
35 if (!install_source.empty()) {
36 params.push_back("installsource=" + install_source);
37 }
38 params.push_back("lang=" + g_browser_process->GetApplicationLocale());
39 params.push_back("uc");
40 std::string url_string = extension_urls::GetWebstoreUpdateUrl(true).spec();
41
42 GURL url(url_string + "?response=redirect&x=" +
43 net::EscapeQueryParamValue(JoinString(params, '&'), true));
44 DCHECK(url.is_valid());
45
46 return url;
47}
48
[email protected]655b2b1a2011-10-13 17:13:0649} // namespace
50
51
[email protected]98e4e522011-10-25 13:00:1652WebstoreInstaller::WebstoreInstaller(Profile* profile,
53 Delegate* delegate,
54 NavigationController* controller,
55 const std::string& id,
56 int flags)
57 : profile_(profile),
58 delegate_(delegate),
59 controller_(controller),
60 id_(id),
61 flags_(flags) {
[email protected]e577c592011-10-25 22:53:3062 download_url_ = GetWebstoreInstallURL(id, flags & FLAG_INLINE_INSTALL ?
[email protected]98e4e522011-10-25 13:00:1663 kInlineInstallSource : kDefaultInstallSource);
64
[email protected]655b2b1a2011-10-13 17:13:0665 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_INSTALLED,
[email protected]86ab86b2011-10-19 03:07:5566 content::Source<Profile>(profile));
[email protected]655b2b1a2011-10-13 17:13:0667 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_INSTALL_ERROR,
[email protected]86ab86b2011-10-19 03:07:5568 content::Source<CrxInstaller>(NULL));
[email protected]655b2b1a2011-10-13 17:13:0669}
70
71WebstoreInstaller::~WebstoreInstaller() {}
72
[email protected]98e4e522011-10-25 13:00:1673void WebstoreInstaller::Start() {
74 AddRef(); // Balanced in ReportSuccess and ReportFailure.
[email protected]655b2b1a2011-10-13 17:13:0675
[email protected]98e4e522011-10-25 13:00:1676 if (!Extension::IdIsValid(id_)) {
77 ReportFailure(kInvalidIdError);
[email protected]655b2b1a2011-10-13 17:13:0678 return;
79 }
80
[email protected]98e4e522011-10-25 13:00:1681 // TODO(mihaip): For inline installs, we pretend like the referrer is the
82 // gallery, even though this could be an inline install, in order to pass the
83 // checks in ExtensionService::IsDownloadFromGallery. We should instead pass
84 // the real referrer, track if this is an inline install in the whitelist
85 // entry and look that up when checking that this is a valid download.
86 GURL referrer = controller_->GetActiveEntry()->url();
87 if (flags_ & FLAG_INLINE_INSTALL)
88 referrer = GURL(extension_urls::GetWebstoreItemDetailURLPrefix() + id_);
[email protected]655b2b1a2011-10-13 17:13:0689
[email protected]98e4e522011-10-25 13:00:1690 // The download url for the given extension is contained in |download_url_|.
91 // We will navigate the current tab to this url to start the download. The
92 // download system will then pass the crx to the CrxInstaller.
93 controller_->LoadURL(download_url_,
94 referrer,
95 content::PAGE_TRANSITION_LINK,
96 std::string());
[email protected]655b2b1a2011-10-13 17:13:0697
[email protected]655b2b1a2011-10-13 17:13:0698}
99
100void WebstoreInstaller::Observe(int type,
[email protected]86ab86b2011-10-19 03:07:55101 const content::NotificationSource& source,
102 const content::NotificationDetails& details) {
[email protected]655b2b1a2011-10-13 17:13:06103 switch (type) {
104 case chrome::NOTIFICATION_EXTENSION_INSTALLED: {
[email protected]86ab86b2011-10-19 03:07:55105 CHECK(profile_->IsSameProfile(content::Source<Profile>(source).ptr()));
106 const Extension* extension =
107 content::Details<const Extension>(details).ptr();
[email protected]98e4e522011-10-25 13:00:16108 if (id_ == extension->id())
109 ReportSuccess();
[email protected]655b2b1a2011-10-13 17:13:06110 break;
111 }
112
113 case chrome::NOTIFICATION_EXTENSION_INSTALL_ERROR: {
[email protected]86ab86b2011-10-19 03:07:55114 CrxInstaller* crx_installer = content::Source<CrxInstaller>(source).ptr();
[email protected]655b2b1a2011-10-13 17:13:06115 CHECK(crx_installer);
116 if (!profile_->IsSameProfile(crx_installer->profile()))
117 return;
118
[email protected]86ab86b2011-10-19 03:07:55119 const std::string* error =
120 content::Details<const std::string>(details).ptr();
[email protected]98e4e522011-10-25 13:00:16121 if (download_url_ == crx_installer->original_download_url())
122 ReportFailure(*error);
[email protected]655b2b1a2011-10-13 17:13:06123 break;
124 }
125
126 default:
127 NOTREACHED();
128 }
129}
130
[email protected]98e4e522011-10-25 13:00:16131void WebstoreInstaller::ReportFailure(const std::string& error) {
132 if (delegate_)
133 delegate_->OnExtensionInstallFailure(id_, error);
134
135 Release(); // Balanced in Start().
[email protected]655b2b1a2011-10-13 17:13:06136}
137
[email protected]98e4e522011-10-25 13:00:16138void WebstoreInstaller::ReportSuccess() {
139 if (delegate_)
140 delegate_->OnExtensionInstallSuccess(id_);
[email protected]655b2b1a2011-10-13 17:13:06141
[email protected]98e4e522011-10-25 13:00:16142 Release(); // Balanced in Start().
[email protected]655b2b1a2011-10-13 17:13:06143}