1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:set ts=2 sw=2 sts=2 et cindent: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7 #include "mozilla/dom/MIDIPermissionRequest.h"
8 #include "mozilla/dom/MIDIAccessManager.h"
9 #include "nsIGlobalObject.h"
10 #include "mozilla/Preferences.h"
11 #include "nsContentUtils.h"
12
13 //-------------------------------------------------
14 // MIDI Permission Requests
15 //-------------------------------------------------
16
NS_IMPL_CYCLE_COLLECTION(MIDIPermissionRequest,mWindow,mPromise)17 NS_IMPL_CYCLE_COLLECTION(MIDIPermissionRequest, mWindow, mPromise)
18
19 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(MIDIPermissionRequest)
20 NS_INTERFACE_MAP_ENTRY(nsIContentPermissionRequest)
21 NS_INTERFACE_MAP_ENTRY(nsIRunnable)
22 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIContentPermissionRequest)
23 NS_INTERFACE_MAP_END
24
25 NS_IMPL_CYCLE_COLLECTING_ADDREF(MIDIPermissionRequest)
26 NS_IMPL_CYCLE_COLLECTING_RELEASE(MIDIPermissionRequest)
27
28 MIDIPermissionRequest::MIDIPermissionRequest(nsPIDOMWindowInner* aWindow,
29 Promise* aPromise,
30 const MIDIOptions& aOptions)
31 : mWindow(aWindow),
32 mPromise(aPromise),
33 mNeedsSysex(aOptions.mSysex),
34 mRequester(new nsContentPermissionRequester(mWindow)) {
35 MOZ_ASSERT(aWindow);
36 MOZ_ASSERT(aPromise, "aPromise should not be null!");
37 MOZ_ASSERT(aWindow->GetDoc());
38 mPrincipal = aWindow->GetDoc()->NodePrincipal();
39 MOZ_ASSERT(mPrincipal);
40 }
41
~MIDIPermissionRequest()42 MIDIPermissionRequest::~MIDIPermissionRequest() {}
43
44 NS_IMETHODIMP
GetIsHandlingUserInput(bool * aHandlingInput)45 MIDIPermissionRequest::GetIsHandlingUserInput(bool* aHandlingInput) {
46 *aHandlingInput = true;
47 return NS_OK;
48 }
49
50 NS_IMETHODIMP
GetRequester(nsIContentPermissionRequester ** aRequester)51 MIDIPermissionRequest::GetRequester(
52 nsIContentPermissionRequester** aRequester) {
53 NS_ENSURE_ARG_POINTER(aRequester);
54 nsCOMPtr<nsIContentPermissionRequester> requester = mRequester;
55 requester.forget(aRequester);
56 return NS_OK;
57 }
58
59 NS_IMETHODIMP
GetTypes(nsIArray ** aTypes)60 MIDIPermissionRequest::GetTypes(nsIArray** aTypes) {
61 NS_ENSURE_ARG_POINTER(aTypes);
62 nsTArray<nsString> options;
63 if (mNeedsSysex) {
64 options.AppendElement(NS_LITERAL_STRING("sysex"));
65 }
66 return nsContentPermissionUtils::CreatePermissionArray(
67 NS_LITERAL_CSTRING("midi"), NS_LITERAL_CSTRING("unused"), options,
68 aTypes);
69 }
70
71 NS_IMETHODIMP
GetPrincipal(nsIPrincipal ** aRequestingPrincipal)72 MIDIPermissionRequest::GetPrincipal(nsIPrincipal** aRequestingPrincipal) {
73 NS_ENSURE_ARG_POINTER(aRequestingPrincipal);
74 NS_IF_ADDREF(*aRequestingPrincipal = mPrincipal);
75 return NS_OK;
76 }
77
78 NS_IMETHODIMP
GetWindow(mozIDOMWindow ** aRequestingWindow)79 MIDIPermissionRequest::GetWindow(mozIDOMWindow** aRequestingWindow) {
80 NS_ENSURE_ARG_POINTER(aRequestingWindow);
81 NS_IF_ADDREF(*aRequestingWindow = mWindow);
82 return NS_OK;
83 }
84
85 NS_IMETHODIMP
GetElement(nsIDOMElement ** aRequestingElement)86 MIDIPermissionRequest::GetElement(nsIDOMElement** aRequestingElement) {
87 NS_ENSURE_ARG_POINTER(aRequestingElement);
88 *aRequestingElement = nullptr;
89 return NS_OK;
90 }
91
92 NS_IMETHODIMP
Cancel()93 MIDIPermissionRequest::Cancel() {
94 mPromise->MaybeReject(NS_ERROR_DOM_SECURITY_ERR);
95 return NS_OK;
96 }
97
98 NS_IMETHODIMP
Allow(JS::HandleValue aChoices)99 MIDIPermissionRequest::Allow(JS::HandleValue aChoices) {
100 MOZ_ASSERT(aChoices.isUndefined());
101 MIDIAccessManager* mgr = MIDIAccessManager::Get();
102 mgr->CreateMIDIAccess(mWindow, mNeedsSysex, mPromise);
103 return NS_OK;
104 }
105
106 NS_IMETHODIMP
Run()107 MIDIPermissionRequest::Run() {
108 // If the testing flag is true, skip dialog
109 if (Preferences::GetBool("midi.prompt.testing", false)) {
110 bool allow =
111 Preferences::GetBool("media.navigator.permission.disabled", false);
112 if (allow) {
113 Allow(JS::UndefinedHandleValue);
114 } else {
115 Cancel();
116 }
117 return NS_OK;
118 }
119
120 // If we already have sysex perms, allow.
121 if (nsContentUtils::IsExactSitePermAllow(mPrincipal, "midi-sysex")) {
122 Allow(JS::UndefinedHandleValue);
123 return NS_OK;
124 }
125
126 // If we have no perms, or only have midi and are asking for sysex, pop dialog
127 if (NS_FAILED(nsContentPermissionUtils::AskPermission(this, mWindow))) {
128 Cancel();
129 return NS_ERROR_FAILURE;
130 }
131 return NS_OK;
132 }
133