toolkit/components/extensions/WebExtensionPolicy.h
author Kris Maglione <maglione.k@gmail.com>
Wed, 27 Sep 2017 18:15:12 -0700
changeset 383532 cd219dd09639d421b6ebf2f85ada518dd8a4c0c2
parent 383168 1ede5092b3695bac4248f6f9435120a7ef603a7c
child 385053 67a8e12324569dd730347187e2ffccae486c758b
permissions -rw-r--r--
Bug 1402944: Part 5 - Move request filtering and permission matching into ChannelWrapper. r=mixedpuppy,ehsan This allows us to reuse the same URLInfo objects for each permission or extension that we match, and also avoids a lot of XPConnect overhead we wind up incurring when we access URI objects from the JS side. MozReview-Commit-ID: GqgVRjQ3wYQ

/* -*-  Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2; -*- */
/* 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/. */

#ifndef mozilla_extensions_WebExtensionPolicy_h
#define mozilla_extensions_WebExtensionPolicy_h

#include "mozilla/dom/BindingDeclarations.h"
#include "mozilla/dom/WebExtensionPolicyBinding.h"
#include "mozilla/extensions/MatchPattern.h"

#include "jspubtd.h"

#include "mozilla/Result.h"
#include "mozilla/WeakPtr.h"
#include "nsCOMPtr.h"
#include "nsCycleCollectionParticipant.h"
#include "nsISupports.h"
#include "nsWrapperCache.h"

namespace mozilla {
namespace extensions {

using dom::WebExtensionInit;
using dom::WebExtensionLocalizeCallback;

class WebExtensionContentScript;

class WebExtensionPolicy final : public nsISupports
                               , public nsWrapperCache
                               , public SupportsWeakPtr<WebExtensionPolicy>
{
public:
  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(WebExtensionPolicy)
  MOZ_DECLARE_WEAKREFERENCE_TYPENAME(WebExtensionPolicy)

  using ScriptArray = nsTArray<RefPtr<WebExtensionContentScript>>;

  static already_AddRefed<WebExtensionPolicy>
  Constructor(dom::GlobalObject& aGlobal, const WebExtensionInit& aInit, ErrorResult& aRv);

  nsIAtom* Id() const { return mId; }
  void GetId(nsAString& aId) const { aId = nsDependentAtomString(mId); };

  const nsCString& MozExtensionHostname() const { return mHostname; }
  void GetMozExtensionHostname(nsACString& aHostname) const
  {
    aHostname = MozExtensionHostname();
  }

  void GetBaseURL(nsACString& aBaseURL) const
  {
    MOZ_ALWAYS_SUCCEEDS(mBaseURI->GetSpec(aBaseURL));
  }

  void GetURL(const nsAString& aPath, nsAString& aURL, ErrorResult& aRv) const;

  Result<nsString, nsresult> GetURL(const nsAString& aPath) const;

  bool CanAccessURI(const URLInfo& aURI, bool aExplicit = false) const
  {
    return mHostPermissions && mHostPermissions->Matches(aURI, aExplicit);
  }

  bool IsPathWebAccessible(const nsAString& aPath) const
  {
    return mWebAccessiblePaths.Matches(aPath);
  }

  bool HasPermission(const nsIAtom* aPermission) const
  {
    return mPermissions->Contains(aPermission);
  }
  bool HasPermission(const nsAString& aPermission) const
  {
    return mPermissions->Contains(aPermission);
  }

  nsCString BackgroundPageHTML() const;

  void Localize(const nsAString& aInput, nsString& aResult) const;

  const nsString& Name() const
  {
    return mName;
  }
  void GetName(nsAString& aName) const
  {
    aName = mName;
  }

  const nsString& ContentSecurityPolicy() const
  {
    return mContentSecurityPolicy;
  }
  void GetContentSecurityPolicy(nsAString& aCSP) const
  {
    aCSP = mContentSecurityPolicy;
  }


  already_AddRefed<MatchPatternSet> AllowedOrigins()
  {
    return do_AddRef(mHostPermissions);
  }
  void SetAllowedOrigins(MatchPatternSet& aAllowedOrigins)
  {
    mHostPermissions = &aAllowedOrigins;
  }

  void GetPermissions(nsTArray<nsString>& aResult) const
  {
    mPermissions->Get(aResult);
  }
  void SetPermissions(const nsTArray<nsString>& aPermissions)
  {
    mPermissions = new AtomSet(aPermissions);
  }

  void GetContentScripts(ScriptArray& aScripts) const;
  const ScriptArray& ContentScripts() const { return mContentScripts; }


  bool Active() const { return mActive; }
  void SetActive(bool aActive, ErrorResult& aRv);


  static void
  GetActiveExtensions(dom::GlobalObject& aGlobal, nsTArray<RefPtr<WebExtensionPolicy>>& aResults);

  static already_AddRefed<WebExtensionPolicy>
  GetByID(dom::GlobalObject& aGlobal, const nsAString& aID);

  static already_AddRefed<WebExtensionPolicy>
  GetByHostname(dom::GlobalObject& aGlobal, const nsACString& aHostname);

  static already_AddRefed<WebExtensionPolicy>
  GetByURI(dom::GlobalObject& aGlobal, nsIURI* aURI);


  static bool UseRemoteWebExtensions(dom::GlobalObject& aGlobal);
  static bool IsExtensionProcess(dom::GlobalObject& aGlobal);


  nsISupports* GetParentObject() const { return mParent; }

  virtual JSObject* WrapObject(JSContext* aCx, JS::HandleObject aGivenProto) override;

protected:
  virtual ~WebExtensionPolicy() = default;

private:
  WebExtensionPolicy(dom::GlobalObject& aGlobal, const WebExtensionInit& aInit, ErrorResult& aRv);

  bool Enable();
  bool Disable();

  nsCOMPtr<nsISupports> mParent;

  RefPtr<nsIAtom> mId;
  nsCString mHostname;
  nsCOMPtr<nsIURI> mBaseURI;

  nsString mName;
  nsString mContentSecurityPolicy;

  bool mActive = false;

  RefPtr<WebExtensionLocalizeCallback> mLocalizeCallback;

  RefPtr<AtomSet> mPermissions;
  RefPtr<MatchPatternSet> mHostPermissions;
  MatchGlobSet mWebAccessiblePaths;

  Nullable<nsTArray<nsString>> mBackgroundScripts;

  nsTArray<RefPtr<WebExtensionContentScript>> mContentScripts;
};

} // namespace extensions
} // namespace mozilla

#endif // mozilla_extensions_WebExtensionPolicy_h