// Copyright 2015 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef COBALT_WEB_CSP_DELEGATE_H_
#define COBALT_WEB_CSP_DELEGATE_H_

#include <memory>
#include <string>

#include "cobalt/base/source_location.h"
#include "cobalt/csp/content_security_policy.h"
#include "cobalt/web/csp_delegate_type.h"
#include "cobalt/web/csp_violation_reporter.h"

namespace cobalt {
namespace web {

// Object that represents a Content Security Policy for a particular document.
// Owned by the Document. Objects wishing to enforce CSP need to query the
// delegate to decide if they are permitted to load a resource.
// Note that any thread may call CanLoad().
class CspDelegate {
 public:
  struct Options {
    Options() = default;
    Options(const network_bridge::PostSender& post_sender,
            csp::CSPHeaderPolicy header_policy,
            CspEnforcementType enforcement_type, int insecure_allowed_token = 0)
        : post_sender(post_sender),
          header_policy(header_policy),
          enforcement_type(enforcement_type),
          insecure_allowed_token(insecure_allowed_token) {}

    network_bridge::PostSender post_sender;
    csp::CSPHeaderPolicy header_policy = csp::kCSPRequired;
    CspEnforcementType enforcement_type = kCspEnforcementEnable;
    int insecure_allowed_token = 0;
  };

  enum ResourceType {
    kFont,
    kImage,
    kLocation,
    kMedia,
    kScript,
    kStyle,
    kWorker,
    kXhr,
    kWebSocket,
  };

  CspDelegate();
  virtual ~CspDelegate();

  virtual const csp::ContentSecurityPolicy* GetPolicyContainer() = 0;
  virtual void ClonePolicyContainer(
      const csp::ContentSecurityPolicy& other) = 0;

  // Return |true| if the given resource type can be loaded from |url|.
  // Set |did_redirect| if url was the result of a redirect.
  virtual bool CanLoad(ResourceType type, const GURL& url,
                       bool did_redirect) const = 0;
  virtual bool IsValidNonce(ResourceType type,
                            const std::string& nonce) const = 0;

  virtual bool AllowInline(ResourceType type,
                           const base::SourceLocation& location,
                           const std::string& script_content) const = 0;

  // Return |true| if 'unsafe-eval' is set. No report will be generated in any
  // case. If eval_disabled_message is non-NULL, it will be set with a message
  // that should be reported when an application attempts to use eval().
  virtual bool AllowEval(std::string* eval_disabled_message) const = 0;

  // Report that code was generated from a string, such as through eval() or the
  // Function constructor. If eval() is not allowed, generate a violation
  // report. Otherwise if eval() is allowed this is a no-op.
  virtual void ReportEval() const = 0;

  // Signal to the CSP object that CSP policy directives have been received.
  // Return |true| if success, |false| if failure and load should be aborted.
  virtual bool OnReceiveHeaders(const csp::ResponseHeaders& headers) = 0;
  virtual void OnReceiveHeader(const std::string& header,
                               csp::HeaderType header_type,
                               csp::HeaderSource header_source) = 0;
  // Inform the policy that the document's origin has changed.
  virtual void NotifyUrlChanged(const GURL& url) const = 0;

 private:
  DISALLOW_COPY_AND_ASSIGN(CspDelegate);
};

// This class is just a no-op implementation that allows everything.
class CspDelegateInsecure : public CspDelegate {
 public:
  CspDelegateInsecure() {}
  const csp::ContentSecurityPolicy* GetPolicyContainer() override {
    return nullptr;
  }
  void ClonePolicyContainer(const csp::ContentSecurityPolicy& other) override {
    // No policy to clone.
    return;
  }
  bool CanLoad(ResourceType, const GURL&, bool) const override { return true; }
  bool IsValidNonce(ResourceType, const std::string&) const override {
    return true;
  }
  bool AllowInline(ResourceType, const base::SourceLocation&,
                   const std::string&) const override {
    return true;
  }
  bool AllowEval(std::string*) const override { return true; }
  void ReportEval() const override {}
  bool OnReceiveHeaders(const csp::ResponseHeaders&) override { return true; }
  void OnReceiveHeader(const std::string&, csp::HeaderType,
                       csp::HeaderSource) override {}
  void NotifyUrlChanged(const GURL&) const override {}

 private:
  DISALLOW_COPY_AND_ASSIGN(CspDelegateInsecure);
};

class CspDelegateSecure : public CspDelegate {
 public:
  CspDelegateSecure(std::unique_ptr<CspViolationReporter> violation_reporter,
                    const GURL& url, csp::CSPHeaderPolicy csp_header_policy,
                    const base::Closure& policy_changed_callback);
  ~CspDelegateSecure();

  const csp::ContentSecurityPolicy* GetPolicyContainer() override {
    return csp_.get();
  }
  void ClonePolicyContainer(const csp::ContentSecurityPolicy& other) override;

  // Return |true| if the given resource type can be loaded from |url|.
  // Set |did_redirect| if url was the result of a redirect.
  bool CanLoad(ResourceType type, const GURL& url,
               bool did_redirect) const override;
  bool IsValidNonce(ResourceType type, const std::string& nonce) const override;

  bool AllowInline(ResourceType type, const base::SourceLocation& location,
                   const std::string& script_content) const override;

  // Return |true| if 'unsafe-eval' is set. No report will be generated in any
  // case. If eval_disabled_message is non-NULL, it will be set with a message
  // that should be reported when an application attempts to use eval().
  bool AllowEval(std::string* eval_disabled_message) const override;

  // Report that code was generated from a string, such as through eval() or the
  // Function constructor. If eval() is not allowed, generate a violation
  // report. Otherwise if eval() is allowed this is a no-op.
  void ReportEval() const override;

  // Signal to the CSP object that CSP policy directives have been received.
  // Return |true| if success, |false| if failure and load should be aborted.
  bool OnReceiveHeaders(const csp::ResponseHeaders& headers) override;
  void OnReceiveHeader(const std::string& header, csp::HeaderType header_type,
                       csp::HeaderSource header_source) override;
  void NotifyUrlChanged(const GURL& url) const override {
    return csp_->NotifyUrlChanged(url);
  }

 protected:
  void SetLocationPolicy(const std::string& policy);

  std::unique_ptr<csp::ContentSecurityPolicy> csp_;

  // Helper class to send violation events to any reporting endpoints.
  std::unique_ptr<CspViolationReporter> reporter_;

  // We disallow all loads if CSP headers weren't received. This tracks if we
  // did get a valid header.
  bool was_header_received_;

  // This should be called any time the CSP policy changes. For example, after
  // receiving (and parsing) the headers, or after encountering a CSP directive
  // in a <meta> tag.
  base::Closure policy_changed_callback_;

  // Whether Cobalt is forbidden to render without receiving CSP header.
  csp::CSPHeaderPolicy csp_header_policy_;

 private:
  DISALLOW_COPY_AND_ASSIGN(CspDelegateSecure);
};

}  // namespace web
}  // namespace cobalt

#endif  // COBALT_WEB_CSP_DELEGATE_H_
