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/Document.h"
9 #include "mozilla/dom/MIDIAccessManager.h"
10 #include "mozilla/dom/MIDIOptionsBinding.h"
11 #include "nsIGlobalObject.h"
12 #include "mozilla/Preferences.h"
13 #include "nsContentUtils.h"
14 
15 //-------------------------------------------------
16 // MIDI Permission Requests
17 //-------------------------------------------------
18 
19 using namespace mozilla::dom;
20 
NS_IMPL_CYCLE_COLLECTION_INHERITED(MIDIPermissionRequest,ContentPermissionRequestBase,mPromise)21 NS_IMPL_CYCLE_COLLECTION_INHERITED(MIDIPermissionRequest,
22                                    ContentPermissionRequestBase, mPromise)
23 
24 NS_IMPL_QUERY_INTERFACE_CYCLE_COLLECTION_INHERITED(MIDIPermissionRequest,
25                                                    ContentPermissionRequestBase,
26                                                    nsIRunnable)
27 
28 NS_IMPL_ADDREF_INHERITED(MIDIPermissionRequest, ContentPermissionRequestBase)
29 NS_IMPL_RELEASE_INHERITED(MIDIPermissionRequest, ContentPermissionRequestBase)
30 
31 MIDIPermissionRequest::MIDIPermissionRequest(nsPIDOMWindowInner* aWindow,
32                                              Promise* aPromise,
33                                              const MIDIOptions& aOptions)
34     : ContentPermissionRequestBase(
35           aWindow->GetDoc()->NodePrincipal(), aWindow,
36           ""_ns,  // We check prefs in a custom way here
37           "midi"_ns),
38       mPromise(aPromise),
39       mNeedsSysex(aOptions.mSysex) {
40   MOZ_ASSERT(aWindow);
41   MOZ_ASSERT(aPromise, "aPromise should not be null!");
42   MOZ_ASSERT(aWindow->GetDoc());
43   mPrincipal = aWindow->GetDoc()->NodePrincipal();
44   MOZ_ASSERT(mPrincipal);
45 }
46 
47 NS_IMETHODIMP
GetTypes(nsIArray ** aTypes)48 MIDIPermissionRequest::GetTypes(nsIArray** aTypes) {
49   NS_ENSURE_ARG_POINTER(aTypes);
50   nsTArray<nsString> options;
51   if (mNeedsSysex) {
52     options.AppendElement(u"sysex"_ns);
53   }
54   return nsContentPermissionUtils::CreatePermissionArray(mType, options,
55                                                          aTypes);
56 }
57 
58 NS_IMETHODIMP
Cancel()59 MIDIPermissionRequest::Cancel() {
60   mPromise->MaybeReject(NS_ERROR_DOM_SECURITY_ERR);
61   return NS_OK;
62 }
63 
64 NS_IMETHODIMP
Allow(JS::HandleValue aChoices)65 MIDIPermissionRequest::Allow(JS::HandleValue aChoices) {
66   MOZ_ASSERT(aChoices.isUndefined());
67   MIDIAccessManager* mgr = MIDIAccessManager::Get();
68   mgr->CreateMIDIAccess(mWindow, mNeedsSysex, mPromise);
69   return NS_OK;
70 }
71 
72 NS_IMETHODIMP
Run()73 MIDIPermissionRequest::Run() {
74   // If the testing flag is true, skip dialog
75   if (Preferences::GetBool("midi.prompt.testing", false)) {
76     bool allow =
77         Preferences::GetBool("media.navigator.permission.disabled", false);
78     if (allow) {
79       Allow(JS::UndefinedHandleValue);
80     } else {
81       Cancel();
82     }
83     return NS_OK;
84   }
85 
86   // If we already have sysex perms, allow.
87   if (nsContentUtils::IsExactSitePermAllow(mPrincipal, "midi-sysex"_ns)) {
88     Allow(JS::UndefinedHandleValue);
89     return NS_OK;
90   }
91 
92   // If we have no perms, or only have midi and are asking for sysex, pop dialog
93   if (NS_FAILED(nsContentPermissionUtils::AskPermission(this, mWindow))) {
94     Cancel();
95     return NS_ERROR_FAILURE;
96   }
97   return NS_OK;
98 }
99