OLD | NEW |
---|---|
(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 | |
OLD | NEW |