OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/extensions/webstore_installer.h" | 5 #include "chrome/browser/extensions/webstore_installer.h" |
6 | 6 |
| 7 #include "base/bind.h" |
| 8 #include "base/command_line.h" |
| 9 #include "base/file_util.h" |
| 10 #include "base/stringprintf.h" |
7 #include "base/string_util.h" | 11 #include "base/string_util.h" |
8 #include "chrome/browser/browser_process.h" | 12 #include "chrome/browser/browser_process.h" |
| 13 #include "chrome/browser/download/download_util.h" |
9 #include "chrome/browser/extensions/crx_installer.h" | 14 #include "chrome/browser/extensions/crx_installer.h" |
10 #include "chrome/browser/profiles/profile.h" | 15 #include "chrome/browser/profiles/profile.h" |
11 #include "chrome/browser/tabs/tab_strip_model.h" | 16 #include "chrome/browser/tabs/tab_strip_model.h" |
12 #include "chrome/browser/ui/browser_list.h" | 17 #include "chrome/browser/ui/browser_list.h" |
13 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" | 18 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" |
14 #include "chrome/common/chrome_notification_types.h" | 19 #include "chrome/common/chrome_notification_types.h" |
| 20 #include "chrome/common/chrome_switches.h" |
15 #include "chrome/common/extensions/extension.h" | 21 #include "chrome/common/extensions/extension.h" |
16 #include "chrome/common/extensions/extension_constants.h" | 22 #include "chrome/common/extensions/extension_constants.h" |
| 23 #include "content/browser/download/download_file.h" |
| 24 #include "content/browser/download/download_manager.h" |
| 25 #include "content/browser/download/download_types.h" |
17 #include "content/browser/tab_contents/navigation_controller.h" | 26 #include "content/browser/tab_contents/navigation_controller.h" |
| 27 #include "content/public/browser/browser_thread.h" |
18 #include "content/public/browser/notification_details.h" | 28 #include "content/public/browser/notification_details.h" |
19 #include "content/public/browser/notification_source.h" | 29 #include "content/public/browser/notification_source.h" |
20 #include "googleurl/src/gurl.h" | 30 #include "googleurl/src/gurl.h" |
21 #include "net/base/escape.h" | 31 #include "net/base/escape.h" |
22 | 32 |
23 namespace { | 33 namespace { |
24 | 34 |
25 const char kInvalidIdError[] = "Invalid id"; | 35 const char kInvalidIdError[] = "Invalid id"; |
26 const char kNoBrowserError[] = "No browser found"; | 36 const char kNoBrowserError[] = "No browser found"; |
27 | 37 |
28 const char kInlineInstallSource[] = "inline"; | 38 const char kInlineInstallSource[] = "inline"; |
29 const char kDefaultInstallSource[] = ""; | 39 const char kDefaultInstallSource[] = ""; |
30 | 40 |
31 GURL GetWebstoreInstallURL( | 41 GURL GetWebstoreInstallURL( |
32 const std::string& extension_id, const std::string& install_source) { | 42 const std::string& extension_id, const std::string& install_source) { |
| 43 CommandLine* cmd_line = CommandLine::ForCurrentProcess(); |
| 44 if (cmd_line->HasSwitch(switches::kAppsGalleryDownloadURL)) { |
| 45 std::string download_url = |
| 46 cmd_line->GetSwitchValueASCII(switches::kAppsGalleryDownloadURL); |
| 47 return GURL(base::StringPrintf(download_url.c_str(), |
| 48 extension_id.c_str())); |
| 49 } |
33 std::vector<std::string> params; | 50 std::vector<std::string> params; |
34 params.push_back("id=" + extension_id); | 51 params.push_back("id=" + extension_id); |
35 if (!install_source.empty()) { | 52 if (!install_source.empty()) { |
36 params.push_back("installsource=" + install_source); | 53 params.push_back("installsource=" + install_source); |
37 } | 54 } |
38 params.push_back("lang=" + g_browser_process->GetApplicationLocale()); | 55 params.push_back("lang=" + g_browser_process->GetApplicationLocale()); |
39 params.push_back("uc"); | 56 params.push_back("uc"); |
40 std::string url_string = extension_urls::GetWebstoreUpdateUrl(true).spec(); | 57 std::string url_string = extension_urls::GetWebstoreUpdateUrl(true).spec(); |
41 | 58 |
42 GURL url(url_string + "?response=redirect&x=" + | 59 GURL url(url_string + "?response=redirect&x=" + |
43 net::EscapeQueryParamValue(JoinString(params, '&'), true)); | 60 net::EscapeQueryParamValue(JoinString(params, '&'), true)); |
44 DCHECK(url.is_valid()); | 61 DCHECK(url.is_valid()); |
45 | 62 |
46 return url; | 63 return url; |
47 } | 64 } |
48 | 65 |
| 66 // Must be executed on the FILE thread. |
| 67 void GetDownloadFilePath(const std::string& id, |
| 68 const base::Callback<void(FilePath)>& callback) { |
| 69 FilePath file = |
| 70 download_util::GetDefaultDownloadDirectory().AppendASCII(id + ".crx"); |
| 71 |
| 72 int uniquifier = DownloadFile::GetUniquePathNumber(file); |
| 73 if (uniquifier > 0) |
| 74 DownloadFile::AppendNumberToPath(&file, uniquifier); |
| 75 |
| 76 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
| 77 base::Bind(callback, file)); |
| 78 } |
| 79 |
49 } // namespace | 80 } // namespace |
50 | 81 |
51 | 82 |
52 WebstoreInstaller::WebstoreInstaller(Profile* profile, | 83 WebstoreInstaller::WebstoreInstaller(Profile* profile, |
53 Delegate* delegate, | 84 Delegate* delegate, |
54 NavigationController* controller, | 85 NavigationController* controller, |
55 const std::string& id, | 86 const std::string& id, |
56 int flags) | 87 int flags) |
57 : profile_(profile), | 88 : profile_(profile), |
58 delegate_(delegate), | 89 delegate_(delegate), |
59 controller_(controller), | 90 controller_(controller), |
60 id_(id), | 91 id_(id), |
61 flags_(flags) { | 92 flags_(flags) { |
62 download_url_ = GetWebstoreInstallURL(id, flags & FLAG_INLINE_INSTALL ? | 93 download_url_ = GetWebstoreInstallURL(id, flags & FLAG_INLINE_INSTALL ? |
63 kInlineInstallSource : kDefaultInstallSource); | 94 kInlineInstallSource : kDefaultInstallSource); |
64 | 95 |
65 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_INSTALLED, | 96 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_INSTALLED, |
66 content::Source<Profile>(profile)); | 97 content::Source<Profile>(profile)); |
67 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_INSTALL_ERROR, | 98 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_INSTALL_ERROR, |
68 content::Source<CrxInstaller>(NULL)); | 99 content::Source<CrxInstaller>(NULL)); |
69 } | 100 } |
70 | 101 |
71 WebstoreInstaller::~WebstoreInstaller() {} | 102 WebstoreInstaller::~WebstoreInstaller() {} |
72 | 103 |
73 void WebstoreInstaller::Start() { | 104 void WebstoreInstaller::Start() { |
| 105 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
74 AddRef(); // Balanced in ReportSuccess and ReportFailure. | 106 AddRef(); // Balanced in ReportSuccess and ReportFailure. |
75 | 107 |
76 if (!Extension::IdIsValid(id_)) { | 108 if (!Extension::IdIsValid(id_)) { |
77 ReportFailure(kInvalidIdError); | 109 ReportFailure(kInvalidIdError); |
78 return; | 110 return; |
79 } | 111 } |
80 | 112 |
81 // TODO(mihaip): For inline installs, we pretend like the referrer is the | 113 BrowserThread::PostTask( |
82 // gallery, even though this could be an inline install, in order to pass the | 114 BrowserThread::FILE, FROM_HERE, |
83 // checks in ExtensionService::IsDownloadFromGallery. We should instead pass | 115 base::Bind(&GetDownloadFilePath, id_, |
84 // the real referrer, track if this is an inline install in the whitelist | 116 base::Bind(&WebstoreInstaller::StartDownload, |
85 // entry and look that up when checking that this is a valid download. | 117 base::Unretained(this)))); |
86 GURL referrer = controller_->GetActiveEntry()->url(); | |
87 if (flags_ & FLAG_INLINE_INSTALL) | |
88 referrer = GURL(extension_urls::GetWebstoreItemDetailURLPrefix() + id_); | |
89 | |
90 // 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()); | |
97 | 118 |
98 } | 119 } |
99 | 120 |
100 void WebstoreInstaller::Observe(int type, | 121 void WebstoreInstaller::Observe(int type, |
101 const content::NotificationSource& source, | 122 const content::NotificationSource& source, |
102 const content::NotificationDetails& details) { | 123 const content::NotificationDetails& details) { |
103 switch (type) { | 124 switch (type) { |
104 case chrome::NOTIFICATION_EXTENSION_INSTALLED: { | 125 case chrome::NOTIFICATION_EXTENSION_INSTALLED: { |
105 CHECK(profile_->IsSameProfile(content::Source<Profile>(source).ptr())); | 126 CHECK(profile_->IsSameProfile(content::Source<Profile>(source).ptr())); |
106 const Extension* extension = | 127 const Extension* extension = |
(...skipping 14 matching lines...) Expand all Loading... |
121 if (download_url_ == crx_installer->original_download_url()) | 142 if (download_url_ == crx_installer->original_download_url()) |
122 ReportFailure(*error); | 143 ReportFailure(*error); |
123 break; | 144 break; |
124 } | 145 } |
125 | 146 |
126 default: | 147 default: |
127 NOTREACHED(); | 148 NOTREACHED(); |
128 } | 149 } |
129 } | 150 } |
130 | 151 |
| 152 void WebstoreInstaller::StartDownload(FilePath file) { |
| 153 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 154 |
| 155 // TODO(mihaip): For inline installs, we pretend like the referrer is the |
| 156 // gallery, even though this could be an inline install, in order to pass the |
| 157 // checks in ExtensionService::IsDownloadFromGallery. We should instead pass |
| 158 // the real referrer, track if this is an inline install in the whitelist |
| 159 // entry and look that up when checking that this is a valid download. |
| 160 GURL referrer = controller_->GetActiveEntry()->url(); |
| 161 if (flags_ & FLAG_INLINE_INSTALL) |
| 162 referrer = GURL(extension_urls::GetWebstoreItemDetailURLPrefix() + id_); |
| 163 |
| 164 DownloadSaveInfo save_info; |
| 165 save_info.file_path = file; |
| 166 |
| 167 // The download url for the given extension is contained in |download_url_|. |
| 168 // We will navigate the current tab to this url to start the download. The |
| 169 // download system will then pass the crx to the CrxInstaller. |
| 170 profile_->GetDownloadManager()->DownloadUrlToFile( |
| 171 download_url_, referrer, "", save_info, controller_->tab_contents()); |
| 172 } |
| 173 |
131 void WebstoreInstaller::ReportFailure(const std::string& error) { | 174 void WebstoreInstaller::ReportFailure(const std::string& error) { |
132 if (delegate_) | 175 if (delegate_) |
133 delegate_->OnExtensionInstallFailure(id_, error); | 176 delegate_->OnExtensionInstallFailure(id_, error); |
134 | 177 |
135 Release(); // Balanced in Start(). | 178 Release(); // Balanced in Start(). |
136 } | 179 } |
137 | 180 |
138 void WebstoreInstaller::ReportSuccess() { | 181 void WebstoreInstaller::ReportSuccess() { |
139 if (delegate_) | 182 if (delegate_) |
140 delegate_->OnExtensionInstallSuccess(id_); | 183 delegate_->OnExtensionInstallSuccess(id_); |
141 | 184 |
142 Release(); // Balanced in Start(). | 185 Release(); // Balanced in Start(). |
143 } | 186 } |
OLD | NEW |