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

Side by Side Diff: chrome/browser/chromeos/arc/fileapi/arc_documents_provider_document.cc

Issue 2574173002: mediaview: Implement ArcDocumentsProviderRoot. (Closed)
Patch Set: Address lhchavez's comments. Created 4 years 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
OLDNEW
(Empty)
1 // Copyright 2016 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/chromeos/arc/fileapi/arc_documents_provider_document.h"
6
7 #include <set>
8
9 #include "base/memory/ptr_util.h"
10 #include "base/strings/string_util.h"
11 #include "base/strings/stringprintf.h"
12 #include "chrome/browser/chromeos/arc/fileapi/arc_documents_provider_util.h"
13 #include "net/base/mime_util.h"
14
15 namespace arc {
16
17 ArcDocumentsProviderDocument::ArcDocumentsProviderDocument(
18 const std::string& document_id,
19 bool is_directory)
20 : document_id_(document_id),
21 is_directory_(is_directory),
22 children_(is_directory ? new ChildMap() : nullptr) {}
23
24 ArcDocumentsProviderDocument::~ArcDocumentsProviderDocument() {
25 DCHECK(thread_checker_.CalledOnValidThread());
26 }
27
28 // static
29 ArcDocumentsProviderDocument* ArcDocumentsProviderDocument::CreateFromDocument(
30 const mojom::Document& document) {
31 return new ArcDocumentsProviderDocument(
32 document.document_id, document.mime_type == kAndroidDirectoryMimeType);
33 }
34
35 ArcDocumentsProviderDocument* ArcDocumentsProviderDocument::Lookup(
36 const base::FilePath& path) {
37 DCHECK(thread_checker_.CalledOnValidThread());
38
39 if (path.empty())
40 return this;
41
42 ArcDocumentsProviderDocument* current = this;
43 std::vector<base::FilePath::StringType> components;
44 path.GetComponents(&components);
45
46 for (const base::FilePath::StringType& component : components) {
47 if (!current->is_directory())
48 return nullptr;
49
50 auto iter = current->children_->find(component);
51 if (iter == current->children_->end())
52 return nullptr;
53
54 current = iter->second.get();
55 }
56 return current;
57 }
58
59 void ArcDocumentsProviderDocument::UpdateWithChildDocuments(
60 const std::vector<mojom::DocumentPtr>& children) {
61 DCHECK(thread_checker_.CalledOnValidThread());
62 DCHECK(is_directory_);
63
64 ChildMap& old_map = *children_;
65 ChildMap new_map;
66
67 std::set<mojom::Document*> processed;
68
69 // If a document is in |old_map|, keep the mapping for them.
70 {
71 std::map<std::string, base::FilePath::StringType> reverse_old_map;
72 for (const auto& pair : old_map) {
73 reverse_old_map[pair.second->document_id()] = pair.first;
74 }
75 for (const mojom::DocumentPtr& child : children) {
76 auto iter = reverse_old_map.find(child->document_id);
77 if (iter == reverse_old_map.end())
78 continue;
79 new_map[iter->second].reset(CreateFromDocument(*child));
80 processed.insert(&*child);
81 }
82 }
83
84 // Process new documents without name conflicts.
85 std::map<base::FilePath::StringType, int> name_counters;
Luis Héctor Chávez 2016/12/15 23:54:26 nit: wrap in a block for consistency?
Shuhei Takahashi 2016/12/16 05:47:14 Done.
86 for (const mojom::DocumentPtr& child : children) {
87 if (processed.count(&*child) > 0)
88 continue;
89 name_counters[GetFileNameForDocument(child)] += 1;
90 }
91 for (const mojom::DocumentPtr& child : children) {
92 if (processed.count(&*child) > 0)
93 continue;
94 base::FilePath::StringType filename = GetFileNameForDocument(child);
95 DCHECK(name_counters[filename] >= 1);
96 if (name_counters[filename] == 1 && new_map.count(filename) == 0) {
97 new_map[filename].reset(CreateFromDocument(*child));
98 processed.insert(&*child);
99 }
100 }
101
102 // Finally, deal with conflicts.
103 {
104 std::map<std::string, int> suffix_counters;
105 for (const mojom::DocumentPtr& child : children) {
106 if (processed.count(&*child) > 0)
107 continue;
108
109 base::FilePath::StringType filename = GetFileNameForDocument(child);
110
111 if (new_map.count(filename) > 0) {
112 // Resolve a conflict by adding a suffix.
113 int& suffix_counter = suffix_counters[filename];
114 while (true) {
115 ++suffix_counter;
116 std::string suffix = base::StringPrintf(" %d", suffix_counter);
117 base::FilePath::StringType new_filename =
118 base::FilePath(filename)
119 .InsertBeforeExtensionASCII(suffix)
120 .value();
121 if (new_map.count(new_filename) == 0) {
122 filename = new_filename;
123 break;
124 }
125 }
126 }
127
128 new_map[filename].reset(CreateFromDocument(*child));
129 processed.insert(&*child);
130 }
131 }
132
133 DCHECK_EQ(processed.size(), children.size());
134
135 old_map.swap(new_map);
136 }
137
138 // static
139 base::FilePath::StringType ArcDocumentsProviderDocument::GetFileNameForDocument(
140 const mojom::DocumentPtr& document) {
141 base::FilePath::StringType filename = document->display_name;
142
143 // Replace path separators appearing in the file name.
144 // Chrome OS is POSIX and kSeparators is "/".
145 base::ReplaceChars(filename, base::FilePath::kSeparators, "_", &filename);
146
147 // Do not allow "." and "..", though this is very unlikely to happen.
148 if (filename == base::FilePath::kCurrentDirectory) {
149 filename = "dot";
150 } else if (filename == base::FilePath::kParentDirectory) {
151 filename = "dotdot";
152 }
153
154 // Since Chrome detects MIME type from file name extensions, we need to change
155 // the file name extension of the document if it does not match with its MIME
156 // type.
157 // For example, Audio Media Provider presents a music file with its title as
158 // the file name.
159 base::FilePath::StringType extension =
160 base::ToLowerASCII(base::FilePath(filename).Extension());
161 if (!extension.empty())
162 extension = extension.substr(1); // Strip the leading dot.
163 std::vector<base::FilePath::StringType> possible_extensions;
164 net::GetExtensionsForMimeType(document->mime_type, &possible_extensions);
165 if (!possible_extensions.empty() &&
166 std::find(possible_extensions.begin(), possible_extensions.end(),
167 extension) == possible_extensions.end()) {
168 std::string new_extension;
169 if (!net::GetPreferredExtensionForMimeType(document->mime_type,
170 &new_extension)) {
171 new_extension = possible_extensions[0];
172 }
173 filename =
174 base::StringPrintf("%s.%s", filename.c_str(), new_extension.c_str());
Luis Héctor Chávez 2016/12/15 23:54:26 Given that you're already converting |filename| to
Shuhei Takahashi 2016/12/16 05:47:14 Using base::FilePath sounds good, thanks for the p
175 }
176
177 return filename;
178 }
179
180 } // namespace arc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698