Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(55)

Side by Side Diff: chrome/browser/extensions/bundle_installer.cc

Issue 9414013: Add a webstore API for installing bundles of extensions. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: . Created 8 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2012 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/bundle_installer.h"
6
7 #include <string>
8 #include <vector>
9
10 #include "base/command_line.h"
11 #include "base/values.h"
12 #include "chrome/browser/extensions/crx_installer.h"
13 #include "chrome/browser/profiles/profile.h"
14 #include "chrome/browser/ui/browser.h"
15 #include "chrome/common/chrome_switches.h"
16 #include "content/public/browser/browser_thread.h"
17 #include "content/public/browser/navigation_controller.h"
18 #include "content/public/browser/web_contents.h"
19
20 using content::NavigationController;
21
22 namespace extensions {
23
24 namespace {
25
26 enum AutoApproveForTest {
27 DO_NOT_SKIP = 0,
28 PROCEED,
29 ABORT
30 };
31
32 AutoApproveForTest g_auto_approve_for_test = DO_NOT_SKIP;
33
34 } // namespace
35
36 // static
37 void BundleInstaller::SetAutoApproveForTesting(bool auto_approve) {
38 CHECK(CommandLine::ForCurrentProcess()->HasSwitch(switches::kTestType));
39 g_auto_approve_for_test = auto_approve ? PROCEED : ABORT;
40 }
41
42 BundleInstaller::Item::Item() : state(STATE_PENDING) {}
43
44 scoped_refptr<Extension> BundleInstaller::Item::CreateDummyExtension(
45 DictionaryValue* manifest) {
Yoyo Zhou 2012/02/22 00:20:26 It's slightly confusing that this argument has the
jstritar 2012/02/22 15:45:48 Done.
46 // We require localized names so we can have nice error messages when we can't
47 // parse an extension manifest.
48 CHECK(!localized_name.empty());
49
50 manifest->SetString(extension_manifest_keys::kName, localized_name);
51
52 std::string error;
53 return Extension::Create(FilePath(),
54 Extension::INTERNAL,
55 *manifest,
56 Extension::NO_FLAGS,
57 id,
58 &error);
59 }
60
61 BundleInstaller::BundleInstaller(Profile* profile,
62 const BundleInstaller::ItemList& items)
63 : approved_(false),
64 browser_(NULL),
65 profile_(profile),
66 delegate_(NULL) {
67 BrowserList::AddObserver(this);
68 for (size_t i = 0; i < items.size(); ++i) {
69 items_[items[i].id] = items[i];
70 items_[items[i].id].state = Item::STATE_PENDING;
71 }
72 }
73
74 BundleInstaller::~BundleInstaller() {
75 BrowserList::RemoveObserver(this);
76 }
77
78 BundleInstaller::ItemList BundleInstaller::GetItemsByState(
79 Item::State state) const {
80 ItemList list;
81
82 for (ItemMap::const_iterator i = items_.begin(); i != items_.end(); ++i) {
83 if (i->second.state == state)
84 list.push_back(i->second);
85 }
86
87 return list;
88 }
89
90 void BundleInstaller::PromptForApproval(Delegate* delegate) {
91 delegate_ = delegate;
92
93 AddRef(); // Balanced in ReportApproved() and ReportCanceled().
94
95 ParseManifests();
96 }
97
98 void BundleInstaller::CompleteInstall(NavigationController* controller,
99 Browser* browser,
100 Delegate* delegate) {
101 browser_ = browser;
102 delegate_ = delegate;
Yoyo Zhou 2012/02/22 00:20:26 Is this delegate argument necessary? It looks like
jstritar 2012/02/22 15:45:48 Yeah, PromptForApproval and CompleteInstall will b
103
104 AddRef(); // Balanced in ReportComplete();
105
106 if (!approved_ || GetItemsByState(Item::STATE_PENDING).empty()) {
Yoyo Zhou 2012/02/22 00:20:26 How do we get here if !approved_; could that be a
jstritar 2012/02/22 15:45:48 Good point -- even if these methods are called by
107 ReportComplete();
108 return;
109 }
110
111 // Start each WebstoreInstaller.
112 for (ItemMap::iterator i = items_.begin(); i != items_.end(); ++i) {
113 if (i->second.state != Item::STATE_PENDING)
114 continue;
115
116 scoped_refptr<WebstoreInstaller> installer = new WebstoreInstaller(
117 profile_,
118 this,
119 controller,
120 i->first,
121 WebstoreInstaller::FLAG_NONE);
122 installer->Start();
123 }
124 }
125
126 // static
127 void BundleInstaller::ShowInstalledBubble(
128 const BundleInstaller* bundle, Browser* browser) {
129 // TODO(jstritar): provide platform specific implementations.
130 }
131
132 void BundleInstaller::ParseManifests() {
133 if (items_.empty()) {
134 ReportCanceled(false);
135 return;
136 }
137
138 for (ItemMap::iterator i = items_.begin(); i != items_.end(); ++i) {
139 scoped_refptr<WebstoreInstallHelper> helper = new WebstoreInstallHelper(
140 this, i->first, i->second.manifest, "", GURL(), NULL);
141 helper->Start();
142 }
143 }
144
145 void BundleInstaller::ReportApproved() {
146 if (delegate_)
147 delegate_->OnBundleInstallApproved();
148
149 Release(); // Balanced in ParseManifests().
Yoyo Zhou 2012/02/22 00:20:26 in PromptForApproval
jstritar 2012/02/22 15:45:48 Done.
150 }
151
152 void BundleInstaller::ReportCanceled(bool user_initiated) {
153 if (delegate_)
154 delegate_->OnBundleInstallCanceled(user_initiated);
155
156 Release(); // Balanced in ParseManifests().
Yoyo Zhou 2012/02/22 00:20:26 ditto
jstritar 2012/02/22 15:45:48 Done.
157 }
158
159 void BundleInstaller::ReportComplete() {
160 if (delegate_)
161 delegate_->OnBundleInstallCompleted();
162
163 Release(); // Balanced in CompleteInstall().
164 }
165
166 void BundleInstaller::ShowPromptIfDoneParsing() {
167 // We don't prompt until all the manifests have been parsed.
168 if (GetItemsByState(Item::STATE_PENDING).size() != dummy_extensions_.size())
169 return;
170
171 ShowPrompt();
172 }
173
174 void BundleInstaller::ShowPrompt() {
175 // Abort if we couldn't create any Extensions out of the manifests.
176 if (dummy_extensions_.empty()) {
177 ReportCanceled(false);
178 return;
179 }
180
181 scoped_refptr<ExtensionPermissionSet> permissions;
182 for (size_t i = 0; i < dummy_extensions_.size(); ++i) {
183 permissions = ExtensionPermissionSet::CreateUnion(
184 permissions, dummy_extensions_[i]->required_permission_set());
185 }
186
187 // TODO(jstritar): show the actual prompt.
188 if (g_auto_approve_for_test == PROCEED)
189 InstallUIProceed();
190 else if (g_auto_approve_for_test == ABORT)
191 InstallUIAbort(true);
192 else
193 InstallUIAbort(false);
194 }
195
196 void BundleInstaller::ShowInstalledBubbleIfDone() {
197 // We're ready to show the installed bubble when no items are pending.
198 if (!GetItemsByState(Item::STATE_PENDING).empty())
199 return;
200
201 if (browser_)
202 ShowInstalledBubble(this, browser_);
203
204 ReportComplete();
205 }
206
207 void BundleInstaller::OnWebstoreParseSuccess(
208 const std::string& id,
209 const SkBitmap& icon,
210 DictionaryValue* manifest) {
211 dummy_extensions_.push_back(items_[id].CreateDummyExtension(manifest));
212 parsed_manifests_[id] = linked_ptr<DictionaryValue>(manifest);
213
214 ShowPromptIfDoneParsing();
215 }
216
217 void BundleInstaller::OnWebstoreParseFailure(
218 const std::string& id,
219 WebstoreInstallHelper::Delegate::InstallHelperResultCode result_code,
220 const std::string& error_message) {
221 items_[id].state = Item::STATE_FAILED;
222
223 ShowPromptIfDoneParsing();
224 }
225
226 void BundleInstaller::InstallUIProceed() {
227 approved_ = true;
228 for (ItemMap::iterator i = items_.begin(); i != items_.end(); ++i) {
229 if (i->second.state != Item::STATE_PENDING)
230 continue;
231
232 // Create a whitelist entry for each of the approved extensions.
233 CrxInstaller::WhitelistEntry* entry = new CrxInstaller::WhitelistEntry;
234 entry->parsed_manifest.reset(parsed_manifests_[i->first]->DeepCopy());
235 entry->localized_name = i->second.localized_name;
236 entry->use_app_installed_bubble = false;
237 entry->skip_post_install_ui = true;
238 CrxInstaller::SetWhitelistEntry(i->first, entry);
239 }
240 ReportApproved();
241 }
242
243 void BundleInstaller::InstallUIAbort(bool user_initiated) {
244 for (ItemMap::iterator i = items_.begin(); i != items_.end(); ++i)
245 i->second.state = Item::STATE_FAILED;
246
247 ReportCanceled(user_initiated);
248 }
249
250 void BundleInstaller::OnExtensionInstallSuccess(const std::string& id) {
251 items_[id].state = Item::STATE_INSTALLED;
252
253 ShowInstalledBubbleIfDone();
254 }
255
256 void BundleInstaller::OnExtensionInstallFailure(const std::string& id,
257 const std::string& error) {
258 items_[id].state = Item::STATE_FAILED;
259
260 ShowInstalledBubbleIfDone();
261 }
262
263 void BundleInstaller::OnBrowserAdded(const Browser* browser) {
264 }
265
266 void BundleInstaller::OnBrowserRemoved(const Browser* browser) {
267 if (browser_ == browser)
268 browser_ = NULL;
269 }
270
271 void BundleInstaller::OnBrowserSetLastActive(const Browser* browser) {
272 }
273
274 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698