author Ehsan Akhgari <>
Thu, 29 Nov 2018 10:30:46 +0000
changeset 505141 04f0bbf40bf36957dc1f72a8aae9916df0e3222f
parent 500257 c4633ad9220fa16e7ab25ba30e82cd792ca1eb5e
child 505383 6f3709b3878117466168c40affa7bca0b60cf75b
permissions -rw-r--r--
Bug 1508472 - Part 5: Fifth batch of comment fix-ups in preparation for the tree reformat r=sylvestre This is a best effort attempt at ensuring that the adverse impact of reformatting the entire tree over the comments would be minimal. I've used a combination of strategies including disabling of formatting, some manual formatting and some changes to formatting to work around some clang-format limitations. Differential Revision:

/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2; -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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 */

#ifndef mozilla_extensions_ChannelWrapper_h
#define mozilla_extensions_ChannelWrapper_h

#include "mozilla/dom/BindingDeclarations.h"
#include "mozilla/dom/ChannelWrapperBinding.h"

#include "mozilla/WebRequestService.h"
#include "mozilla/extensions/MatchPattern.h"
#include "mozilla/extensions/WebExtensionPolicy.h"

#include "mozilla/Attributes.h"
#include "mozilla/LinkedList.h"
#include "mozilla/Maybe.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/WeakPtr.h"

#include "mozilla/DOMEventTargetHelper.h"
#include "nsCOMPtr.h"
#include "nsCycleCollectionParticipant.h"
#include "nsIChannel.h"
#include "nsIHttpChannel.h"
#include "nsIStreamListener.h"
#include "nsITabParent.h"
#include "nsIThreadRetargetableStreamListener.h"
#include "nsPointerHashKeys.h"
#include "nsInterfaceHashtable.h"
#include "nsIWeakReferenceUtils.h"
#include "nsWrapperCache.h"

{ 0xc06162d2, 0xb803, 0x43b4, \
  { 0xaa, 0x31, 0xcf, 0x69, 0x7f, 0x93, 0x68, 0x1c } }

class nsILoadContext;
class nsITraceableChannel;

namespace mozilla {
namespace dom {
  class nsIContentParent;
  class Element;
} // namespace dom
namespace extensions {

namespace detail {

  // We need to store our wrapped channel as a weak reference, since channels
  // are not cycle collected, and we're going to be hanging this wrapper
  // instance off the channel in order to ensure the same channel always has
  // the same wrapper.
  // But since performance matters here, and we don't want to have to
  // QueryInterface the channel every time we touch it, we store separate
  // nsIChannel and nsIHttpChannel weak references, and check that the WeakPtr
  // is alive before returning it.
  // This holder class prevents us from accidentally touching the weak pointer
  // members directly from our ChannelWrapper class.
  struct ChannelHolder
    explicit ChannelHolder(nsIChannel* aChannel)
      : mChannel(do_GetWeakReference(aChannel))
      , mWeakChannel(aChannel)

    bool HaveChannel() const { return mChannel && mChannel->IsAlive(); }

    void SetChannel(nsIChannel* aChannel)
      mChannel = do_GetWeakReference(aChannel);
      mWeakChannel = aChannel;

    already_AddRefed<nsIChannel> MaybeChannel() const
      if (!HaveChannel()) {
        mWeakChannel = nullptr;
      return do_AddRef(mWeakChannel);

    already_AddRefed<nsIHttpChannel> MaybeHttpChannel() const
      if (mWeakHttpChannel.isNothing()) {
        nsCOMPtr<nsIHttpChannel> chan = QueryChannel();

      if (!HaveChannel()) {
        mWeakHttpChannel.ref() = nullptr;
      return do_AddRef(mWeakHttpChannel.value());

    const nsQueryReferent QueryChannel() const { return do_QueryReferent(mChannel); }

    nsWeakPtr mChannel;

    mutable nsIChannel* MOZ_NON_OWNING_REF mWeakChannel;
    mutable Maybe<nsIHttpChannel*> MOZ_NON_OWNING_REF mWeakHttpChannel;

class WebRequestChannelEntry;

class ChannelWrapper final : public DOMEventTargetHelper
                           , public SupportsWeakPtr<ChannelWrapper>
                           , public LinkedListElement<ChannelWrapper>
                           , private detail::ChannelHolder


  void Die();

  static already_AddRefed<extensions::ChannelWrapper> Get(const dom::GlobalObject& global, nsIChannel* channel);
  static already_AddRefed<extensions::ChannelWrapper> GetRegisteredChannel(const dom::GlobalObject& global, uint64_t aChannelId, const WebExtensionPolicy& aAddon, nsITabParent* aTabParent);

  uint64_t Id() const { return mId; }

  already_AddRefed<nsIChannel> GetChannel() const { return MaybeChannel(); }

  void SetChannel(nsIChannel* aChannel);

  void Cancel(uint32_t result, ErrorResult& aRv);

  void RedirectTo(nsIURI* uri, ErrorResult& aRv);
  void UpgradeToSecure(ErrorResult& aRv);

  bool Suspended() const { return mSuspended; }

  void SetSuspended(bool aSuspended, ErrorResult& aRv);

  void GetContentType(nsCString& aContentType) const;
  void SetContentType(const nsACString& aContentType);

  void RegisterTraceableChannel(const WebExtensionPolicy& aAddon, nsITabParent* aTabParent);

  already_AddRefed<nsITraceableChannel> GetTraceableChannel(nsAtom* aAddonId, dom::nsIContentParent* aContentParent) const;

  void GetMethod(nsCString& aRetVal) const;

  dom::MozContentPolicyType Type() const;

  uint32_t StatusCode() const;

  void GetStatusLine(nsCString& aRetVal) const;

  void GetErrorString(nsString& aRetVal) const;

  void ErrorCheck();


  already_AddRefed<nsIURI> FinalURI() const;

  void GetFinalURL(nsString& aRetVal) const;

  bool Matches(const dom::MozRequestFilter& aFilter,
               const WebExtensionPolicy* aExtension,
               const dom::MozRequestMatchOptions& aOptions) const;

  already_AddRefed<nsILoadInfo> GetLoadInfo() const
    nsCOMPtr<nsIChannel> chan = MaybeChannel();
    if (chan) {
      return chan->GetLoadInfo();
    return nullptr;

  int64_t WindowId() const;

  int64_t ParentWindowId() const;

  void GetFrameAncestors(dom::Nullable<nsTArray<dom::MozFrameAncestorInfo>>& aFrameAncestors, ErrorResult& aRv) const;

  bool IsSystemLoad() const;

  void GetOriginURL(nsCString& aRetVal) const;

  void GetDocumentURL(nsCString& aRetVal) const;

  already_AddRefed<nsIURI> GetOriginURI() const;

  already_AddRefed<nsIURI> GetDocumentURI() const;

  already_AddRefed<nsILoadContext> GetLoadContext() const;

  already_AddRefed<dom::Element> GetBrowserElement() const;

  bool CanModify() const;
  bool GetCanModify(ErrorResult& aRv) const
    return CanModify();

  void GetProxyInfo(dom::Nullable<dom::MozProxyInfo>& aRetVal, ErrorResult& aRv) const;

  void GetRemoteAddress(nsCString& aRetVal) const;

  void GetRequestHeaders(nsTArray<dom::MozHTTPHeader>& aRetVal, ErrorResult& aRv) const;

  void GetResponseHeaders(nsTArray<dom::MozHTTPHeader>& aRetVal, ErrorResult& aRv) const;

  void SetRequestHeader(const nsCString& header, const nsCString& value, bool merge, ErrorResult& aRv);

  void SetResponseHeader(const nsCString& header, const nsCString& value, bool merge, ErrorResult& aRv);

  using EventTarget::EventListenerAdded;
  using EventTarget::EventListenerRemoved;
  virtual void EventListenerAdded(nsAtom* aType) override;
  virtual void EventListenerRemoved(nsAtom* aType) override;

  nsISupports* GetParentObject() const { return mParent; }

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


  ChannelWrapper(nsISupports* aParent, nsIChannel* aChannel);

  void ClearCachedAttributes();

  bool CheckAlive(ErrorResult& aRv) const
    if (!HaveChannel()) {
      return false;
    return true;

  void FireEvent(const nsAString& aType);

  const URLInfo& FinalURLInfo() const;
  const URLInfo* DocumentURLInfo() const;

  uint64_t WindowId(nsILoadInfo* aLoadInfo) const;

  nsresult GetFrameAncestors(nsILoadInfo* aLoadInfo, nsTArray<dom::MozFrameAncestorInfo>& aFrameAncestors) const;

  static uint64_t GetNextId()
    static uint64_t sNextId = 1;
    return ++sNextId;

  void CheckEventListeners();

  class ChannelWrapperStub final : public nsISupports

    explicit ChannelWrapperStub(ChannelWrapper* aChannelWrapper)
      : mChannelWrapper(aChannelWrapper)

    friend class ChannelWrapper;

    RefPtr<ChannelWrapper> mChannelWrapper;

    ~ChannelWrapperStub() = default;

  RefPtr<ChannelWrapperStub> mStub;

  mutable Maybe<URLInfo> mFinalURLInfo;
  mutable Maybe<URLInfo> mDocumentURLInfo;

  UniquePtr<WebRequestChannelEntry> mChannelEntry;

  // The overridden Content-Type header value.
  nsCString mContentTypeHdr = VoidCString();

  const uint64_t mId = GetNextId();
  nsCOMPtr<nsISupports> mParent;

  bool mAddedStreamListener = false;
  bool mFiredErrorEvent = false;
  bool mSuspended = false;
  bool mResponseStarted = false;

  nsInterfaceHashtable<nsPtrHashKey<const nsAtom>, nsITabParent> mAddonEntries;

  class RequestListener final : public nsIStreamListener
                              , public nsIThreadRetargetableStreamListener

    explicit RequestListener(ChannelWrapper* aWrapper)
      : mChannelWrapper(aWrapper) {}

    nsresult Init();

    virtual ~RequestListener();

    RefPtr<ChannelWrapper> mChannelWrapper;
    nsCOMPtr<nsIStreamListener> mOrigStreamListener;


} // namespace extensions
} // namespace mozilla

#endif // mozilla_extensions_ChannelWrapper_h