| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/chromeos/arc/fileapi/arc_documents_provider_util.h" | 5 #include "chrome/browser/chromeos/arc/fileapi/arc_documents_provider_util.h" |
| 6 | 6 |
| 7 #include <vector> | 7 #include <vector> |
| 8 | 8 |
| 9 #include "base/strings/string_util.h" | 9 #include "base/strings/string_util.h" |
| 10 #include "base/strings/stringprintf.h" | 10 #include "base/strings/stringprintf.h" |
| 11 #include "net/base/escape.h" | 11 #include "net/base/escape.h" |
| 12 #include "storage/browser/fileapi/file_system_url.h" | 12 #include "storage/browser/fileapi/file_system_url.h" |
| 13 #include "url/gurl.h" | 13 #include "url/gurl.h" |
| 14 | 14 |
| 15 namespace arc { | 15 namespace arc { |
| 16 | 16 |
| 17 // This is based on net/base/escape.cc: net::(anonymous namespace)::Escape. |
| 18 // TODO(nya): Consider consolidating this function with EscapeFileSystemId() in |
| 19 // chrome/browser/chromeos/file_system_provider/mount_path_util.cc. |
| 20 // This version differs from the other one in the point that dots are not always |
| 21 // escaped because authorities often contain harmless dots. |
| 22 std::string EscapePathComponent(const std::string& name) { |
| 23 std::string escaped; |
| 24 // Escape dots only when they forms a special file name. |
| 25 if (name == "." || name == "..") { |
| 26 base::ReplaceChars(name, ".", "%2E", &escaped); |
| 27 return escaped; |
| 28 } |
| 29 // Escape % and / only. |
| 30 for (size_t i = 0; i < name.size(); ++i) { |
| 31 const char c = name[i]; |
| 32 if (c == '%' || c == '/') |
| 33 base::StringAppendF(&escaped, "%%%02X", c); |
| 34 else |
| 35 escaped.push_back(c); |
| 36 } |
| 37 return escaped; |
| 38 } |
| 39 |
| 40 std::string UnescapePathComponent(const std::string& escaped) { |
| 41 return net::UnescapeURLComponent( |
| 42 escaped, net::UnescapeRule::PATH_SEPARATORS | |
| 43 net::UnescapeRule::URL_SPECIAL_CHARS_EXCEPT_PATH_SEPARATORS); |
| 44 } |
| 45 |
| 17 const char kDocumentsProviderMountPointName[] = "arc-documents-provider"; | 46 const char kDocumentsProviderMountPointName[] = "arc-documents-provider"; |
| 18 const base::FilePath::CharType kDocumentsProviderMountPointPath[] = | 47 const base::FilePath::CharType kDocumentsProviderMountPointPath[] = |
| 19 "/special/arc-documents-provider"; | 48 "/special/arc-documents-provider"; |
| 20 const char kAndroidDirectoryMimeType[] = "vnd.android.document/directory"; | 49 const char kAndroidDirectoryMimeType[] = "vnd.android.document/directory"; |
| 21 | 50 |
| 51 base::FilePath GetDocumentsProviderMountPath( |
| 52 const std::string& authority, |
| 53 const std::string& root_document_id) { |
| 54 return base::FilePath(kDocumentsProviderMountPointPath) |
| 55 .Append(EscapePathComponent(authority)) |
| 56 .Append(EscapePathComponent(root_document_id)); |
| 57 } |
| 58 |
| 22 bool ParseDocumentsProviderUrl(const storage::FileSystemURL& url, | 59 bool ParseDocumentsProviderUrl(const storage::FileSystemURL& url, |
| 23 std::string* authority, | 60 std::string* authority, |
| 24 std::string* root_document_id, | 61 std::string* root_document_id, |
| 25 base::FilePath* path) { | 62 base::FilePath* path) { |
| 26 if (url.type() != storage::kFileSystemTypeArcDocumentsProvider) | 63 if (url.type() != storage::kFileSystemTypeArcDocumentsProvider) |
| 27 return false; | 64 return false; |
| 28 base::FilePath url_path_stripped = url.path().StripTrailingSeparators(); | 65 base::FilePath url_path_stripped = url.path().StripTrailingSeparators(); |
| 29 | 66 |
| 30 if (!base::FilePath(kDocumentsProviderMountPointPath) | 67 if (!base::FilePath(kDocumentsProviderMountPointPath) |
| 31 .IsParent(url_path_stripped)) { | 68 .IsParent(url_path_stripped)) { |
| 32 return false; | 69 return false; |
| 33 } | 70 } |
| 34 | 71 |
| 35 // Filesystem URL format for documents provider is: | 72 // Filesystem URL format for documents provider is: |
| 36 // /special/arc-documents-provider/<authority>/<root_doc_id>/<relative_path> | 73 // /special/arc-documents-provider/<authority>/<root_doc_id>/<relative_path> |
| 37 std::vector<base::FilePath::StringType> components; | 74 std::vector<base::FilePath::StringType> components; |
| 38 url_path_stripped.GetComponents(&components); | 75 url_path_stripped.GetComponents(&components); |
| 39 if (components.size() < 5) | 76 if (components.size() < 5) |
| 40 return false; | 77 return false; |
| 41 | 78 |
| 42 *authority = components[3]; | 79 *authority = UnescapePathComponent(components[3]); |
| 43 *root_document_id = components[4]; | 80 *root_document_id = UnescapePathComponent(components[4]); |
| 44 | 81 |
| 45 base::FilePath root_path = base::FilePath(kDocumentsProviderMountPointPath) | 82 base::FilePath root_path = |
| 46 .Append(*authority) | 83 GetDocumentsProviderMountPath(*authority, *root_document_id); |
| 47 .Append(*root_document_id); | |
| 48 // Special case: AppendRelativePath() fails for identical paths. | 84 // Special case: AppendRelativePath() fails for identical paths. |
| 49 if (url_path_stripped == root_path) { | 85 if (url_path_stripped == root_path) { |
| 50 path->clear(); | 86 path->clear(); |
| 51 } else { | 87 } else { |
| 52 bool success = root_path.AppendRelativePath(url_path_stripped, path); | 88 bool success = root_path.AppendRelativePath(url_path_stripped, path); |
| 53 DCHECK(success); | 89 DCHECK(success); |
| 54 } | 90 } |
| 55 return true; | 91 return true; |
| 56 } | 92 } |
| 57 | 93 |
| 58 GURL BuildDocumentUrl(const std::string& authority, | 94 GURL BuildDocumentUrl(const std::string& authority, |
| 59 const std::string& document_id) { | 95 const std::string& document_id) { |
| 60 return GURL(base::StringPrintf( | 96 return GURL(base::StringPrintf( |
| 61 "content://%s/document/%s", | 97 "content://%s/document/%s", |
| 62 net::EscapeQueryParamValue(authority, false /* use_plus */).c_str(), | 98 net::EscapeQueryParamValue(authority, false /* use_plus */).c_str(), |
| 63 net::EscapeQueryParamValue(document_id, false /* use_plus */).c_str())); | 99 net::EscapeQueryParamValue(document_id, false /* use_plus */).c_str())); |
| 64 } | 100 } |
| 65 | 101 |
| 66 } // namespace arc | 102 } // namespace arc |
| OLD | NEW |