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

Unified Diff: chrome/browser/chromeos/arc/fileapi/arc_documents_provider_document.cc

Issue 2574173002: mediaview: Implement ArcDocumentsProviderRoot. (Closed)
Patch Set: 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 side-by-side diff with in-line comments
Download patch
Index: chrome/browser/chromeos/arc/fileapi/arc_documents_provider_document.cc
diff --git a/chrome/browser/chromeos/arc/fileapi/arc_documents_provider_document.cc b/chrome/browser/chromeos/arc/fileapi/arc_documents_provider_document.cc
new file mode 100644
index 0000000000000000000000000000000000000000..7c1b7aba655948d88a7f6b0071b9c2f5a75e9ca8
--- /dev/null
+++ b/chrome/browser/chromeos/arc/fileapi/arc_documents_provider_document.cc
@@ -0,0 +1,177 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/arc/fileapi/arc_documents_provider_document.h"
+
+#include <set>
+
+#include "base/memory/ptr_util.h"
+#include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
+#include "chrome/browser/chromeos/arc/fileapi/arc_documents_provider_util.h"
+#include "net/base/mime_util.h"
+
+namespace arc {
+
+ArcDocumentsProviderDocument::ArcDocumentsProviderDocument(
+ const std::string& document_id,
+ bool is_directory)
+ : document_id_(document_id),
+ is_directory_(is_directory),
+ children_(is_directory ? new ChildMap() : nullptr) {}
+
+ArcDocumentsProviderDocument::~ArcDocumentsProviderDocument() = default;
+
+// static
+ArcDocumentsProviderDocument* ArcDocumentsProviderDocument::CreateFromDocument(
+ const mojom::Document& document) {
+ return new ArcDocumentsProviderDocument(
+ document.document_id, document.mime_type == kAndroidDirectoryMimeType);
+}
+
+ArcDocumentsProviderDocument* ArcDocumentsProviderDocument::Lookup(
+ const base::FilePath& path) {
+ if (path.empty()) {
Luis Héctor Chávez 2016/12/15 02:40:31 nit: elide braces for all the one-line if blocks.
Shuhei Takahashi 2016/12/15 06:50:57 Done.
+ return this;
+ }
+ ArcDocumentsProviderDocument* current = this;
+ std::vector<base::FilePath::StringType> components;
+ path.GetComponents(&components);
+ for (const base::FilePath::StringType& component : components) {
+ if (!current->is_directory()) {
+ return nullptr;
+ }
+ auto iter = current->children_->find(component);
+ if (iter == current->children_->end()) {
+ return nullptr;
+ }
+ current = iter->second.get();
+ }
+ return current;
+}
+
+void ArcDocumentsProviderDocument::UpdateWithChildDocuments(
+ const std::vector<mojom::DocumentPtr>& children) {
+ DCHECK(is_directory_);
+
+ ChildMap& old_map = *children_;
+ ChildMap new_map;
+
+ std::set<mojom::Document*> processed;
Luis Héctor Chávez 2016/12/15 02:40:31 How large do you think these maps/sets are going t
Shuhei Takahashi 2016/12/15 06:50:57 It is the number of files in a single directory, s
Luis Héctor Chávez 2016/12/15 23:54:26 sort of. depends on the load factor. On 64-bit mac
+
+ // If a document is in |old_map|, keep the mapping for them.
+ {
+ std::map<std::string, base::FilePath::StringType> reverse_old_map;
+ for (const auto& pair : old_map) {
+ reverse_old_map[pair.second->document_id()] = pair.first;
+ }
+ for (const mojom::DocumentPtr& child : children) {
+ auto iter = reverse_old_map.find(child->document_id);
+ if (iter != reverse_old_map.end()) {
Luis Héctor Chávez 2016/12/15 02:40:31 nit: if (iter == reverse_old_map.end()) continu
Shuhei Takahashi 2016/12/15 06:50:57 Done.
+ new_map[iter->second].reset(CreateFromDocument(*child));
+ processed.insert(&*child);
+ }
+ }
+ }
+
+ // Process new documents without name conflicts.
+ std::map<base::FilePath::StringType, int> name_counters;
Luis Héctor Chávez 2016/12/15 02:40:31 Can you also wrap this in a block to ensure |name_
Shuhei Takahashi 2016/12/15 06:50:57 Done.
+ for (const mojom::DocumentPtr& child : children) {
+ if (processed.count(&*child) > 0) {
+ continue;
+ }
+ name_counters[GetFileNameForDocument(child)] += 1;
+ }
+ for (const mojom::DocumentPtr& child : children) {
+ if (processed.count(&*child) > 0) {
+ continue;
+ }
+ base::FilePath::StringType filename = GetFileNameForDocument(child);
+ DCHECK(name_counters[filename] >= 1);
+ if (name_counters[filename] == 1 && new_map.count(filename) == 0) {
+ new_map[filename].reset(CreateFromDocument(*child));
+ processed.insert(&*child);
+ }
+ }
+
+ // Finally, deal with conflicts.
+ std::map<std::string, int> suffix_counters;
+ for (const mojom::DocumentPtr& child : children) {
+ if (processed.count(&*child) > 0) {
+ continue;
+ }
+
+ base::FilePath::StringType filename = GetFileNameForDocument(child);
+
+ if (new_map.count(filename) > 0) {
+ // Resolve a conflict by adding a suffix.
+ int& suffix_counter = suffix_counters[filename];
+ if (suffix_counter == 0) {
+ suffix_counter = 1;
+ }
+ while (true) {
+ std::string suffix = base::StringPrintf(" %d", suffix_counter);
+ ++suffix_counter;
Luis Héctor Chávez 2016/12/15 02:40:31 Why not move this above L114? That way you don't n
Shuhei Takahashi 2016/12/15 06:50:57 Sounds like a good idea.
+ base::FilePath::StringType new_filename =
+ base::FilePath(filename).InsertBeforeExtensionASCII(suffix).value();
+ if (new_map.count(new_filename) == 0) {
+ filename = new_filename;
+ break;
+ }
+ }
+ }
+
+ new_map[filename].reset(CreateFromDocument(*child));
+ processed.insert(&*child);
+ }
+
+ DCHECK_EQ(processed.size(), children.size());
+
+ old_map.swap(new_map);
+}
+
+// static
+base::FilePath::StringType ArcDocumentsProviderDocument::GetFileNameForDocument(
+ const mojom::DocumentPtr& document) {
+ base::FilePath::StringType filename = document->display_name;
+
+ // Replace path separators appearing in the file name.
+ // Chrome OS is POSIX and kSeparators is "/".
+ base::ReplaceChars(filename, base::FilePath::kSeparators, "_", &filename);
+
+ // Do not allow "." and "..", though this is very unlikely to happen.
+ if (filename == base::FilePath::kCurrentDirectory) {
+ filename = "dot";
+ } else if (filename == base::FilePath::kParentDirectory) {
+ filename = "dotdot";
+ }
+
+ // Since Chrome detects MIME type from file name extensions, we need to change
+ // the file name extension of the document if it does not match with its MIME
+ // type.
+ // For example, Audio Media Provider presents a music file with its title as
+ // the file name.
+ base::FilePath::StringType extension =
+ base::ToLowerASCII(base::FilePath(filename).Extension());
+ if (!extension.empty()) {
+ extension = extension.substr(1); // Strip the leading dot.
+ }
+ std::vector<base::FilePath::StringType> possible_extensions;
+ net::GetExtensionsForMimeType(document->mime_type, &possible_extensions);
+ if (!possible_extensions.empty() &&
+ std::find(possible_extensions.begin(), possible_extensions.end(),
+ extension) == possible_extensions.end()) {
+ std::string new_extension;
+ if (!net::GetPreferredExtensionForMimeType(document->mime_type,
+ &new_extension)) {
+ new_extension = possible_extensions[0];
+ }
+ filename =
+ base::StringPrintf("%s.%s", filename.c_str(), new_extension.c_str());
+ }
+
+ return filename;
+}
+
+} // namespace arc

Powered by Google App Engine
This is Rietveld 408576698