/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "nsISerializable.idl"
#include "nsIContentPolicy.idl"

interface nsIURI;
interface nsIChannel;
interface nsIDocShell;
interface nsIDOMDocument;
interface nsIPrincipal;
interface nsIURI;

/**
 * nsIContentSecurityPolicy
 * Describes an XPCOM component used to model and enforce CSPs.  Instances of
 * this class may have multiple policies within them, but there should only be
 * one of these per document/principal.
 */

typedef unsigned short CSPDirective;

%{C++
class nsCSPPolicy;
%}

[ptr] native CSPPolicyPtr(const nsCSPPolicy);

[scriptable, builtinclass, uuid(b3c4c0ae-bd5e-4cad-87e0-8d210dbb3f9f)]
interface nsIContentSecurityPolicy : nsISerializable
{
  /**
   * Directives supported by Content Security Policy.  These are enums for
   * the CSPDirective type.
   * The NO_DIRECTIVE entry is  used for checking default permissions and
   * returning failure when asking CSP which directive to check.
   *
   * NOTE: When implementing a new directive, you will need to add it here but also
   * add it to the CSPStrDirectives array in nsCSPUtils.h.
   */
  const unsigned short NO_DIRECTIVE                   = 0;
  const unsigned short DEFAULT_SRC_DIRECTIVE          = 1;
  const unsigned short SCRIPT_SRC_DIRECTIVE           = 2;
  const unsigned short OBJECT_SRC_DIRECTIVE           = 3;
  const unsigned short STYLE_SRC_DIRECTIVE            = 4;
  const unsigned short IMG_SRC_DIRECTIVE              = 5;
  const unsigned short MEDIA_SRC_DIRECTIVE            = 6;
  const unsigned short FRAME_SRC_DIRECTIVE            = 7;
  const unsigned short FONT_SRC_DIRECTIVE             = 8;
  const unsigned short CONNECT_SRC_DIRECTIVE          = 9;
  const unsigned short REPORT_URI_DIRECTIVE           = 10;
  const unsigned short FRAME_ANCESTORS_DIRECTIVE      = 11;
  const unsigned short REFLECTED_XSS_DIRECTIVE        = 12;
  const unsigned short BASE_URI_DIRECTIVE             = 13;
  const unsigned short FORM_ACTION_DIRECTIVE          = 14;
  const unsigned short REFERRER_DIRECTIVE             = 15;
  const unsigned short WEB_MANIFEST_SRC_DIRECTIVE     = 16;
  const unsigned short UPGRADE_IF_INSECURE_DIRECTIVE  = 17;
  const unsigned short CHILD_SRC_DIRECTIVE            = 18;
  const unsigned short BLOCK_ALL_MIXED_CONTENT        = 19;
  const unsigned short REQUIRE_SRI_FOR                = 20;
  const unsigned short SANDBOX_DIRECTIVE              = 21;

  /**
   * Accessor method for a read-only string version of the policy at a given
   * index.
   */
  [binaryname(GetPolicyString)] AString getPolicy(in unsigned long index);

  /**
   * Accessor method for a read-only pointer the policy object at a given
   * index. Returns a null pointer if the index is larger than the current
   * policy count.
   */
  [noscript,notxpcom,nostdcall] CSPPolicyPtr GetPolicy(in unsigned long index);

  /**
   * Returns the number of policies attached to this CSP instance.  Useful with
   * getPolicy().
   */
  readonly attribute unsigned long policyCount;

  /**
   * Returns whether this policy uses the directive upgrade-insecure-requests.
   * Please note that upgrade-insecure-reqeusts also applies if the parent or
   * including document (context) makes use of the directive.
   */
  readonly attribute bool upgradeInsecureRequests;

  /**
   * Returns whether this policy uses the directive block-all-mixed-content.
   * Please note that block-all-mixed-content takes presedence in case the
   * directive upgrade-insecure-requests is defined in the same policy and
   * will therefore block all mixed content without even trying to perform
   * an upgrade.
   */
  readonly attribute bool blockAllMixedContent;

  /**
   * Obtains the referrer policy (as integer) for this browsing context as
   * specified in CSP.  If there are multiple policies and...
   *  - only one sets a referrer policy: that policy is returned
   *  - more than one sets different referrer policies: no-referrer is returned
   *  - more than one set equivalent policies: that policy is returned
   * For the enumeration of policies see ReferrerPolicy.h and nsIHttpChannel.
   *
   * @param aPolicy
   *        The referrer policy to use for the protected resource.
   * @return
   *        true if a referrer policy is specified, false if it's unspecified.
   */
  bool getReferrerPolicy(out unsigned long policy);

  /**
   * Parse and install a CSP policy.
   * @param aPolicy
   *        String representation of the policy
   *        (e.g., header value, meta content)
   * @param reportOnly
   *        Should this policy affect content, script and style processing or
   *        just send reports if it is violated?
   * @param deliveredViaMetaTag
   *        Indicates whether the policy was delivered via the meta tag.
   */
  void appendPolicy(in AString policyString,
                    in boolean reportOnly,
                    in boolean deliveredViaMetaTag);

  /*
   * Whether this policy allows inline script or style.
   * @param aContentPolicyType Either TYPE_SCRIPT or TYPE_STYLESHEET
   * @param aNonce The nonce string to check against the policy
   * @param aContent  The content of the inline resource to hash
   *        (and compare to the hashes listed in the policy)
   * @param aLineNumber The line number of the inline resource
   *        (used for reporting)
   * @return
   *     Whether or not the effects of the inline style should be allowed
   *     (block the rules if false).
   */
  boolean getAllowsInline(in nsContentPolicyType aContentPolicyType,
                          in AString aNonce,
                          in AString aContent,
                          in unsigned long aLineNumber);

  /**
   * whether this policy allows eval and eval-like functions
   * such as setTimeout("code string", time).
   * @param shouldReportViolations
   *     Whether or not the use of eval should be reported.
   *     This function returns "true" when violating report-only policies, but
   *     when any policy (report-only or otherwise) is violated,
   *     shouldReportViolations is true as well.
   * @return
   *     Whether or not the effects of the eval call should be allowed
   *     (block the call if false).
   */
  boolean getAllowsEval(out boolean shouldReportViolations);

  /**
   * Delegate method called by the service when the protected document is loaded.
   * Returns the union of all the sandbox flags contained in CSP policies. This is the most
   * restrictive interpretation of flags set in multiple policies.
   * See nsSandboxFlags.h for the possible flags.
   *
   * @return
   *    sandbox flags or SANDBOXED_NONE if no sandbox directive exists
   */
  uint32_t getCSPSandboxFlags();

  /**
   * For each violated policy (of type violationType), log policy violation on
   * the Error Console and send a report to report-uris present in the violated
   * policies.
   *
   * @param violationType
   *     one of the VIOLATION_TYPE_* constants, e.g. inline-script or eval
   * @param sourceFile
   *     name of the source file containing the violation (if available)
   * @param contentSample
   *     sample of the violating content (to aid debugging)
   * @param lineNum
   *     source line number of the violation (if available)
   * @param aNonce
   *     (optional) If this is a nonce violation, include the nonce so we can
   *     recheck to determine which policies were violated and send the
   *     appropriate reports.
   * @param aContent
   *     (optional) If this is a hash violation, include contents of the inline
   *     resource in the question so we can recheck the hash in order to
   *     determine which policies were violated and send the appropriate
   *     reports.
   */
  void logViolationDetails(in unsigned short violationType,
                           in AString sourceFile,
                           in AString scriptSample,
                           in int32_t lineNum,
                           [optional] in AString nonce,
                           [optional] in AString content);

  const unsigned short VIOLATION_TYPE_INLINE_SCRIPT          = 1;
  const unsigned short VIOLATION_TYPE_EVAL                   = 2;
  const unsigned short VIOLATION_TYPE_INLINE_STYLE           = 3;
  const unsigned short VIOLATION_TYPE_NONCE_SCRIPT           = 4;
  const unsigned short VIOLATION_TYPE_NONCE_STYLE            = 5;
  const unsigned short VIOLATION_TYPE_HASH_SCRIPT            = 6;
  const unsigned short VIOLATION_TYPE_HASH_STYLE             = 7;
  const unsigned short VIOLATION_TYPE_REQUIRE_SRI_FOR_STYLE  = 8;
  const unsigned short VIOLATION_TYPE_REQUIRE_SRI_FOR_SCRIPT = 9;

  /**
   * Called after the CSP object is created to fill in appropriate request
   * context. Either use
   *  * aDocument (preferred), or if no document is available, then provide
   *  * aPrincipal
   */
  void setRequestContext(in nsIDOMDocument aDocument,
                         in nsIPrincipal aPrincipal);


  /*
   * Checks if a CSP requires Subresource Integrity (SRI)
   * for a given nsContentPolicyType.
   */
  bool requireSRIForType(in nsContentPolicyType aContentType);

  /**
   * Verifies ancestry as permitted by the policy.
   *
   * NOTE: Calls to this may trigger violation reports when queried, so this
   * value should not be cached.
   *
   * @param docShell
   *    containing the protected resource
   * @return
   *    true if the frame's ancestors are all allowed by policy (except for
   *    report-only policies, which will send reports and then return true
   *    here when violated).
   */
  boolean permitsAncestry(in nsIDocShell docShell);


  /**
   * Checks if a specific directive permits loading of a URI.
   *
   * NOTE: Calls to this may trigger violation reports when queried, so the
   * return value should not be cached.
   *
   * @param aURI
   *    The URI about to be loaded or used.
   * @param aDir
   *    The CSPDirective to query (see above constants *_DIRECTIVE).
   * @param aSpecific
   *    If "true" and the directive is specified to fall back to "default-src"
   *    when it's not explicitly provided, directivePermits will NOT try
   *    default-src when the specific directive is not used.  Setting this to
   *    "false" allows CSP to fall back to default-src.  This function
   *    behaves the same for both values of canUseDefault when querying
   *    directives that don't fall-back.
   * @return
   *    Whether or not the provided URI is allowed by CSP under the given
   *    directive. (block the pending operation if false).
   */
  boolean permits(in nsIURI aURI, in CSPDirective aDir, in boolean aSpecific);

  /**
   * Delegate method called by the service when sub-elements of the protected
   * document are being loaded.  Given a bit of information about the request,
   * decides whether or not the policy is satisfied.
   *
   * Calls to this may trigger violation reports when queried, so
   * this value should not be cached.
   */
  short shouldLoad(in nsContentPolicyType aContentType,
                   in nsIURI          aContentLocation,
                   in nsIURI          aRequestOrigin,
                   in nsISupports     aContext,
                   in ACString        aMimeTypeGuess,
                   in nsISupports     aExtra);

%{ C++
// nsIObserver topic to fire when the policy encounters a violation.
#define CSP_VIOLATION_TOPIC "csp-on-violate-policy"
%}

  /**
   * Returns the CSP in JSON notation.
   */
  AString toJSON();

};
