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

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: fix debug build 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 // Creates a dummy extension and sets the manifest's name to the item's
35 // localized name.
36 scoped_refptr<Extension> CreateDummyExtension(BundleInstaller::Item item,
37 DictionaryValue* manifest) {
38 // We require localized names so we can have nice error messages when we can't
39 // parse an extension manifest.
40 CHECK(!item.localized_name.empty());
41
42 manifest->SetString(extension_manifest_keys::kName, item.localized_name);
43
44 std::string error;
45 return Extension::Create(FilePath(),
46 Extension::INTERNAL,
47 *manifest,
48 Extension::NO_FLAGS,
49 item.id,
50 &error);
51 }
52
53 } // namespace
54
55 // static
56 void BundleInstaller::SetAutoApproveForTesting(bool auto_approve) {
57 CHECK(CommandLine::ForCurrentProcess()->HasSwitch(switches::kTestType));
58 g_auto_approve_for_test = auto_approve ? PROCEED : ABORT;
59 }
60
61 BundleInstaller::Item::Item() : state(STATE_PENDING) {}
62
63 BundleInstaller::BundleInstaller(Profile* profile,
64 const BundleInstaller::ItemList& items)
65 : approved_(false),
66 browser_(NULL),
67 profile_(profile),
68 delegate_(NULL) {
69 BrowserList::AddObserver(this);
70 for (size_t i = 0; i < items.size(); ++i) {
71 items_[items[i].id] = items[i];
72 items_[items[i].id].state = Item::STATE_PENDING;
73 }
74 }
75
76 BundleInstaller::~BundleInstaller() {
77 BrowserList::RemoveObserver(this);
78 }
79
80 BundleInstaller::ItemList BundleInstaller::GetItemsWithState(
81 Item::State state) const {
82 ItemList list;
83
84 for (ItemMap::const_iterator i = items_.begin(); i != items_.end(); ++i) {
85 if (i->second.state == state)
86 list.push_back(i->second);
87 }
88
89 return list;
90 }
91
92 void BundleInstaller::PromptForApproval(Delegate* delegate) {
93 delegate_ = delegate;
94
95 AddRef(); // Balanced in ReportApproved() and ReportCanceled().
96
97 ParseManifests();
98 }
99
100 void BundleInstaller::CompleteInstall(NavigationController* controller,
101 Browser* browser,
102 Delegate* delegate) {
103 CHECK(approved_);
104
105 browser_ = browser;
106 delegate_ = delegate;
107
108 AddRef(); // Balanced in ReportComplete();
109
110 if (GetItemsWithState(Item::STATE_PENDING).empty()) {
111 ReportComplete();
112 return;
113 }
114
115 // Start each WebstoreInstaller.
116 for (ItemMap::iterator i = items_.begin(); i != items_.end(); ++i) {
117 if (i->second.state != Item::STATE_PENDING)
118 continue;
119
120 scoped_refptr<WebstoreInstaller> installer = new WebstoreInstaller(
121 profile_,
122 this,
123 controller,
124 i->first,
125 WebstoreInstaller::FLAG_NONE);
126 installer->Start();
127 }
128 }
129
130 // static
131 void BundleInstaller::ShowInstalledBubble(
132 const BundleInstaller* bundle, Browser* browser) {
133 // TODO(jstritar): provide platform specific implementations.
134 }
135
136 void BundleInstaller::ParseManifests() {
137 if (items_.empty()) {
138 ReportCanceled(false);
139 return;
140 }
141
142 for (ItemMap::iterator i = items_.begin(); i != items_.end(); ++i) {
143 scoped_refptr<WebstoreInstallHelper> helper = new WebstoreInstallHelper(
144 this, i->first, i->second.manifest, "", GURL(), NULL);
145 helper->Start();
146 }
147 }
148
149 void BundleInstaller::ReportApproved() {
150 if (delegate_)
151 delegate_->OnBundleInstallApproved();
152
153 Release(); // Balanced in PromptForApproval().
154 }
155
156 void BundleInstaller::ReportCanceled(bool user_initiated) {
157 if (delegate_)
158 delegate_->OnBundleInstallCanceled(user_initiated);
159
160 Release(); // Balanced in PromptForApproval().
161 }
162
163 void BundleInstaller::ReportComplete() {
164 if (delegate_)
165 delegate_->OnBundleInstallCompleted();
166
167 Release(); // Balanced in CompleteInstall().
168 }
169
170 void BundleInstaller::ShowPromptIfDoneParsing() {
171 // We don't prompt until all the manifests have been parsed.
172 ItemList pending_items = GetItemsWithState(Item::STATE_PENDING);
173 if (pending_items.size() != dummy_extensions_.size())
174 return;
175
176 ShowPrompt();
177 }
178
179 void BundleInstaller::ShowPrompt() {
180 // Abort if we couldn't create any Extensions out of the manifests.
181 if (dummy_extensions_.empty()) {
182 ReportCanceled(false);
183 return;
184 }
185
186 scoped_refptr<ExtensionPermissionSet> permissions;
187 for (size_t i = 0; i < dummy_extensions_.size(); ++i) {
188 permissions = ExtensionPermissionSet::CreateUnion(
189 permissions, dummy_extensions_[i]->required_permission_set());
190 }
191
192 // TODO(jstritar): show the actual prompt.
193 if (g_auto_approve_for_test == PROCEED)
194 InstallUIProceed();
195 else if (g_auto_approve_for_test == ABORT)
196 InstallUIAbort(true);
197 else
198 InstallUIAbort(false);
199 }
200
201 void BundleInstaller::ShowInstalledBubbleIfDone() {
202 // We're ready to show the installed bubble when no items are pending.
203 if (!GetItemsWithState(Item::STATE_PENDING).empty())
204 return;
205
206 if (browser_)
207 ShowInstalledBubble(this, browser_);
208
209 ReportComplete();
210 }
211
212 void BundleInstaller::OnWebstoreParseSuccess(
213 const std::string& id,
214 const SkBitmap& icon,
215 DictionaryValue* manifest) {
216 dummy_extensions_.push_back(CreateDummyExtension(items_[id], manifest));
217 parsed_manifests_[id] = linked_ptr<DictionaryValue>(manifest);
218
219 ShowPromptIfDoneParsing();
220 }
221
222 void BundleInstaller::OnWebstoreParseFailure(
223 const std::string& id,
224 WebstoreInstallHelper::Delegate::InstallHelperResultCode result_code,
225 const std::string& error_message) {
226 items_[id].state = Item::STATE_FAILED;
227
228 ShowPromptIfDoneParsing();
229 }
230
231 void BundleInstaller::InstallUIProceed() {
232 approved_ = true;
233 for (ItemMap::iterator i = items_.begin(); i != items_.end(); ++i) {
234 if (i->second.state != Item::STATE_PENDING)
235 continue;
236
237 // Create a whitelist entry for each of the approved extensions.
238 CrxInstaller::WhitelistEntry* entry = new CrxInstaller::WhitelistEntry;
239 entry->parsed_manifest.reset(parsed_manifests_[i->first]->DeepCopy());
240 entry->localized_name = i->second.localized_name;
241 entry->use_app_installed_bubble = false;
242 entry->skip_post_install_ui = true;
243 CrxInstaller::SetWhitelistEntry(i->first, entry);
244 }
245 ReportApproved();
246 }
247
248 void BundleInstaller::InstallUIAbort(bool user_initiated) {
249 for (ItemMap::iterator i = items_.begin(); i != items_.end(); ++i)
250 i->second.state = Item::STATE_FAILED;
251
252 ReportCanceled(user_initiated);
253 }
254
255 void BundleInstaller::OnExtensionInstallSuccess(const std::string& id) {
256 items_[id].state = Item::STATE_INSTALLED;
257
258 ShowInstalledBubbleIfDone();
259 }
260
261 void BundleInstaller::OnExtensionInstallFailure(const std::string& id,
262 const std::string& error) {
263 items_[id].state = Item::STATE_FAILED;
264
265 ShowInstalledBubbleIfDone();
266 }
267
268 void BundleInstaller::OnBrowserAdded(const Browser* browser) {
269 }
270
271 void BundleInstaller::OnBrowserRemoved(const Browser* browser) {
272 if (browser_ == browser)
273 browser_ = NULL;
274 }
275
276 void BundleInstaller::OnBrowserSetLastActive(const Browser* browser) {
277 }
278
279 } // namespace extensions
OLDNEW
« no previous file with comments | « chrome/browser/extensions/bundle_installer.h ('k') | chrome/browser/extensions/crx_installer.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698