Home | History | Annotate | Download | only in database
      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