/* 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 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;

[scriptable, uuid(059b94e3-45c2-4794-ac2a-5b66a66b5967)]
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;

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

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

  /**
   * 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);

  /**
   * Remove a policy associated with this CSP context.
   * @throws NS_ERROR_FAILURE if the index is out of bounds or invalid.
   */
  void removePolicy(in unsigned long index);

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

  /**
   * Whether this policy allows in-page script.
   * @param shouldReportViolations
   *     Whether or not the use of inline script should be reported.
   *     This function always returns "true" for 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 inline script should be allowed
   *     (block the compilation if false).
   */
  boolean getAllowsInlineScript(out boolean shouldReportViolations);

  /**
   * 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);

  /**
   * Whether this policy allows in-page styles.
   * This includes <style> tags with text content and style="" attributes in
   * HTML elements.
   * @param shouldReportViolations
   *     Whether or not the use of inline style should be reported.
   *     If there are report-only policies, this function may return true
   *     (don't block), but one or more policy may still want to send
   *     violation reports so shouldReportViolations will be true even if the
   *     inline style should be permitted.
   * @return
   *     Whether or not the effects of the inline style should be allowed
   *     (block the rules if false).
   */
  boolean getAllowsInlineStyle(out boolean shouldReportViolations);

  /**
   * Whether this policy accepts the given nonce
   * @param aNonce
   *     The nonce string to check against the policy
   * @param aContentType
   *     The type of element on which we encountered this nonce
   * @param shouldReportViolation
   *     Whether or not the use of an incorrect nonce should be reported.
   *     This function always returns "true" for report-only policies, but when
   *     the report-only policy is violated, shouldReportViolation is true as
   *     well.
   * @return
   *     Whether or not this nonce is valid
   */
   boolean getAllowsNonce(in AString aNonce,
                          in unsigned long aContentType,
                          out boolean shouldReportViolation);

   /**
    * Whether this policy accepts the given inline resource based on the hash
    * of its content.
    * @param aContent
    *     The content of the inline resource to hash (and compare to the
    *     hashes listed in the policy)
    * @param aContentType
    *     The type of inline element (script or style)
    * @param shouldReportViolation
    *     Whether this inline resource should be reported as a hash-source
    *     violation. If there are no hash-sources in the policy, this is
    *     always false.
    * @return
    *     Whether or not this inline resource is whitelisted by a hash-source
    */
   boolean getAllowsHash(in AString aContent,
                         in unsigned short aContentType,
                         out boolean shouldReportViolation);

  /**
   * 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;

  /**
   * Called after the CSP object is created to fill in appropriate request
   * context and give it a reference to its owning principal for violation
   * report generation.
   * This will use whatever data is available, choosing earlier arguments first
   * if multiple are available.  Either way, it will attempt to obtain the URI,
   * referrer and the principal from whatever is available.  If the channel is
   * available, it'll also store that for processing policy-uri directives.
   */
  void setRequestContext(in nsIURI selfURI,
                         in nsIURI referrer,
                         in nsIChannel aChannel);

  /**
   * 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();

};
