1 // Copyright 2018 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 "components/services/app_service/public/cpp/app_update.h"
6
7 #include "base/logging.h"
8 #include "base/strings/string_util.h"
9 #include "base/time/time.h"
10
11 namespace {
12
ClonePermissions(const std::vector<apps::mojom::PermissionPtr> & clone_from,std::vector<apps::mojom::PermissionPtr> * clone_to)13 void ClonePermissions(const std::vector<apps::mojom::PermissionPtr>& clone_from,
14 std::vector<apps::mojom::PermissionPtr>* clone_to) {
15 for (const auto& permission : clone_from) {
16 clone_to->push_back(permission->Clone());
17 }
18 }
19
CloneStrings(const std::vector<std::string> & clone_from,std::vector<std::string> * clone_to)20 void CloneStrings(const std::vector<std::string>& clone_from,
21 std::vector<std::string>* clone_to) {
22 for (const auto& s : clone_from) {
23 clone_to->push_back(s);
24 }
25 }
26
CloneIntentFilters(const std::vector<apps::mojom::IntentFilterPtr> & clone_from,std::vector<apps::mojom::IntentFilterPtr> * clone_to)27 void CloneIntentFilters(
28 const std::vector<apps::mojom::IntentFilterPtr>& clone_from,
29 std::vector<apps::mojom::IntentFilterPtr>* clone_to) {
30 for (const auto& intent_filter : clone_from) {
31 clone_to->push_back(intent_filter->Clone());
32 }
33 }
34
35 } // namespace
36
37 namespace apps {
38
39 // static
Merge(apps::mojom::App * state,const apps::mojom::App * delta)40 void AppUpdate::Merge(apps::mojom::App* state, const apps::mojom::App* delta) {
41 DCHECK(state);
42 if (!delta) {
43 return;
44 }
45
46 if ((delta->app_type != state->app_type) ||
47 (delta->app_id != state->app_id)) {
48 LOG(ERROR) << "inconsistent (app_type, app_id): (" << delta->app_type
49 << ", " << delta->app_id << ") vs (" << state->app_type << ", "
50 << state->app_id << ") ";
51 DCHECK(false);
52 return;
53 }
54
55 if (delta->readiness != apps::mojom::Readiness::kUnknown) {
56 state->readiness = delta->readiness;
57 }
58 if (delta->name.has_value()) {
59 state->name = delta->name;
60 }
61 if (delta->short_name.has_value()) {
62 state->short_name = delta->short_name;
63 }
64 if (delta->publisher_id.has_value()) {
65 state->publisher_id = delta->publisher_id;
66 }
67 if (delta->description.has_value()) {
68 state->description = delta->description;
69 }
70 if (delta->version.has_value()) {
71 state->version = delta->version;
72 }
73 if (!delta->additional_search_terms.empty()) {
74 state->additional_search_terms.clear();
75 CloneStrings(delta->additional_search_terms,
76 &state->additional_search_terms);
77 }
78 if (!delta->icon_key.is_null()) {
79 state->icon_key = delta->icon_key.Clone();
80 }
81 if (delta->last_launch_time.has_value()) {
82 state->last_launch_time = delta->last_launch_time;
83 }
84 if (delta->install_time.has_value()) {
85 state->install_time = delta->install_time;
86 }
87 if (!delta->permissions.empty()) {
88 DCHECK(state->permissions.empty() ||
89 (delta->permissions.size() == state->permissions.size()));
90 state->permissions.clear();
91 ClonePermissions(delta->permissions, &state->permissions);
92 }
93 if (delta->install_source != apps::mojom::InstallSource::kUnknown) {
94 state->install_source = delta->install_source;
95 }
96 if (delta->is_platform_app != apps::mojom::OptionalBool::kUnknown) {
97 state->is_platform_app = delta->is_platform_app;
98 }
99 if (delta->recommendable != apps::mojom::OptionalBool::kUnknown) {
100 state->recommendable = delta->recommendable;
101 }
102 if (delta->searchable != apps::mojom::OptionalBool::kUnknown) {
103 state->searchable = delta->searchable;
104 }
105 if (delta->show_in_launcher != apps::mojom::OptionalBool::kUnknown) {
106 state->show_in_launcher = delta->show_in_launcher;
107 }
108 if (delta->show_in_shelf != apps::mojom::OptionalBool::kUnknown) {
109 state->show_in_shelf = delta->show_in_shelf;
110 }
111 if (delta->show_in_search != apps::mojom::OptionalBool::kUnknown) {
112 state->show_in_search = delta->show_in_search;
113 }
114 if (delta->show_in_management != apps::mojom::OptionalBool::kUnknown) {
115 state->show_in_management = delta->show_in_management;
116 }
117 if (delta->has_badge != apps::mojom::OptionalBool::kUnknown) {
118 state->has_badge = delta->has_badge;
119 }
120 if (delta->paused != apps::mojom::OptionalBool::kUnknown) {
121 state->paused = delta->paused;
122 }
123
124 if (!delta->intent_filters.empty()) {
125 state->intent_filters.clear();
126 CloneIntentFilters(delta->intent_filters, &state->intent_filters);
127 }
128
129 // When adding new fields to the App Mojo type, this function should also be
130 // updated.
131 }
132
AppUpdate(const apps::mojom::App * state,const apps::mojom::App * delta,const::AccountId & account_id)133 AppUpdate::AppUpdate(const apps::mojom::App* state,
134 const apps::mojom::App* delta,
135 const ::AccountId& account_id)
136 : state_(state), delta_(delta), account_id_(account_id) {
137 DCHECK(state_ || delta_);
138 if (state_ && delta_) {
139 DCHECK(state_->app_type == delta->app_type);
140 DCHECK(state_->app_id == delta->app_id);
141 }
142 }
143
StateIsNull() const144 bool AppUpdate::StateIsNull() const {
145 return state_ == nullptr;
146 }
147
AppType() const148 apps::mojom::AppType AppUpdate::AppType() const {
149 return delta_ ? delta_->app_type : state_->app_type;
150 }
151
AppId() const152 const std::string& AppUpdate::AppId() const {
153 return delta_ ? delta_->app_id : state_->app_id;
154 }
155
Readiness() const156 apps::mojom::Readiness AppUpdate::Readiness() const {
157 if (delta_ && (delta_->readiness != apps::mojom::Readiness::kUnknown)) {
158 return delta_->readiness;
159 }
160 if (state_) {
161 return state_->readiness;
162 }
163 return apps::mojom::Readiness::kUnknown;
164 }
165
ReadinessChanged() const166 bool AppUpdate::ReadinessChanged() const {
167 return delta_ && (delta_->readiness != apps::mojom::Readiness::kUnknown) &&
168 (!state_ || (delta_->readiness != state_->readiness));
169 }
170
Name() const171 const std::string& AppUpdate::Name() const {
172 if (delta_ && delta_->name.has_value()) {
173 return delta_->name.value();
174 }
175 if (state_ && state_->name.has_value()) {
176 return state_->name.value();
177 }
178 return base::EmptyString();
179 }
180
NameChanged() const181 bool AppUpdate::NameChanged() const {
182 return delta_ && delta_->name.has_value() &&
183 (!state_ || (delta_->name != state_->name));
184 }
185
ShortName() const186 const std::string& AppUpdate::ShortName() const {
187 if (delta_ && delta_->short_name.has_value()) {
188 return delta_->short_name.value();
189 }
190 if (state_ && state_->short_name.has_value()) {
191 return state_->short_name.value();
192 }
193 return base::EmptyString();
194 }
195
ShortNameChanged() const196 bool AppUpdate::ShortNameChanged() const {
197 return delta_ && delta_->short_name.has_value() &&
198 (!state_ || (delta_->short_name != state_->short_name));
199 }
200
PublisherId() const201 const std::string& AppUpdate::PublisherId() const {
202 if (delta_ && delta_->publisher_id.has_value()) {
203 return delta_->publisher_id.value();
204 }
205 if (state_ && state_->publisher_id.has_value()) {
206 return state_->publisher_id.value();
207 }
208 return base::EmptyString();
209 }
210
PublisherIdChanged() const211 bool AppUpdate::PublisherIdChanged() const {
212 return delta_ && delta_->publisher_id.has_value() &&
213 (!state_ || (delta_->publisher_id != state_->publisher_id));
214 }
215
Description() const216 const std::string& AppUpdate::Description() const {
217 if (delta_ && delta_->description.has_value()) {
218 return delta_->description.value();
219 }
220 if (state_ && state_->description.has_value()) {
221 return state_->description.value();
222 }
223 return base::EmptyString();
224 }
225
DescriptionChanged() const226 bool AppUpdate::DescriptionChanged() const {
227 return delta_ && delta_->description.has_value() &&
228 (!state_ || (delta_->description != state_->description));
229 }
230
Version() const231 const std::string& AppUpdate::Version() const {
232 if (delta_ && delta_->version.has_value()) {
233 return delta_->version.value();
234 }
235 if (state_ && state_->version.has_value()) {
236 return state_->version.value();
237 }
238 return base::EmptyString();
239 }
240
VersionChanged() const241 bool AppUpdate::VersionChanged() const {
242 return delta_ && delta_->version.has_value() &&
243 (!state_ || (delta_->version != state_->version));
244 }
245
AdditionalSearchTerms() const246 std::vector<std::string> AppUpdate::AdditionalSearchTerms() const {
247 std::vector<std::string> additional_search_terms;
248
249 if (delta_ && !delta_->additional_search_terms.empty()) {
250 CloneStrings(delta_->additional_search_terms, &additional_search_terms);
251 } else if (state_ && !state_->additional_search_terms.empty()) {
252 CloneStrings(state_->additional_search_terms, &additional_search_terms);
253 }
254
255 return additional_search_terms;
256 }
257
AdditionalSearchTermsChanged() const258 bool AppUpdate::AdditionalSearchTermsChanged() const {
259 return delta_ && !delta_->additional_search_terms.empty() &&
260 (!state_ ||
261 (delta_->additional_search_terms != state_->additional_search_terms));
262 }
263
IconKey() const264 apps::mojom::IconKeyPtr AppUpdate::IconKey() const {
265 if (delta_ && !delta_->icon_key.is_null()) {
266 return delta_->icon_key.Clone();
267 }
268 if (state_ && !state_->icon_key.is_null()) {
269 return state_->icon_key.Clone();
270 }
271 return apps::mojom::IconKeyPtr();
272 }
273
IconKeyChanged() const274 bool AppUpdate::IconKeyChanged() const {
275 return delta_ && !delta_->icon_key.is_null() &&
276 (!state_ || !delta_->icon_key.Equals(state_->icon_key));
277 }
278
LastLaunchTime() const279 base::Time AppUpdate::LastLaunchTime() const {
280 if (delta_ && delta_->last_launch_time.has_value()) {
281 return delta_->last_launch_time.value();
282 }
283 if (state_ && state_->last_launch_time.has_value()) {
284 return state_->last_launch_time.value();
285 }
286 return base::Time();
287 }
288
LastLaunchTimeChanged() const289 bool AppUpdate::LastLaunchTimeChanged() const {
290 return delta_ && delta_->last_launch_time.has_value() &&
291 (!state_ || (delta_->last_launch_time != state_->last_launch_time));
292 }
293
InstallTime() const294 base::Time AppUpdate::InstallTime() const {
295 if (delta_ && delta_->install_time.has_value()) {
296 return delta_->install_time.value();
297 }
298 if (state_ && state_->install_time.has_value()) {
299 return state_->install_time.value();
300 }
301 return base::Time();
302 }
303
InstallTimeChanged() const304 bool AppUpdate::InstallTimeChanged() const {
305 return delta_ && delta_->install_time.has_value() &&
306 (!state_ || (delta_->install_time != state_->install_time));
307 }
308
Permissions() const309 std::vector<apps::mojom::PermissionPtr> AppUpdate::Permissions() const {
310 std::vector<apps::mojom::PermissionPtr> permissions;
311
312 if (delta_ && !delta_->permissions.empty()) {
313 ClonePermissions(delta_->permissions, &permissions);
314 } else if (state_ && !state_->permissions.empty()) {
315 ClonePermissions(state_->permissions, &permissions);
316 }
317
318 return permissions;
319 }
320
PermissionsChanged() const321 bool AppUpdate::PermissionsChanged() const {
322 return delta_ && !delta_->permissions.empty() &&
323 (!state_ || (delta_->permissions != state_->permissions));
324 }
325
InstallSource() const326 apps::mojom::InstallSource AppUpdate::InstallSource() const {
327 if (delta_ &&
328 (delta_->install_source != apps::mojom::InstallSource::kUnknown)) {
329 return delta_->install_source;
330 }
331 if (state_) {
332 return state_->install_source;
333 }
334 return apps::mojom::InstallSource::kUnknown;
335 }
336
InstallSourceChanged() const337 bool AppUpdate::InstallSourceChanged() const {
338 return delta_ &&
339 (delta_->install_source != apps::mojom::InstallSource::kUnknown) &&
340 (!state_ || (delta_->install_source != state_->install_source));
341 }
342
InstalledInternally() const343 apps::mojom::OptionalBool AppUpdate::InstalledInternally() const {
344 switch (InstallSource()) {
345 case apps::mojom::InstallSource::kUnknown:
346 return apps::mojom::OptionalBool::kUnknown;
347 case apps::mojom::InstallSource::kSystem:
348 case apps::mojom::InstallSource::kPolicy:
349 case apps::mojom::InstallSource::kOem:
350 case apps::mojom::InstallSource::kDefault:
351 return apps::mojom::OptionalBool::kTrue;
352 default:
353 return apps::mojom::OptionalBool::kFalse;
354 }
355 }
356
IsPlatformApp() const357 apps::mojom::OptionalBool AppUpdate::IsPlatformApp() const {
358 if (delta_ &&
359 (delta_->is_platform_app != apps::mojom::OptionalBool::kUnknown)) {
360 return delta_->is_platform_app;
361 }
362 if (state_) {
363 return state_->is_platform_app;
364 }
365 return apps::mojom::OptionalBool::kUnknown;
366 }
367
IsPlatformAppChanged() const368 bool AppUpdate::IsPlatformAppChanged() const {
369 return delta_ &&
370 (delta_->is_platform_app != apps::mojom::OptionalBool::kUnknown) &&
371 (!state_ || (delta_->is_platform_app != state_->is_platform_app));
372 }
373
Recommendable() const374 apps::mojom::OptionalBool AppUpdate::Recommendable() const {
375 if (delta_ &&
376 (delta_->recommendable != apps::mojom::OptionalBool::kUnknown)) {
377 return delta_->recommendable;
378 }
379 if (state_) {
380 return state_->recommendable;
381 }
382 return apps::mojom::OptionalBool::kUnknown;
383 }
384
RecommendableChanged() const385 bool AppUpdate::RecommendableChanged() const {
386 return delta_ &&
387 (delta_->recommendable != apps::mojom::OptionalBool::kUnknown) &&
388 (!state_ || (delta_->recommendable != state_->recommendable));
389 }
390
Searchable() const391 apps::mojom::OptionalBool AppUpdate::Searchable() const {
392 if (delta_ && (delta_->searchable != apps::mojom::OptionalBool::kUnknown)) {
393 return delta_->searchable;
394 }
395 if (state_) {
396 return state_->searchable;
397 }
398 return apps::mojom::OptionalBool::kUnknown;
399 }
400
SearchableChanged() const401 bool AppUpdate::SearchableChanged() const {
402 return delta_ &&
403 (delta_->searchable != apps::mojom::OptionalBool::kUnknown) &&
404 (!state_ || (delta_->searchable != state_->searchable));
405 }
406
ShowInLauncher() const407 apps::mojom::OptionalBool AppUpdate::ShowInLauncher() const {
408 if (delta_ &&
409 (delta_->show_in_launcher != apps::mojom::OptionalBool::kUnknown)) {
410 return delta_->show_in_launcher;
411 }
412 if (state_) {
413 return state_->show_in_launcher;
414 }
415 return apps::mojom::OptionalBool::kUnknown;
416 }
417
ShowInLauncherChanged() const418 bool AppUpdate::ShowInLauncherChanged() const {
419 return delta_ &&
420 (delta_->show_in_launcher != apps::mojom::OptionalBool::kUnknown) &&
421 (!state_ || (delta_->show_in_launcher != state_->show_in_launcher));
422 }
423
ShowInShelf() const424 apps::mojom::OptionalBool AppUpdate::ShowInShelf() const {
425 if (delta_ &&
426 (delta_->show_in_shelf != apps::mojom::OptionalBool::kUnknown)) {
427 return delta_->show_in_shelf;
428 }
429 if (state_) {
430 return state_->show_in_shelf;
431 }
432 return apps::mojom::OptionalBool::kUnknown;
433 }
434
ShowInShelfChanged() const435 bool AppUpdate::ShowInShelfChanged() const {
436 return delta_ &&
437 (delta_->show_in_shelf != apps::mojom::OptionalBool::kUnknown) &&
438 (!state_ || (delta_->show_in_shelf != state_->show_in_shelf));
439 }
440
ShowInSearch() const441 apps::mojom::OptionalBool AppUpdate::ShowInSearch() const {
442 if (delta_ &&
443 (delta_->show_in_search != apps::mojom::OptionalBool::kUnknown)) {
444 return delta_->show_in_search;
445 }
446 if (state_) {
447 return state_->show_in_search;
448 }
449 return apps::mojom::OptionalBool::kUnknown;
450 }
451
ShowInSearchChanged() const452 bool AppUpdate::ShowInSearchChanged() const {
453 return delta_ &&
454 (delta_->show_in_search != apps::mojom::OptionalBool::kUnknown) &&
455 (!state_ || (delta_->show_in_search != state_->show_in_search));
456 }
457
ShowInManagement() const458 apps::mojom::OptionalBool AppUpdate::ShowInManagement() const {
459 if (delta_ &&
460 (delta_->show_in_management != apps::mojom::OptionalBool::kUnknown)) {
461 return delta_->show_in_management;
462 }
463 if (state_) {
464 return state_->show_in_management;
465 }
466 return apps::mojom::OptionalBool::kUnknown;
467 }
468
ShowInManagementChanged() const469 bool AppUpdate::ShowInManagementChanged() const {
470 return delta_ &&
471 (delta_->show_in_management != apps::mojom::OptionalBool::kUnknown) &&
472 (!state_ ||
473 (delta_->show_in_management != state_->show_in_management));
474 }
475
HasBadge() const476 apps::mojom::OptionalBool AppUpdate::HasBadge() const {
477 if (delta_ && (delta_->has_badge != apps::mojom::OptionalBool::kUnknown)) {
478 return delta_->has_badge;
479 }
480 if (state_) {
481 return state_->has_badge;
482 }
483 return apps::mojom::OptionalBool::kUnknown;
484 }
485
HasBadgeChanged() const486 bool AppUpdate::HasBadgeChanged() const {
487 return delta_ && (delta_->has_badge != apps::mojom::OptionalBool::kUnknown) &&
488 (!state_ || (delta_->has_badge != state_->has_badge));
489 }
490
Paused() const491 apps::mojom::OptionalBool AppUpdate::Paused() const {
492 if (delta_ && (delta_->paused != apps::mojom::OptionalBool::kUnknown)) {
493 return delta_->paused;
494 }
495 if (state_) {
496 return state_->paused;
497 }
498 return apps::mojom::OptionalBool::kUnknown;
499 }
500
PausedChanged() const501 bool AppUpdate::PausedChanged() const {
502 return delta_ && (delta_->paused != apps::mojom::OptionalBool::kUnknown) &&
503 (!state_ || (delta_->paused != state_->paused));
504 }
505
IntentFilters() const506 std::vector<apps::mojom::IntentFilterPtr> AppUpdate::IntentFilters() const {
507 std::vector<apps::mojom::IntentFilterPtr> intent_filters;
508
509 if (delta_ && !delta_->intent_filters.empty()) {
510 CloneIntentFilters(delta_->intent_filters, &intent_filters);
511 } else if (state_ && !state_->intent_filters.empty()) {
512 CloneIntentFilters(state_->intent_filters, &intent_filters);
513 }
514
515 return intent_filters;
516 }
517
IntentFiltersChanged() const518 bool AppUpdate::IntentFiltersChanged() const {
519 return delta_ && !delta_->intent_filters.empty() &&
520 (!state_ || (delta_->intent_filters != state_->intent_filters));
521 }
522
AccountId() const523 const ::AccountId& AppUpdate::AccountId() const {
524 return account_id_;
525 }
526
527 } // namespace apps
528