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

Side by Side Diff: chrome/browser/apps/drive/drive_app_provider.cc

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

Powered by Google App Engine
This is Rietveld 408576698