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

Side by Side Diff: chrome/browser/ui/app_list/drive/drive_app_provider.cc

Issue 308003005: app_list: Drive app integration. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: format Created 6 years, 6 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 2014 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/ui/app_list/drive/drive_app_provider.h"
6
7 #include <vector>
8
9 #include "base/bind.h"
10 #include "base/bind_helpers.h"
11 #include "base/logging.h"
12 #include "base/message_loop/message_loop.h"
13 #include "base/stl_util.h"
14 #include "chrome/browser/drive/drive_app_registry.h"
15 #include "chrome/browser/extensions/extension_service.h"
16 #include "chrome/browser/extensions/install_tracker.h"
17 #include "chrome/browser/extensions/install_tracker_factory.h"
18 #include "chrome/browser/profiles/profile.h"
19 #include "chrome/browser/ui/app_list/drive/drive_app_converter.h"
20 #include "chrome/browser/ui/app_list/drive/drive_app_mapping.h"
21 #include "chrome/browser/ui/app_list/drive/drive_service_bridge.h"
22 #include "chrome/common/extensions/manifest_handlers/app_launch_info.h"
23 #include "extensions/browser/extension_registry.h"
24 #include "extensions/browser/extension_system.h"
25 #include "extensions/common/extension.h"
26 #include "ui/app_list/app_list_item.h"
27 #include "ui/app_list/app_list_model.h"
28
29 namespace {
30
31 void IgnoreUninstallResult(google_apis::GDataErrorCode) {
32 }
33
34 } // namespace
35
36 DriveAppProvider::DriveAppProvider(Profile* profile,
37 app_list::AppListModel* model)
38 : profile_(profile),
39 model_(model),
40 service_bridge_(DriveServiceBridge::Create(profile).Pass()),
41 mapping_(new DriveAppMapping(profile->GetPrefs())),
42 weak_ptr_factory_(this) {
43 service_bridge_->GetAppRegistry()->AddObserver(this);
44 extensions::InstallTracker::Get(profile_)->AddObserver(this);
45 }
46
47 DriveAppProvider::~DriveAppProvider() {
48 extensions::InstallTracker::Get(profile_)->RemoveObserver(this);
49 service_bridge_->GetAppRegistry()->RemoveObserver(this);
50 }
51
52 // static
53 void DriveAppProvider::AppendDependsOnFactories(
54 std::set<BrowserContextKeyedServiceFactory*>* factories) {
55 factories->insert(extensions::InstallTrackerFactory::GetInstance());
56 DriveServiceBridge::AppendDependsOnFactories(factories);
57 }
58
59 void DriveAppProvider::SetDriveServiceBridgeForTest(
60 scoped_ptr<DriveServiceBridge> test_bridge) {
61 service_bridge_->GetAppRegistry()->RemoveObserver(this);
62 service_bridge_ = test_bridge.Pass();
63 service_bridge_->GetAppRegistry()->AddObserver(this);
64 }
65
66 void DriveAppProvider::MigrateModelSettings(
67 const std::string& drive_app_id,
68 const std::string& old_chrome_app_id,
69 const std::string& new_chrome_app_id) {
70 if (!model_ || old_chrome_app_id == new_chrome_app_id)
71 return;
72
73 app_list::AppListItem* old_app_item = model_->FindItem(old_chrome_app_id);
74 if (!old_app_item) {
75 NOTREACHED();
76 return;
77 }
78
79 app_list::AppListItem* new_app_item = model_->FindItem(new_chrome_app_id);
80 if (!new_app_item) {
81 NOTREACHED();
82 return;
83 }
84
85 model_->MoveItemToFolderAt(
86 new_app_item, old_app_item->folder_id(), old_app_item->position());
87 }
88
89 void DriveAppProvider::UpdateMappingAndExtensionSystem(
90 const std::string& drive_app_id,
91 const extensions::Extension* new_app) {
92 const std::string& new_chrome_app_id = new_app->id();
93
94 const std::string existing_chrome_app_id =
95 mapping_->GetChromeApp(drive_app_id);
96 if (existing_chrome_app_id.empty()) {
97 mapping_->Add(drive_app_id, new_chrome_app_id);
98 return;
99 }
100
101 if (existing_chrome_app_id == new_chrome_app_id)
102 return;
103
104 const extensions::Extension* existing_app =
105 extensions::ExtensionRegistry::Get(profile_)->GetExtensionById(
106 existing_chrome_app_id, extensions::ExtensionRegistry::EVERYTHING);
107 if (!existing_app) {
108 mapping_->Add(drive_app_id, new_chrome_app_id);
109 return;
110 }
111
112 if (existing_app->from_bookmark()) {
113 MigrateModelSettings(
114 drive_app_id, existing_chrome_app_id, new_chrome_app_id);
115 mapping_->Add(drive_app_id, new_chrome_app_id);
116 extensions::ExtensionSystem::Get(profile_)
117 ->extension_service()
118 ->UninstallExtension(existing_chrome_app_id, false, NULL);
119 return;
120 }
121
122 if (new_app->from_bookmark()) {
123 // New app is an URL app. Existing app is not URL app. Keep existing.
124 extensions::ExtensionSystem::Get(profile_)
125 ->extension_service()
126 ->UninstallExtension(new_chrome_app_id, false, NULL);
127 } else {
128 // Both existing and new chrome apps are not URL apps, keep existing app
129 // but update mapping to use the new one.
130 mapping_->Add(drive_app_id, new_chrome_app_id);
131 }
132 }
133
134 void DriveAppProvider::ProcessDeferredOnExtensionInstalled(
135 const std::string drive_app_id,
136 const std::string chrome_app_id) {
137 const extensions::Extension* app =
138 extensions::ExtensionRegistry::Get(profile_)->GetExtensionById(
139 chrome_app_id, extensions::ExtensionRegistry::EVERYTHING);
140 if (!app)
141 return;
142
143 UpdateMappingAndExtensionSystem(drive_app_id, app);
144 }
145
146 void DriveAppProvider::SchedulePendingConverters() {
147 if (pending_converters_.empty())
148 return;
149
150 if (!pending_converters_.front()->IsStarted())
151 pending_converters_.front()->Start();
152 }
153
154 void DriveAppProvider::OnLocalAppConverted(const DriveAppConverter* converter,
155 bool success) {
156 DCHECK_EQ(pending_converters_.front(), converter);
157
158 if (success) {
159 UpdateMappingAndExtensionSystem(converter->app_info().app_id,
160 converter->app());
161 } else {
162 LOG(WARNING) << "Failed to convert drive app to web app, "
163 << "drive app id= " << converter->app_info().app_id
164 << ", name=" << converter->app_info().app_name;
165 }
166
167 pending_converters_.erase(pending_converters_.begin());
168 SchedulePendingConverters();
169 }
170
171 bool DriveAppProvider::IsDriveAppUpToDate(
172 const drive::DriveAppInfo& drive_app) const {
173 const std::string& url_app_id = mapping_->GetChromeApp(drive_app.app_id);
174 if (url_app_id.empty())
175 return false;
176
177 const extensions::Extension* url_app =
178 extensions::ExtensionRegistry::Get(profile_)->GetExtensionById(
179 url_app_id, extensions::ExtensionRegistry::EVERYTHING);
180 if (!url_app)
181 return false;
182
183 return drive_app.app_name == url_app->name() &&
184 drive_app.create_url ==
185 extensions::AppLaunchInfo::GetLaunchWebURL(url_app);
186 }
187
188 void DriveAppProvider::AddOrUpdateDriveApp(
189 const drive::DriveAppInfo& drive_app) {
190 const extensions::Extension* chrome_app =
191 extensions::ExtensionRegistry::Get(profile_)->GetExtensionById(
192 drive_app.product_id, extensions::ExtensionRegistry::EVERYTHING);
193 if (chrome_app) {
194 UpdateMappingAndExtensionSystem(drive_app.app_id, chrome_app);
195 return;
196 }
197
198 if (IsDriveAppUpToDate(drive_app))
199 return;
200
201 ScopedVector<DriveAppConverter>::iterator it = pending_converters_.begin();
202 while (it != pending_converters_.end()) {
203 if (!(*it)->IsStarted() && (*it)->app_info().app_id == drive_app.app_id) {
204 it = pending_converters_.erase(it);
205 } else {
206 ++it;
207 }
208 }
209
210 pending_converters_.push_back(
211 new DriveAppConverter(profile_,
212 drive_app,
213 base::Bind(&DriveAppProvider::OnLocalAppConverted,
214 base::Unretained(this))));
215 }
216
217 void DriveAppProvider::RemoveDriveApp(const std::string& drive_app_id) {
218 const std::string chrome_app_id = mapping_->GetChromeApp(drive_app_id);
219 mapping_->Remove(drive_app_id);
220
221 if (chrome_app_id.empty())
222 return;
223
224 const extensions::Extension* existing_app =
225 extensions::ExtensionRegistry::Get(profile_)->GetExtensionById(
226 chrome_app_id, extensions::ExtensionRegistry::EVERYTHING);
227 if (!existing_app || !existing_app->from_bookmark())
228 return;
229
230 extensions::ExtensionSystem::Get(profile_)
231 ->extension_service()
232 ->UninstallExtension(chrome_app_id, false, NULL);
233 }
234
235 void DriveAppProvider::OnDriveAppRegistryUpdated() {
236 service_bridge_->GetAppRegistry()->GetAppList(&drive_apps_);
237
238 IdSet current_ids;
239 for (size_t i = 0; i < drive_apps_.size(); ++i)
240 current_ids.insert(drive_apps_[i].app_id);
241
242 const IdSet existing_ids = mapping_->GetDriveAppIds();
243 const IdSet ids_to_remove =
244 base::STLSetDifference<IdSet>(existing_ids, current_ids);
245 for (IdSet::const_iterator it = ids_to_remove.begin();
246 it != ids_to_remove.end();
247 ++it) {
248 RemoveDriveApp(*it);
249 }
250
251 for (size_t i = 0; i < drive_apps_.size(); ++i) {
252 AddOrUpdateDriveApp(drive_apps_[i]);
253 }
254 SchedulePendingConverters();
255 }
256
257 void DriveAppProvider::OnExtensionInstalled(
258 const extensions::Extension* extension) {
259 for (size_t i = 0; i < drive_apps_.size(); ++i) {
260 if (drive_apps_[i].product_id == extension->id()) {
261 base::MessageLoop::current()->PostTask(
262 FROM_HERE,
263 base::Bind(&DriveAppProvider::ProcessDeferredOnExtensionInstalled,
264 weak_ptr_factory_.GetWeakPtr(),
265 drive_apps_[i].app_id,
266 extension->id()));
267 return;
268 }
269 }
270 }
271
272 void DriveAppProvider::OnExtensionUninstalled(
273 const extensions::Extension* extension) {
274 std::string drive_app_id = mapping_->GetDriveApp(extension->id());
275 if (drive_app_id.empty())
276 return;
277
278 service_bridge_->GetAppRegistry()->UninstallApp(
279 drive_app_id, base::Bind(&IgnoreUninstallResult));
280 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698