1 // Copyright 2013 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 "webkit/common/database/database_identifier.h" 6 7 #include "base/strings/string_number_conversions.h" 8 #include "base/strings/string_util.h" 9 #include "url/url_canon.h" 10 11 namespace webkit_database { 12 13 // static 14 std::string GetIdentifierFromOrigin(const GURL& origin) { 15 return DatabaseIdentifier::CreateFromOrigin(origin).ToString(); 16 } 17 18 // static 19 GURL GetOriginFromIdentifier(const std::string& identifier) { 20 return DatabaseIdentifier::Parse(identifier).ToOrigin(); 21 } 22 23 static bool SchemeIsUnique(const std::string& scheme) { 24 return scheme == "about" || scheme == "data" || scheme == "javascript"; 25 } 26 27 // static 28 const DatabaseIdentifier DatabaseIdentifier::UniqueFileIdentifier() { 29 return DatabaseIdentifier("", "", 0, true, true); 30 } 31 32 // static 33 DatabaseIdentifier DatabaseIdentifier::CreateFromOrigin(const GURL& origin) { 34 if (!origin.is_valid() || origin.is_empty() || 35 !origin.IsStandard() || SchemeIsUnique(origin.scheme())) 36 return DatabaseIdentifier(); 37 38 if (origin.SchemeIsFile()) 39 return UniqueFileIdentifier(); 40 41 int port = origin.IntPort(); 42 if (port == url_parse::PORT_INVALID) 43 return DatabaseIdentifier(); 44 45 // We encode the default port for the specified scheme as 0. GURL 46 // canonicalizes this as an unspecified port. 47 if (port == url_parse::PORT_UNSPECIFIED) 48 port = 0; 49 50 return DatabaseIdentifier(origin.scheme(), 51 origin.host(), 52 port, 53 false /* unique */, 54 false /* file */); 55 } 56 57 // static 58 DatabaseIdentifier DatabaseIdentifier::Parse(const std::string& identifier) { 59 if (!IsStringASCII(identifier)) 60 return DatabaseIdentifier(); 61 62 size_t first_underscore = identifier.find_first_of('_'); 63 if (first_underscore == std::string::npos || first_underscore == 0) 64 return DatabaseIdentifier(); 65 66 size_t last_underscore = identifier.find_last_of('_'); 67 if (last_underscore == std::string::npos || 68 last_underscore == first_underscore || 69 last_underscore == identifier.length() - 1) 70 return DatabaseIdentifier(); 71 72 std::string scheme(identifier.data(), first_underscore); 73 if (scheme == "file") 74 return UniqueFileIdentifier(); 75 76 // This magical set of schemes is always treated as unique. 77 if (SchemeIsUnique(scheme)) 78 return DatabaseIdentifier(); 79 80 base::StringPiece port_str(identifier.begin() + last_underscore + 1, 81 identifier.end()); 82 int port = 0; 83 if (!base::StringToInt(port_str, &port) || port < 0 || port >= 1 << 16) 84 return DatabaseIdentifier(); 85 86 std::string hostname(identifier.data() + first_underscore + 1, 87 last_underscore - first_underscore - 1); 88 GURL url(scheme + "://" + hostname + "/"); 89 90 if (!url.IsStandard()) 91 hostname = ""; 92 93 // If a url doesn't parse cleanly or doesn't round trip, reject it. 94 if (!url.is_valid() || url.scheme() != scheme || url.host() != hostname) 95 return DatabaseIdentifier(); 96 97 return DatabaseIdentifier(scheme, hostname, port, false /* unique */, false); 98 } 99 100 DatabaseIdentifier::DatabaseIdentifier() 101 : port_(0), 102 is_unique_(true), 103 is_file_(false) { 104 } 105 106 DatabaseIdentifier::DatabaseIdentifier(const std::string& scheme, 107 const std::string& hostname, 108 int port, 109 bool is_unique, 110 bool is_file) 111 : scheme_(scheme), 112 hostname_(StringToLowerASCII(hostname)), 113 port_(port), 114 is_unique_(is_unique), 115 is_file_(is_file) { 116 } 117 118 DatabaseIdentifier::~DatabaseIdentifier() {} 119 120 std::string DatabaseIdentifier::ToString() const { 121 if (is_file_) 122 return "file__0"; 123 if (is_unique_) 124 return "__0"; 125 return scheme_ + "_" + hostname_ + "_" + base::IntToString(port_); 126 } 127 128 GURL DatabaseIdentifier::ToOrigin() const { 129 if (is_file_) 130 return GURL("file:///"); 131 if (is_unique_) 132 return GURL(); 133 if (port_ == 0) 134 return GURL(scheme_ + "://" + hostname_); 135 return GURL(scheme_ + "://" + hostname_ + ":" + base::IntToString(port_)); 136 } 137 138 } // namespace webkit_database 139