1 // Copyright 2020 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 "ash/public/cpp/holding_space/holding_space_item.h"
6
7 #include "ash/public/cpp/holding_space/holding_space_image.h"
8 #include "base/memory/ptr_util.h"
9 #include "base/strings/strcat.h"
10 #include "base/util/values/values_util.h"
11
12 namespace ash {
13
14 namespace {
15
16 // Used to indicate which version of serialization is being used. When
17 // intentionally breaking backwards compatibility, increment this value and
18 // perform any necessary conversions in `Deserialize()`.
19 constexpr int kVersion = 1;
20
21 // Preference paths.
22 // NOTE: As these paths are written to preferences, changes must ensure
23 // backwards compatibility. When intentionally breaking backwards compatibility,
24 // increment `kVersion` and perform any needed conversions in `Deserialize()`.
25 constexpr char kFilePathPath[] = "filePath";
26 constexpr char kIdPath[] = "id";
27 constexpr char kTypePath[] = "type";
28 constexpr char kVersionPath[] = "version";
29
TypeToString(HoldingSpaceItem::Type type)30 std::string TypeToString(HoldingSpaceItem::Type type) {
31 switch (type) {
32 case HoldingSpaceItem::Type::kPinnedFile:
33 return "pinned_file";
34 case HoldingSpaceItem::Type::kDownload:
35 return "download";
36 case HoldingSpaceItem::Type::kScreenshot:
37 return "screenshot";
38 case HoldingSpaceItem::Type::kNearbyShare:
39 return "nearby_share";
40 case HoldingSpaceItem::Type::kScreenRecording:
41 return "screen_recording";
42 }
43 }
44
45 } // namespace
46
47 HoldingSpaceItem::~HoldingSpaceItem() = default;
48
operator ==(const HoldingSpaceItem & rhs) const49 bool HoldingSpaceItem::operator==(const HoldingSpaceItem& rhs) const {
50 return type_ == rhs.type_ && id_ == rhs.id_ && file_path_ == rhs.file_path_ &&
51 file_system_url_ == rhs.file_system_url_ && text_ == rhs.text_ &&
52 *image_ == *rhs.image_;
53 }
54
55 // static
GetFileBackedItemId(Type type,const base::FilePath & file_path)56 std::string HoldingSpaceItem::GetFileBackedItemId(
57 Type type,
58 const base::FilePath& file_path) {
59 return base::StrCat({TypeToString(type), ":", file_path.value()});
60 }
61
62 // static
CreateFileBackedItem(Type type,const base::FilePath & file_path,const GURL & file_system_url,std::unique_ptr<HoldingSpaceImage> image)63 std::unique_ptr<HoldingSpaceItem> HoldingSpaceItem::CreateFileBackedItem(
64 Type type,
65 const base::FilePath& file_path,
66 const GURL& file_system_url,
67 std::unique_ptr<HoldingSpaceImage> image) {
68 DCHECK(!file_system_url.is_empty());
69
70 // Note: std::make_unique does not work with private constructors.
71 return base::WrapUnique(new HoldingSpaceItem(
72 type, GetFileBackedItemId(type, file_path), file_path, file_system_url,
73 file_path.BaseName().LossyDisplayName(), std::move(image)));
74 }
75
76 // static
77 // NOTE: This method must remain in sync with `Serialize()`. If multiple
78 // serialization versions are supported, care must be taken to handle each.
Deserialize(const base::DictionaryValue & dict,ImageResolver image_resolver)79 std::unique_ptr<HoldingSpaceItem> HoldingSpaceItem::Deserialize(
80 const base::DictionaryValue& dict,
81 ImageResolver image_resolver) {
82 const base::Optional<int> version = dict.FindIntPath(kVersionPath);
83 DCHECK(version.has_value() && version.value() == kVersion);
84
85 const Type type = static_cast<Type>(dict.FindIntPath(kTypePath).value());
86 const base::FilePath file_path = DeserializeFilePath(dict);
87
88 // NOTE: `std::make_unique` does not work with private constructors.
89 return base::WrapUnique(new HoldingSpaceItem(
90 type, DeserializeId(dict), file_path,
91 /*file_system_url=*/GURL(), file_path.BaseName().LossyDisplayName(),
92 std::move(image_resolver).Run(type, file_path)));
93 }
94
95 // static
96 // NOTE: This method must remain in sync with `Serialize()`. If multiple
97 // serialization versions are supported, care must be taken to handle each.
DeserializeId(const base::DictionaryValue & dict)98 const std::string& HoldingSpaceItem::DeserializeId(
99 const base::DictionaryValue& dict) {
100 const base::Optional<int> version = dict.FindIntPath(kVersionPath);
101 DCHECK(version.has_value() && version.value() == kVersion);
102
103 const std::string* id = dict.FindStringPath(kIdPath);
104 DCHECK(id);
105
106 return *id;
107 }
108
109 // static
110 // NOTE: This method must remain in sync with `Serialize()`. If multiple
111 // serialization versions are supported, care must be taken to handle each.
DeserializeFilePath(const base::DictionaryValue & dict)112 base::FilePath HoldingSpaceItem::DeserializeFilePath(
113 const base::DictionaryValue& dict) {
114 const base::Optional<int> version = dict.FindIntPath(kVersionPath);
115 DCHECK(version.has_value() && version.value() == kVersion);
116
117 const base::Optional<base::FilePath> file_path =
118 util::ValueToFilePath(dict.FindPath(kFilePathPath));
119 DCHECK(file_path.has_value());
120
121 return file_path.value();
122 }
123
124 // NOTE: This method must remain in sync with `Deserialize()`. The
125 // return value will be written to preferences so this implementation must
126 // maintain backwards compatibility so long as `kVersion` remains unchanged.
Serialize() const127 base::DictionaryValue HoldingSpaceItem::Serialize() const {
128 base::DictionaryValue dict;
129 dict.SetIntPath(kVersionPath, kVersion);
130 dict.SetIntPath(kTypePath, static_cast<int>(type_));
131 dict.SetStringPath(kIdPath, id_);
132 dict.SetPath(kFilePathPath, util::FilePathToValue(file_path_));
133 return dict;
134 }
135
HoldingSpaceItem(Type type,const std::string & id,const base::FilePath & file_path,const GURL & file_system_url,const base::string16 & text,std::unique_ptr<HoldingSpaceImage> image)136 HoldingSpaceItem::HoldingSpaceItem(Type type,
137 const std::string& id,
138 const base::FilePath& file_path,
139 const GURL& file_system_url,
140 const base::string16& text,
141 std::unique_ptr<HoldingSpaceImage> image)
142 : type_(type),
143 id_(id),
144 file_path_(file_path),
145 file_system_url_(file_system_url),
146 text_(text),
147 image_(std::move(image)) {}
148
IsFinalized() const149 bool HoldingSpaceItem::IsFinalized() const {
150 return !file_system_url_.is_empty();
151 }
152
Finalize(const GURL & file_system_url)153 void HoldingSpaceItem::Finalize(const GURL& file_system_url) {
154 DCHECK(!IsFinalized());
155 DCHECK(!file_system_url.is_empty());
156 file_system_url_ = file_system_url;
157 }
158
159 } // namespace ash
160