Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  nsContentPermissionHelper.cpp   Sprache: C

 
/* -*- Mode: C++; tab-width: 8; 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 http://mozilla.org/MPL/2.0/. */


#include <map>
#include "nsCOMPtr.h"
#include "nsIPrincipal.h"
#include "mozilla/dom/BrowserChild.h"
#include "mozilla/dom/BrowserParent.h"
#include "mozilla/dom/ContentChild.h"
#include "mozilla/dom/ContentParent.h"
#include "mozilla/dom/Element.h"
#include "mozilla/dom/Event.h"
#include "mozilla/dom/PContentPermission.h"
#include "mozilla/dom/PermissionMessageUtils.h"
#include "mozilla/dom/PContentPermissionRequestParent.h"
#include "mozilla/dom/ScriptSettings.h"
#include "mozilla/Attributes.h"
#include "mozilla/Preferences.h"
#include "mozilla/Unused.h"
#include "nsComponentManagerUtils.h"
#include "nsArrayUtils.h"
#include "nsIMutableArray.h"
#include "nsContentPermissionHelper.h"
#include "nsGlobalWindowInner.h"
#include "nsJSUtils.h"
#include "nsISupportsPrimitives.h"
#include "nsServiceManagerUtils.h"
#include "mozilla/dom/Document.h"
#include "nsIWeakReferenceUtils.h"
#include "js/PropertyAndElement.h"  // JS_GetProperty, JS_SetProperty

using mozilla::Unused;  // <snicker>
using namespace mozilla::dom;
using namespace mozilla;
using DelegateInfo = PermissionDelegateHandler::PermissionDelegateInfo;

namespace mozilla::dom {

class ContentPermissionRequestParent : public PContentPermissionRequestParent {
 public:
  // @param aIsRequestDelegatedToUnsafeThirdParty see
  // mIsRequestDelegatedToUnsafeThirdParty.
  ContentPermissionRequestParent(
      const nsTArray<PermissionRequest>& aRequests, Element* aElement,
      nsIPrincipal* aPrincipal, nsIPrincipal* aTopLevelPrincipal,
      const bool aHasValidTransientUserGestureActivation,
      const bool aIsRequestDelegatedToUnsafeThirdParty);
  virtual ~ContentPermissionRequestParent();

  bool IsBeingDestroyed();

  nsCOMPtr<nsIPrincipal> mPrincipal;
  nsCOMPtr<nsIPrincipal> mTopLevelPrincipal;
  nsCOMPtr<Element> mElement;
  bool mHasValidTransientUserGestureActivation;

  // See nsIPermissionDelegateHandler.maybeUnsafePermissionDelegate.
  bool mIsRequestDelegatedToUnsafeThirdParty;

  RefPtr<nsContentPermissionRequestProxy> mProxy;
  nsTArray<PermissionRequest> mRequests;

 private:
  // Not MOZ_CAN_RUN_SCRIPT because we can't annotate the thing we override yet.
  MOZ_CAN_RUN_SCRIPT_BOUNDARY
  virtual mozilla::ipc::IPCResult Recvprompt() override;
  virtual mozilla::ipc::IPCResult RecvDestroy() override;
  virtual void ActorDestroy(ActorDestroyReason why) override;
};

ContentPermissionRequestParent::ContentPermissionRequestParent(
    const nsTArray<PermissionRequest>& aRequests, Element* aElement,
    nsIPrincipal* aPrincipal, nsIPrincipal* aTopLevelPrincipal,
    const bool aHasValidTransientUserGestureActivation,
    const bool aIsRequestDelegatedToUnsafeThirdParty) {
  MOZ_COUNT_CTOR(ContentPermissionRequestParent);

  mPrincipal = aPrincipal;
  mTopLevelPrincipal = aTopLevelPrincipal;
  mElement = aElement;
  mRequests = aRequests.Clone();
  mHasValidTransientUserGestureActivation =
      aHasValidTransientUserGestureActivation;
  mIsRequestDelegatedToUnsafeThirdParty = aIsRequestDelegatedToUnsafeThirdParty;
}

ContentPermissionRequestParent::~ContentPermissionRequestParent() {
  MOZ_COUNT_DTOR(ContentPermissionRequestParent);
}

mozilla::ipc::IPCResult ContentPermissionRequestParent::Recvprompt() {
  mProxy = new nsContentPermissionRequestProxy(this);
  if (NS_FAILED(mProxy->Init(mRequests))) {
    RefPtr<nsContentPermissionRequestProxy> proxy(mProxy);
    proxy->Cancel();
  }
  return IPC_OK();
}

mozilla::ipc::IPCResult ContentPermissionRequestParent::RecvDestroy() {
  Unused << PContentPermissionRequestParent::Send__delete__(this);
  return IPC_OK();
}

void ContentPermissionRequestParent::ActorDestroy(ActorDestroyReason why) {
  if (mProxy) {
    mProxy->OnParentDestroyed();
  }
}

bool ContentPermissionRequestParent::IsBeingDestroyed() {
  // When ContentParent::MarkAsDead() is called, we are being destroyed.
  // It's unsafe to send out any message now.
  ContentParent* contentParent = static_cast<ContentParent*>(Manager());
  return !contentParent->IsAlive();
}

NS_IMPL_ISUPPORTS(ContentPermissionType, nsIContentPermissionType)

ContentPermissionType::ContentPermissionType(
    const nsACString& aType, const nsTArray<nsString>& aOptions) {
  mType = aType;
  mOptions = aOptions.Clone();
}

ContentPermissionType::~ContentPermissionType() = default;

NS_IMETHODIMP
ContentPermissionType::GetType(nsACString& aType) {
  aType = mType;
  return NS_OK;
}

NS_IMETHODIMP
ContentPermissionType::GetOptions(nsIArray** aOptions) {
  NS_ENSURE_ARG_POINTER(aOptions);

  *aOptions = nullptr;

  nsresult rv;
  nsCOMPtr<nsIMutableArray> options =
      do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
  NS_ENSURE_SUCCESS(rv, rv);

  // copy options into JS array
  for (uint32_t i = 0; i < mOptions.Length(); ++i) {
    nsCOMPtr<nsISupportsString> isupportsString =
        do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID, &rv);
    NS_ENSURE_SUCCESS(rv, rv);

    rv = isupportsString->SetData(mOptions[i]);
    NS_ENSURE_SUCCESS(rv, rv);

    rv = options->AppendElement(isupportsString);
    NS_ENSURE_SUCCESS(rv, rv);
  }

  options.forget(aOptions);
  return NS_OK;
}

// nsContentPermissionUtils

/* static */
uint32_t nsContentPermissionUtils::ConvertPermissionRequestToArray(
    nsTArray<PermissionRequest>& aSrcArray, nsIMutableArray* aDesArray) {
  uint32_t len = aSrcArray.Length();
  for (uint32_t i = 0; i < len; i++) {
    RefPtr<ContentPermissionType> cpt =
        new ContentPermissionType(aSrcArray[i].type(), aSrcArray[i].options());
    aDesArray->AppendElement(cpt);
  }
  return len;
}

/* static */
void nsContentPermissionUtils::ConvertArrayToPermissionRequest(
    nsIArray* aSrcArray, nsTArray<PermissionRequest>& aDesArray) {
  uint32_t len = 0;
  aSrcArray->GetLength(&len);
  for (uint32_t i = 0; i < len; i++) {
    nsCOMPtr<nsIContentPermissionType> cpt = do_QueryElementAt(aSrcArray, i);
    nsAutoCString type;
    cpt->GetType(type);

    nsCOMPtr<nsIArray> optionArray;
    cpt->GetOptions(getter_AddRefs(optionArray));
    uint32_t optionsLength = 0;
    if (optionArray) {
      optionArray->GetLength(&optionsLength);
    }
    nsTArray<nsString> options;
    for (uint32_t j = 0; j < optionsLength; ++j) {
      nsCOMPtr<nsISupportsString> isupportsString =
          do_QueryElementAt(optionArray, j);
      if (isupportsString) {
        nsString option;
        isupportsString->GetData(option);
        options.AppendElement(option);
      }
    }

    aDesArray.AppendElement(PermissionRequest(type, options));
  }
}

static std::map<PContentPermissionRequestParent*, TabId>&
ContentPermissionRequestParentMap() {
  MOZ_ASSERT(NS_IsMainThread());
  static std::map<PContentPermissionRequestParent*, TabId>
      sPermissionRequestParentMap;
  return sPermissionRequestParentMap;
}

static std::map<PContentPermissionRequestChild*, TabId>&
ContentPermissionRequestChildMap() {
  MOZ_ASSERT(NS_IsMainThread());
  static std::map<PContentPermissionRequestChild*, TabId>
      sPermissionRequestChildMap;
  return sPermissionRequestChildMap;
}

/* static */
nsresult nsContentPermissionUtils::CreatePermissionArray(
    const nsACString& aType, const nsTArray<nsString>& aOptions,
    nsIArray** aTypesArray) {
  nsCOMPtr<nsIMutableArray> types = do_CreateInstance(NS_ARRAY_CONTRACTID);
  RefPtr<ContentPermissionType> permType =
      new ContentPermissionType(aType, aOptions);
  types->AppendElement(permType);
  types.forget(aTypesArray);

  return NS_OK;
}

/* static */
PContentPermissionRequestParent*
nsContentPermissionUtils::CreateContentPermissionRequestParent(
    const nsTArray<PermissionRequest>& aRequests, Element* aElement,
    nsIPrincipal* aPrincipal, nsIPrincipal* aTopLevelPrincipal,
    const bool aHasValidTransientUserGestureActivation,
    const bool aIsRequestDelegatedToUnsafeThirdParty, const TabId& aTabId) {
  PContentPermissionRequestParent* parent = new ContentPermissionRequestParent(
      aRequests, aElement, aPrincipal, aTopLevelPrincipal,
      aHasValidTransientUserGestureActivation,
      aIsRequestDelegatedToUnsafeThirdParty);
  ContentPermissionRequestParentMap()[parent] = aTabId;

  return parent;
}

/* static */
nsresult nsContentPermissionUtils::AskPermission(
    nsIContentPermissionRequest* aRequest, nsPIDOMWindowInner* aWindow) {
  NS_ENSURE_STATE(aWindow && aWindow->IsCurrentInnerWindow());

  // for content process
  if (XRE_IsContentProcess()) {
    RefPtr<RemotePermissionRequest> req =
        new RemotePermissionRequest(aRequest, aWindow);

    MOZ_ASSERT(NS_IsMainThread());  // IPC can only be execute on main thread.

    BrowserChild* child = BrowserChild::GetFrom(aWindow->GetDocShell());
    NS_ENSURE_TRUE(child, NS_ERROR_FAILURE);

    nsCOMPtr<nsIArray> typeArray;
    nsresult rv = aRequest->GetTypes(getter_AddRefs(typeArray));
    NS_ENSURE_SUCCESS(rv, rv);

    nsTArray<PermissionRequest> permArray;
    ConvertArrayToPermissionRequest(typeArray, permArray);

    nsCOMPtr<nsIPrincipal> principal;
    rv = aRequest->GetPrincipal(getter_AddRefs(principal));
    NS_ENSURE_SUCCESS(rv, rv);

    nsCOMPtr<nsIPrincipal> topLevelPrincipal;
    rv = aRequest->GetTopLevelPrincipal(getter_AddRefs(topLevelPrincipal));
    NS_ENSURE_SUCCESS(rv, rv);

    bool hasValidTransientUserGestureActivation;
    rv = aRequest->GetHasValidTransientUserGestureActivation(
        &hasValidTransientUserGestureActivation);
    NS_ENSURE_SUCCESS(rv, rv);

    bool isRequestDelegatedToUnsafeThirdParty;
    rv = aRequest->GetIsRequestDelegatedToUnsafeThirdParty(
        &isRequestDelegatedToUnsafeThirdParty);
    NS_ENSURE_SUCCESS(rv, rv);

    req->IPDLAddRef();
    if (!ContentChild::GetSingleton()->SendPContentPermissionRequestConstructor(
            req, permArray, principal, topLevelPrincipal,
            hasValidTransientUserGestureActivation,
            isRequestDelegatedToUnsafeThirdParty, child->GetTabId())) {
      return NS_ERROR_FAILURE;
    }
    ContentPermissionRequestChildMap()[req.get()] = child->GetTabId();

    req->Sendprompt();
    return NS_OK;
  }

  // for chrome process
  nsCOMPtr<nsIContentPermissionPrompt> prompt =
      do_GetService(NS_CONTENT_PERMISSION_PROMPT_CONTRACTID);
  if (prompt) {
    if (NS_FAILED(prompt->Prompt(aRequest))) {
      return NS_ERROR_FAILURE;
    }
  }
  return NS_OK;
}

/* static */
nsTArray<PContentPermissionRequestParent*>
nsContentPermissionUtils::GetContentPermissionRequestParentById(
    const TabId& aTabId) {
  nsTArray<PContentPermissionRequestParent*> parentArray;
  for (auto& it : ContentPermissionRequestParentMap()) {
    if (it.second == aTabId) {
      parentArray.AppendElement(it.first);
    }
  }

  return parentArray;
}

/* static */
void nsContentPermissionUtils::NotifyRemoveContentPermissionRequestParent(
    PContentPermissionRequestParent* aParent) {
  auto it = ContentPermissionRequestParentMap().find(aParent);
  MOZ_ASSERT(it != ContentPermissionRequestParentMap().end());

  ContentPermissionRequestParentMap().erase(it);
}

/* static */
nsTArray<PContentPermissionRequestChild*>
nsContentPermissionUtils::GetContentPermissionRequestChildById(
    const TabId& aTabId) {
  nsTArray<PContentPermissionRequestChild*> childArray;
  for (auto& it : ContentPermissionRequestChildMap()) {
    if (it.second == aTabId) {
      childArray.AppendElement(it.first);
    }
  }

  return childArray;
}

/* static */
void nsContentPermissionUtils::NotifyRemoveContentPermissionRequestChild(
    PContentPermissionRequestChild* aChild) {
  auto it = ContentPermissionRequestChildMap().find(aChild);
  MOZ_ASSERT(it != ContentPermissionRequestChildMap().end());

  ContentPermissionRequestChildMap().erase(it);
}

static nsIPrincipal* GetTopLevelPrincipal(nsPIDOMWindowInner* aWindow) {
  MOZ_ASSERT(aWindow);

  BrowsingContext* top = aWindow->GetBrowsingContext()->Top();
  MOZ_ASSERT(top);

  nsPIDOMWindowOuter* outer = top->GetDOMWindow();
  if (!outer) {
    return nullptr;
  }

  nsPIDOMWindowInner* inner = outer->GetCurrentInnerWindow();
  if (!inner) {
    return nullptr;
  }

  return nsGlobalWindowInner::Cast(inner)->GetPrincipal();
}

NS_IMPL_CYCLE_COLLECTION(ContentPermissionRequestBase, mPrincipal,
                         mTopLevelPrincipal, mWindow)

NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ContentPermissionRequestBase)
  NS_INTERFACE_MAP_ENTRY_CONCRETE(nsISupports)
  NS_INTERFACE_MAP_ENTRY_CONCRETE(nsIContentPermissionRequest)
NS_INTERFACE_MAP_END

NS_IMPL_CYCLE_COLLECTING_ADDREF(ContentPermissionRequestBase)
NS_IMPL_CYCLE_COLLECTING_RELEASE(ContentPermissionRequestBase)

ContentPermissionRequestBase::ContentPermissionRequestBase(
    nsIPrincipal* aPrincipal, nsPIDOMWindowInner* aWindow,
    const nsACString& aPrefName, const nsACString& aType)
    : mPrincipal(aPrincipal),
      mTopLevelPrincipal(aWindow ? ::GetTopLevelPrincipal(aWindow) : nullptr),
      mWindow(aWindow),
      mPrefName(aPrefName),
      mType(aType),
      mHasValidTransientUserGestureActivation(false),
      mIsRequestDelegatedToUnsafeThirdParty(false) {
  if (!aWindow) {
    return;
  }

  Document* doc = aWindow->GetExtantDoc();
  if (!doc) {
    return;
  }

  mHasValidTransientUserGestureActivation =
      doc->HasValidTransientUserGestureActivation();

  mPermissionHandler = doc->GetPermissionDelegateHandler();
  if (mPermissionHandler) {
    nsTArray<nsCString> types;
    types.AppendElement(mType);
    mPermissionHandler->MaybeUnsafePermissionDelegate(
        types, &mIsRequestDelegatedToUnsafeThirdParty);
  }
}

NS_IMETHODIMP
ContentPermissionRequestBase::GetPrincipal(
    nsIPrincipal** aRequestingPrincipal) {
  NS_IF_ADDREF(*aRequestingPrincipal = mPrincipal);
  return NS_OK;
}

NS_IMETHODIMP
ContentPermissionRequestBase::GetDelegatePrincipal(
    const nsACString& aType, nsIPrincipal** aRequestingPrincipal) {
  return PermissionDelegateHandler::GetDelegatePrincipal(aType, this,
                                                         aRequestingPrincipal);
}

NS_IMETHODIMP
ContentPermissionRequestBase::GetIsRequestDelegatedToUnsafeThirdParty(
    bool* aIsRequestDelegatedToUnsafeThirdParty) {
  *aIsRequestDelegatedToUnsafeThirdParty =
      mIsRequestDelegatedToUnsafeThirdParty;
  return NS_OK;
}

NS_IMETHODIMP
ContentPermissionRequestBase::GetTopLevelPrincipal(
    nsIPrincipal** aRequestingPrincipal) {
  if (!mTopLevelPrincipal) {
    *aRequestingPrincipal = nullptr;
    return NS_OK;
  }

  NS_IF_ADDREF(*aRequestingPrincipal = mTopLevelPrincipal);
  return NS_OK;
}

NS_IMETHODIMP
ContentPermissionRequestBase::GetWindow(mozIDOMWindow** aRequestingWindow) {
  NS_IF_ADDREF(*aRequestingWindow = mWindow);
  return NS_OK;
}

NS_IMETHODIMP
ContentPermissionRequestBase::GetElement(Element** aElement) {
  NS_ENSURE_ARG_POINTER(aElement);
  *aElement = nullptr;
  return NS_OK;
}

NS_IMETHODIMP
ContentPermissionRequestBase::GetHasValidTransientUserGestureActivation(
    bool* aHasValidTransientUserGestureActivation) {
  *aHasValidTransientUserGestureActivation =
      mHasValidTransientUserGestureActivation;
  return NS_OK;
}

NS_IMETHODIMP
ContentPermissionRequestBase::GetTypes(nsIArray** aTypes) {
  nsTArray<nsString> emptyOptions;
  return nsContentPermissionUtils::CreatePermissionArray(mType, emptyOptions,
                                                         aTypes);
}

ContentPermissionRequestBase::PromptResult
ContentPermissionRequestBase::CheckPromptPrefs() const {
  MOZ_ASSERT(!mPrefName.IsEmpty(),
             "This derived class must support checking pref types");

  nsAutoCString prefName(mPrefName);
  prefName.AppendLiteral(".prompt.testing");
  if (Preferences::GetBool(PromiseFlatCString(prefName).get(), false)) {
    prefName.AppendLiteral(".allow");
    if (Preferences::GetBool(PromiseFlatCString(prefName).get(), true)) {
      return PromptResult::Granted;
    }
    return PromptResult::Denied;
  }

  return PromptResult::Pending;
}

bool ContentPermissionRequestBase::CheckPermissionDelegate() const {
  // There is case that ContentPermissionRequestBase is constructed without
  // window, then mPermissionHandler will be null. So we only check permission
  // delegate if we have non-null mPermissionHandler
  if (mPermissionHandler &&
      !mPermissionHandler->HasPermissionDelegated(mType)) {
    return false;
  }

  return true;
}

nsresult ContentPermissionRequestBase::ShowPrompt(
    ContentPermissionRequestBase::PromptResult& aResult) {
  if (!CheckPermissionDelegate()) {
    aResult = PromptResult::Denied;
    return NS_OK;
  }

  aResult = CheckPromptPrefs();

  if (aResult != PromptResult::Pending) {
    return NS_OK;
  }

  return nsContentPermissionUtils::AskPermission(this, mWindow);
}

class RequestPromptEvent : public Runnable {
 public:
  RequestPromptEvent(ContentPermissionRequestBase* aRequest,
                     nsPIDOMWindowInner* aWindow)
      : mozilla::Runnable("RequestPromptEvent"),
        mRequest(aRequest),
        mWindow(aWindow) {}

  NS_IMETHOD Run() override {
    nsContentPermissionUtils::AskPermission(mRequest, mWindow);
    return NS_OK;
  }

 private:
  RefPtr<ContentPermissionRequestBase> mRequest;
  nsCOMPtr<nsPIDOMWindowInner> mWindow;
};

class RequestAllowEvent : public Runnable {
 public:
  RequestAllowEvent(bool allow, ContentPermissionRequestBase* request)
      : mozilla::Runnable("RequestAllowEvent"),
        mAllow(allow),
        mRequest(request) {}

  // Not MOZ_CAN_RUN_SCRIPT because we can't annotate the thing we override yet.
  MOZ_CAN_RUN_SCRIPT_BOUNDARY
  NS_IMETHOD Run() override {
    // MOZ_KnownLive is OK, because we never drop the ref to mRequest.
    if (mAllow) {
      MOZ_KnownLive(mRequest)->Allow(JS::UndefinedHandleValue);
    } else {
      MOZ_KnownLive(mRequest)->Cancel();
    }
    return NS_OK;
  }

 private:
  bool mAllow;
  RefPtr<ContentPermissionRequestBase> mRequest;
};

void ContentPermissionRequestBase::RequestDelayedTask(
    nsIEventTarget* aTarget,
    ContentPermissionRequestBase::DelayedTaskType aType) {
  nsCOMPtr<nsIRunnable> r;
  switch (aType) {
    case DelayedTaskType::Allow:
      r = new RequestAllowEvent(truethis);
      break;
    case DelayedTaskType::Deny:
      r = new RequestAllowEvent(falsethis);
      break;
    default:
      r = new RequestPromptEvent(this, mWindow);
      break;
  }

  aTarget->Dispatch(r.forget());
}

nsresult TranslateChoices(
    JS::Handle<JS::Value> aChoices,
    const nsTArray<PermissionRequest>& aPermissionRequests,
    nsTArray<PermissionChoice>& aTranslatedChoices) {
  if (aChoices.isNullOrUndefined()) {
    // No choice is specified.
  } else if (aChoices.isObject()) {
    // Iterate through all permission types.
    for (uint32_t i = 0; i < aPermissionRequests.Length(); ++i) {
      nsCString type = aPermissionRequests[i].type();

      JS::Rooted<JSObject*> obj(RootingCx(), &aChoices.toObject());
      // People really shouldn't be passing WindowProxy or Location
      // objects for the choices here.
      obj = js::CheckedUnwrapStatic(obj);
      if (!obj) {
        return NS_ERROR_FAILURE;
      }

      AutoJSAPI jsapi;
      jsapi.Init();

      JSContext* cx = jsapi.cx();
      JSAutoRealm ar(cx, obj);

      JS::Rooted<JS::Value> val(cx);

      if (!JS_GetProperty(cx, obj, type.BeginReading(), &val) ||
          !val.isString()) {
        // no setting for the permission type, clear exception and skip it
        jsapi.ClearException();
      } else {
        nsAutoJSString choice;
        if (!choice.init(cx, val)) {
          jsapi.ClearException();
          return NS_ERROR_FAILURE;
        }
        aTranslatedChoices.AppendElement(PermissionChoice(type, choice));
      }
    }
  } else {
    MOZ_ASSERT(false"SelectedChoices should be undefined or an JS object");
    return NS_ERROR_FAILURE;
  }

  return NS_OK;
}

}  // namespace mozilla::dom

nsContentPermissionRequestProxy::nsContentPermissionRequestProxy(
    ContentPermissionRequestParent* parent)
    : mParent(parent) {
  NS_ASSERTION(mParent, "null parent");
}

nsContentPermissionRequestProxy::~nsContentPermissionRequestProxy() = default;

nsresult nsContentPermissionRequestProxy::Init(
    const nsTArray<PermissionRequest>& requests) {
  mPermissionRequests = requests.Clone();

  nsCOMPtr<nsIContentPermissionPrompt> prompt =
      do_GetService(NS_CONTENT_PERMISSION_PROMPT_CONTRACTID);
  if (!prompt) {
    return NS_ERROR_FAILURE;
  }

  prompt->Prompt(this);
  return NS_OK;
}

void nsContentPermissionRequestProxy::OnParentDestroyed() { mParent = nullptr; }

NS_IMPL_ISUPPORTS(nsContentPermissionRequestProxy, nsIContentPermissionRequest)

NS_IMETHODIMP
nsContentPermissionRequestProxy::GetTypes(nsIArray** aTypes) {
  nsCOMPtr<nsIMutableArray> types = do_CreateInstance(NS_ARRAY_CONTRACTID);
  if (mozilla::dom::nsContentPermissionUtils::ConvertPermissionRequestToArray(
          mPermissionRequests, types)) {
    types.forget(aTypes);
    return NS_OK;
  }
  return NS_ERROR_FAILURE;
}

NS_IMETHODIMP
nsContentPermissionRequestProxy::GetWindow(mozIDOMWindow** aRequestingWindow) {
  NS_ENSURE_ARG_POINTER(aRequestingWindow);
  *aRequestingWindow = nullptr;  // ipc doesn't have a window
  return NS_OK;
}

NS_IMETHODIMP
nsContentPermissionRequestProxy::GetPrincipal(
    nsIPrincipal** aRequestingPrincipal) {
  NS_ENSURE_ARG_POINTER(aRequestingPrincipal);
  if (mParent == nullptr) {
    return NS_ERROR_FAILURE;
  }

  NS_IF_ADDREF(*aRequestingPrincipal = mParent->mPrincipal);
  return NS_OK;
}

NS_IMETHODIMP
nsContentPermissionRequestProxy::GetTopLevelPrincipal(
    nsIPrincipal** aRequestingPrincipal) {
  NS_ENSURE_ARG_POINTER(aRequestingPrincipal);
  if (mParent == nullptr) {
    return NS_ERROR_FAILURE;
  }

  NS_IF_ADDREF(*aRequestingPrincipal = mParent->mTopLevelPrincipal);
  return NS_OK;
}

NS_IMETHODIMP
nsContentPermissionRequestProxy::GetDelegatePrincipal(
    const nsACString& aType, nsIPrincipal** aRequestingPrincipal) {
  NS_ENSURE_ARG_POINTER(aRequestingPrincipal);
  if (mParent == nullptr) {
    return NS_ERROR_FAILURE;
  }

  return PermissionDelegateHandler::GetDelegatePrincipal(aType, this,
                                                         aRequestingPrincipal);
}

NS_IMETHODIMP
nsContentPermissionRequestProxy::GetElement(Element** aRequestingElement) {
  NS_ENSURE_ARG_POINTER(aRequestingElement);
  if (mParent == nullptr) {
    return NS_ERROR_FAILURE;
  }

  nsCOMPtr<Element> elem = mParent->mElement;
  elem.forget(aRequestingElement);
  return NS_OK;
}

NS_IMETHODIMP
nsContentPermissionRequestProxy::GetHasValidTransientUserGestureActivation(
    bool* aHasValidTransientUserGestureActivation) {
  NS_ENSURE_ARG_POINTER(aHasValidTransientUserGestureActivation);
  if (mParent == nullptr) {
    return NS_ERROR_FAILURE;
  }
  *aHasValidTransientUserGestureActivation =
      mParent->mHasValidTransientUserGestureActivation;
  return NS_OK;
}

NS_IMETHODIMP
nsContentPermissionRequestProxy::GetIsRequestDelegatedToUnsafeThirdParty(
    bool* aIsRequestDelegatedToUnsafeThirdParty) {
  NS_ENSURE_ARG_POINTER(aIsRequestDelegatedToUnsafeThirdParty);
  if (mParent == nullptr) {
    return NS_ERROR_FAILURE;
  }
  *aIsRequestDelegatedToUnsafeThirdParty =
      mParent->mIsRequestDelegatedToUnsafeThirdParty;
  return NS_OK;
}

NS_IMETHODIMP
nsContentPermissionRequestProxy::Cancel() {
  if (mParent == nullptr) {
    return NS_ERROR_FAILURE;
  }

  // Don't send out the delete message when the managing protocol (PBrowser) is
  // being destroyed and PContentPermissionRequest will soon be.
  if (mParent->IsBeingDestroyed()) {
    return NS_ERROR_FAILURE;
  }

  nsTArray<PermissionChoice> emptyChoices;

  Unused << mParent->SendNotifyResult(false, emptyChoices);
  return NS_OK;
}

NS_IMETHODIMP
nsContentPermissionRequestProxy::Allow(JS::Handle<JS::Value> aChoices) {
  if (mParent == nullptr) {
    return NS_ERROR_FAILURE;
  }

  // Don't send out the delete message when the managing protocol (PBrowser) is
  // being destroyed and PContentPermissionRequest will soon be.
  if (mParent->IsBeingDestroyed()) {
    return NS_ERROR_FAILURE;
  }

  nsTArray<PermissionChoice> choices;
  nsresult rv = TranslateChoices(aChoices, mPermissionRequests, choices);
  if (NS_FAILED(rv)) {
    return rv;
  }

  Unused << mParent->SendNotifyResult(true, choices);
  return NS_OK;
}

// RemotePermissionRequest

RemotePermissionRequest::RemotePermissionRequest(
    nsIContentPermissionRequest* aRequest, nsPIDOMWindowInner* aWindow)
    : mRequest(aRequest),
      mWindow(aWindow),
      mIPCOpen(false),
      mDestroyed(false) {}

RemotePermissionRequest::~RemotePermissionRequest() {
  MOZ_ASSERT(
      !mIPCOpen,
      "Protocol must not be open when RemotePermissionRequest is destroyed.");
}

void RemotePermissionRequest::DoCancel() {
  NS_ASSERTION(mRequest, "We need a request");
  nsCOMPtr<nsIContentPermissionRequest> request(mRequest);
  request->Cancel();
}

void RemotePermissionRequest::DoAllow(JS::Handle<JS::Value> aChoices) {
  NS_ASSERTION(mRequest, "We need a request");
  nsCOMPtr<nsIContentPermissionRequest> request(mRequest);
  request->Allow(aChoices);
}

// PContentPermissionRequestChild
mozilla::ipc::IPCResult RemotePermissionRequest::RecvNotifyResult(
    const bool& aAllow, nsTArray<PermissionChoice>&& aChoices) {
  Destroy();

  if (aAllow && mWindow->IsCurrentInnerWindow()) {
    // Use 'undefined' if no choice is provided.
    if (aChoices.IsEmpty()) {
      DoAllow(JS::UndefinedHandleValue);
      return IPC_OK();
    }

    // Convert choices to a JS val if any.
    // {"type1": "choice1", "type2": "choiceA"}
    AutoJSAPI jsapi;
    if (NS_WARN_IF(!jsapi.Init(mWindow))) {
      return IPC_OK();  // This is not an IPC error.
    }

    JSContext* cx = jsapi.cx();
    JS::Rooted<JSObject*> obj(cx);
    obj = JS_NewPlainObject(cx);
    for (uint32_t i = 0; i < aChoices.Length(); ++i) {
      const nsString& choice = aChoices[i].choice();
      const nsCString& type = aChoices[i].type();
      JS::Rooted<JSString*> jChoice(
          cx, JS_NewUCStringCopyN(cx, choice.get(), choice.Length()));
      JS::Rooted<JS::Value> vChoice(cx, StringValue(jChoice));
      if (!JS_SetProperty(cx, obj, type.get(), vChoice)) {
        return IPC_FAIL_NO_REASON(this);
      }
    }
    JS::Rooted<JS::Value> val(cx, JS::ObjectValue(*obj));
    DoAllow(val);
  } else {
    DoCancel();
  }
  return IPC_OK();
}

void RemotePermissionRequest::Destroy() {
  if (!IPCOpen()) {
    return;
  }
  Unused << this->SendDestroy();
  mDestroyed = true;
}

94%


¤ Dauer der Verarbeitung: 0.18 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung ist noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge