text: // 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.
  
  // ----------------------------
  // Overview of error design
  // ----------------------------
  //
  // Certificate path validation/parsing may emit a sequence of
  // errors/warnings/context. These are represented by a tree of CertErrorNodes.
  // Each node is comprised of:
  //
  //   * A unique identifier.
  //
  //     This serves similarly to an error code, and is useful for querying if a
  //     particular error occurred.
  //
  //   * [optional] A parameters object.
  //
  //     Nodes may attach a heap-allocated subclass of CertErrorParams, to carry
  //     extra information that is useful when reporting the error. For instance
  //     a parsing error may want to describe where in the DER the failure
  //     happened, or what the unexpected value was.
  //
  //   * [optional] Child nodes.
  //
  //     Error nodes are arranged in a tree. The parent/child hierarchy is used to
  //     group errors that share some common state.
  //     For instance during path processing it is useful to group the
  //     errors/warnings that happened while processing certificate "i" as
  //     children of a shared "context" node. The context node in this case
  //     doesn't describe a particular error, but rather some shared event and
  //     its parameters.
  //
  // ----------------------------
  // Using errors in other APIs
  // ----------------------------
  //
  // The top level object used in APIs is CertErrors. A pointer to a CertErrors
  // object is typically given as an out-parameter for code that may generate
  // errors.
  //
  // Note that CertErrors gives a non-hiearhical interface for emitting errors.
  // In other words, it doesn't let you create parent/child relationships
  // directly.
  //
  // To change the parent node for subsequently emitted errors in the CertErrors
  // object, one constructs a CertErrorScoper on the stack.
  //
  // ----------------------------
  // Defining new errors
  // ----------------------------
  //
  // The error IDs are extensible and do not need to be centrally defined.
  //
  // To define a new error use the macro DEFINE_CERT_ERROR_ID() in a .cc file.
  // If consumers are to be able to query for this error then the symbol should
  // also be exposed in a header file.
  //
  // Error IDs are in truth string literals, whose pointer value will be unique
  // per process.
  
  #ifndef NET_CERT_INTERNAL_CERT_ERRORS_H_
  #define NET_CERT_INTERNAL_CERT_ERRORS_H_
  
  #include <memory>
  #include <vector>
  
  #include "base/compiler_specific.h"
  #include "base/macros.h"
  #include "net/base/net_export.h"
  #include "net/cert/internal/cert_error_id.h"
  
  namespace net {
  
  class CertErrorParams;
  class CertErrorScoper;
  
  // The type of a particular CertErrorNode.
  enum class CertErrorNodeType {
    // Note the TYPE_ prefix is to avoid compile errors. Because ERROR() is a
    // commonly used macro name.
  
    // Node that represents a single error.
    TYPE_ERROR,
  
    // Node that represents a single non-fatal error.
    TYPE_WARNING,
  
    // Parent node for other errors/warnings.
    TYPE_CONTEXT,
  };
  
  struct CertErrorNode;
  using CertErrorNodes = std::vector<std::unique_ptr<CertErrorNode>>;
  
  // CertErrorNode represents a node in the error tree. This could be an error,
  // warning, or simply contextual parent node. See the error design overview for
  // a better description of how this is used.
  struct NET_EXPORT CertErrorNode {
    CertErrorNode(CertErrorNodeType node_type,
                  CertErrorId id,
                  std::unique_ptr<CertErrorParams> params);
    ~CertErrorNode();
  
    void AddChild(std::unique_ptr<CertErrorNode> child);
  
    CertErrorNodeType node_type;
    CertErrorId id;
    std::unique_ptr<CertErrorParams> params;
    CertErrorNodes children;
  };
  
  // CertErrors is the main object for emitting errors and internally builds up
  // the error tree.
  class NET_EXPORT CertErrors {
   public:
    CertErrors();
    ~CertErrors();
  
    // Adds a node to the current insertion point in the error tree. |params| may
    // be null.
    void Add(CertErrorNodeType node_type,
             CertErrorId id,
             std::unique_ptr<CertErrorParams> params);
  
    void AddError(CertErrorId id, std::unique_ptr<CertErrorParams> params);
    void AddError(CertErrorId id);
  
    void AddWarning(CertErrorId id, std::unique_ptr<CertErrorParams> params);
    void AddWarning(CertErrorId id);
  
    // Returns true if the tree is empty. Note that emptiness of the error tree
    // is NOT equivalent to success for some call, and vice versa. (For instance
    // consumers may forget to emit errors on failures, or some errors may be
    // non-fatal warnings).
    bool empty() const;
  
    // Dumps a textual representation of the errors for debugging purposes.
    std::string ToDebugString() const;
  
   private:
    // CertErrorScoper manipulates the CertErrors object.
    friend class CertErrorScoper;
  
    void AddNode(std::unique_ptr<CertErrorNode> node);
  
    // Used by CertErrorScoper to register itself as the top-level scoper.
    // Returns the previously set scoper, or nullptr if there was none.
    CertErrorScoper* SetScoper(CertErrorScoper* scoper);
  
    CertErrorNodes nodes_;
  
    // The top-most CertErrorScoper that is currently in scope (and which affects
    // the parent node for newly added errors).
    CertErrorScoper* current_scoper_ = nullptr;
  
    DISALLOW_COPY_AND_ASSIGN(CertErrors);
  };
  
  }  // namespace net
  
  #endif  // NET_CERT_INTERNAL_CERT_ERRORS_H_
  