C++程序  |  281行  |  9 KB

// Copyright (c) 2012 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.

// Patterns used in content setting rules.

#ifndef CHROME_COMMON_CONTENT_SETTINGS_PATTERN_H_
#define CHROME_COMMON_CONTENT_SETTINGS_PATTERN_H_

#include <ostream>
#include <string>

#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/gtest_prod_util.h"

class GURL;
class Pickle;
class PickleIterator;

namespace content_settings {
class PatternParser;
}

namespace IPC {
class Message;
}

// A pattern used in content setting rules. See |IsValid| for a description of
// possible patterns.
class ContentSettingsPattern {
 public:
  // Each content settings pattern describes a set of origins. Patterns, and the
  // sets they describe, have specific relations. |Relation| describes the
  // relation of two patterns A and B. When pattern A is compared with pattern B
  // (A compare B) interesting relations are:
  // - IDENTITY:
  //   Pattern A and B are identical. The patterns are equal.
  //
  // - DISJOINT_ORDER_PRE:
  //   Pattern A and B have no intersection. A and B never match the origin of
  //   a URL at the same time. But pattern A has a higher precedence than
  //   pattern B when patterns are sorted.
  //
  // - DISJOINT_ORDER_POST:
  //   Pattern A and B have no intersection. A and B never match the origin of
  //   a URL at the same time. But pattern A has a lower precedence than
  //   pattern B when patterns are sorted.
  //
  // - SUCCESSOR:
  //   Pattern A and B have an intersection. But pattern B has a higher
  //   precedence than pattern A for URLs that are matched by both pattern.
  //
  // - PREDECESSOR:
  //   Pattern A and B have an intersection. But pattern A has a higher
  //   precedence than pattern B for URLs that are matched by both pattern.
  enum Relation {
    DISJOINT_ORDER_POST = -2,
    SUCCESSOR = -1,
    IDENTITY = 0,
    PREDECESSOR = 1,
    DISJOINT_ORDER_PRE = 2,
  };

  struct PatternParts {
    PatternParts();
    ~PatternParts();

    // Lowercase string of the URL scheme to match. This string is empty if the
    // |is_scheme_wildcard| flag is set.
    std::string scheme;

    // True if the scheme wildcard is set.
    bool is_scheme_wildcard;

    // Normalized string that is either of the following:
    // - IPv4 or IPv6
    // - hostname
    // - domain
    // - empty string if the |is_host_wildcard flag is set.
    std::string host;

    // True if the domain wildcard is set.
    bool has_domain_wildcard;

    // String with the port to match. This string is empty if the
    // |is_port_wildcard| flag is set.
    std::string port;

    // True if the port wildcard is set.
    bool is_port_wildcard;

    // TODO(markusheintz): Needed for legacy reasons. Remove. Path
    // specification. Only used for content settings pattern with a "file"
    // scheme part.
    std::string path;

    // True if the path wildcard is set.
    bool is_path_wildcard;
  };

  class BuilderInterface {
   public:
    virtual ~BuilderInterface() {}

    virtual BuilderInterface* WithPort(const std::string& port) = 0;

    virtual BuilderInterface* WithPortWildcard() = 0;

    virtual BuilderInterface* WithHost(const std::string& host) = 0;

    virtual BuilderInterface* WithDomainWildcard() = 0;

    virtual BuilderInterface* WithScheme(const std::string& scheme) = 0;

    virtual BuilderInterface* WithSchemeWildcard() = 0;

    virtual BuilderInterface* WithPath(const std::string& path) = 0;

    virtual BuilderInterface* WithPathWildcard() = 0;

    virtual BuilderInterface* Invalid() = 0;

    // Returns a content settings pattern according to the current configuration
    // of the builder.
    virtual ContentSettingsPattern Build() = 0;
  };

  static BuilderInterface* CreateBuilder(bool use_legacy_validate);

  // The version of the pattern format implemented.
  static const int kContentSettingsPatternVersion;

  // The format of a domain wildcard.
  static const char* kDomainWildcard;

  // The length of kDomainWildcard (without the trailing '\0').
  static const size_t kDomainWildcardLength;

  // Returns a wildcard content settings pattern that matches all possible valid
  // origins.
  static ContentSettingsPattern Wildcard();

  // Returns a pattern that matches the scheme and host of this URL, as well as
  // all subdomains and ports.
  static ContentSettingsPattern FromURL(const GURL& url);

  // Returns a pattern that matches exactly this URL.
  static ContentSettingsPattern FromURLNoWildcard(const GURL& url);

  // Returns a pattern that matches the given pattern specification.
  // Valid patterns specifications are:
  //   - [*.]domain.tld (matches domain.tld and all sub-domains)
  //   - host (matches an exact hostname)
  //   - scheme://host:port (supported schemes: http,https)
  //   - scheme://[*.]domain.tld:port (supported schemes: http,https)
  //   - file://path (The path has to be an absolute path and start with a '/')
  //   - a.b.c.d (matches an exact IPv4 ip)
  //   - [a:b:c:d:e:f:g:h] (matches an exact IPv6 ip)
  static ContentSettingsPattern FromString(const std::string& pattern_spec);

  static ContentSettingsPattern LegacyFromString(
      const std::string& pattern_spec);

  // Constructs an empty pattern. Empty patterns are invalid patterns. Invalid
  // patterns match nothing.
  ContentSettingsPattern();

  // Serializes the pattern to an IPC message or deserializes it.
  void WriteToMessage(IPC::Message* m) const;
  bool ReadFromMessage(const IPC::Message* m, PickleIterator* iter);

  // True if this is a valid pattern.
  bool IsValid() const { return is_valid_; }

  // True if |url| matches this pattern.
  bool Matches(const GURL& url) const;

  // True if this pattern matches all hosts (i.e. it has a host wildcard).
  bool MatchesAllHosts() const;

  // Returns a std::string representation of this pattern.
  const std::string ToString() const;

  // Compares the pattern with a given |other| pattern and returns the
  // |Relation| of the two patterns.
  Relation Compare(const ContentSettingsPattern& other) const;

  // Returns true if the pattern and the |other| pattern are identical.
  bool operator==(const ContentSettingsPattern& other) const;

  // Returns true if the pattern and the |other| pattern are not identical.
  bool operator!=(const ContentSettingsPattern& other) const;

  // Returns true if the pattern has a lower priority than the |other| pattern.
  bool operator<(const ContentSettingsPattern& other) const;

  // Returns true if the pattern has a higher priority than the |other| pattern.
  bool operator>(const ContentSettingsPattern& other) const;

 private:
  friend class content_settings::PatternParser;
  friend class Builder;
  FRIEND_TEST_ALL_PREFIXES(ContentSettingsPatternParserTest, SerializePatterns);

  class Builder : public BuilderInterface {
    public:
     explicit Builder(bool use_legacy_validate);
     virtual ~Builder();

     // Overrides BuilderInterface
     virtual BuilderInterface* WithPort(const std::string& port) OVERRIDE;

     virtual BuilderInterface* WithPortWildcard() OVERRIDE;

     virtual BuilderInterface* WithHost(const std::string& host) OVERRIDE;

     virtual BuilderInterface* WithDomainWildcard() OVERRIDE;

     virtual BuilderInterface* WithScheme(const std::string& scheme) OVERRIDE;

     virtual BuilderInterface* WithSchemeWildcard() OVERRIDE;

     virtual BuilderInterface* WithPath(const std::string& path) OVERRIDE;

     virtual BuilderInterface* WithPathWildcard() OVERRIDE;

     virtual BuilderInterface* Invalid() OVERRIDE;

     virtual ContentSettingsPattern Build() OVERRIDE;

    private:
     // Canonicalizes the pattern parts so that they are ASCII only, either
     // in original (if it was already ASCII) or punycode form. Returns true if
     // the canonicalization was successful.
     static bool Canonicalize(PatternParts* parts);

     // Returns true when the pattern |parts| represent a valid pattern.
     static bool Validate(const PatternParts& parts);

     static bool LegacyValidate(const PatternParts& parts);

     bool is_valid_;

     bool use_legacy_validate_;

     PatternParts parts_;

     DISALLOW_COPY_AND_ASSIGN(Builder);
  };

  static Relation CompareScheme(
      const ContentSettingsPattern::PatternParts& parts,
      const ContentSettingsPattern::PatternParts& other_parts);

  static Relation CompareHost(
      const ContentSettingsPattern::PatternParts& parts,
      const ContentSettingsPattern::PatternParts& other_parts);

  static Relation ComparePort(
      const ContentSettingsPattern::PatternParts& parts,
      const ContentSettingsPattern::PatternParts& other_parts);

  static bool Validate(const PatternParts& parts);

  ContentSettingsPattern(const PatternParts& parts, bool valid);

  PatternParts parts_;

  bool is_valid_;
};

// Stream operator so ContentSettingsPattern can be used in assertion
// statements.
inline std::ostream& operator<<(
    std::ostream& out, const ContentSettingsPattern& pattern) {
  return out << pattern.ToString();
}

#endif  // CHROME_COMMON_CONTENT_SETTINGS_PATTERN_H_