This commit is contained in:
Ryan VanderMeulen 2015-04-08 13:09:36 -04:00
Родитель 22a9074ce7 75871f42cb
Коммит edb7f6086e
333 изменённых файлов: 5591 добавлений и 3002 удалений

Просмотреть файл

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="ef937d1aca7c4cf89ecb5cc43ae8c21c2000a9db">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="84cbd4391fb7175d5380fa72c04d68873ce77e6d"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="a290b11627ec2b7c25980f5687a98da86641cfe4"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2aa4a75c63cd6e93870a8bddbba45f863cbfd9a3"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
@ -128,7 +128,7 @@
<!-- Stock Android things -->
<project name="platform/external/icu4c" path="external/icu4c" revision="2bb01561780583cc37bc667f0ea79f48a122d8a2"/>
<!-- dolphin specific things -->
<project name="device/sprd" path="device/sprd" revision="1eb575040af22c58a16f90ecd04b6e1ebdee5c80"/>
<project name="device/sprd" path="device/sprd" revision="a26ba0ab998133ad590102be1e5950818b86ce82"/>
<project name="platform/external/wpa_supplicant_8" path="external/wpa_supplicant_8" revision="2ea7f18a7bc45e16cb97a835dc86ee64d2d6b0b3"/>
<project name="platform/frameworks/av" path="frameworks/av" revision="fd359e3a74a658d9eaab1c683440ba5412535777"/>
<project name="platform/hardware/akm" path="hardware/akm" revision="6d3be412647b0eab0adff8a2768736cf4eb68039"/>

Просмотреть файл

@ -19,11 +19,11 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="84cbd4391fb7175d5380fa72c04d68873ce77e6d"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="a290b11627ec2b7c25980f5687a98da86641cfe4"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2aa4a75c63cd6e93870a8bddbba45f863cbfd9a3"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="93f9ba577f68d772093987c2f1c0a4ae293e1802"/>
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="3b3407510d6e2c60242e8b9b5f2bc1783ca0a0e4"/>
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="a89cebcccc1e067ebdb71a93194f4ee79d71bd69"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="ed2cf97a6c37a4bbd0bbbbffe06ec7136d8c79ff"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="34ea6163f9f0e0122fb0bb03607eccdca31ced7a"/>
<!-- Stock Android things -->

Просмотреть файл

@ -17,7 +17,7 @@
</project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="84cbd4391fb7175d5380fa72c04d68873ce77e6d"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="a290b11627ec2b7c25980f5687a98da86641cfe4"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2aa4a75c63cd6e93870a8bddbba45f863cbfd9a3"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="ed2cf97a6c37a4bbd0bbbbffe06ec7136d8c79ff"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="1b1d86462d3150dceacff927536ded9fcc168419"/>

Просмотреть файл

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="ef937d1aca7c4cf89ecb5cc43ae8c21c2000a9db">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="84cbd4391fb7175d5380fa72c04d68873ce77e6d"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="a290b11627ec2b7c25980f5687a98da86641cfe4"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2aa4a75c63cd6e93870a8bddbba45f863cbfd9a3"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
@ -131,7 +131,7 @@
<project name="device_generic_goldfish" path="device/generic/goldfish" remote="b2g" revision="f5f7fa2fc26b96d2cbd0af4569c0036fe034bb43"/>
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="fbd2becab3825c49e756db5149552f85049c66e2"/>
<project name="platform/external/wpa_supplicant_8" path="external/wpa_supplicant_8" revision="694cecf256122d0cb3b6a1a4efb4b5c7401db223"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="f810abaa47932079396ea3815df65fbdd83b1f94"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="c0bf1eec60644abbc5e72c251c15092b4c71b6a9"/>
<project name="platform/development" path="development" revision="5968ff4e13e0d696ad8d972281fc27ae5a12829b"/>
<project name="android-sdk" path="sdk" remote="b2g" revision="0951179277915335251c5e11d242e4e1a8c2236f"/>
<project name="darwinstreamingserver" path="system/darwinstreamingserver" remote="b2g" revision="cf85968c7f85e0ec36e72c87ceb4837a943b8af6"/>

Просмотреть файл

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="52775e03a2d8532429dff579cb2cd56718e488c3">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="84cbd4391fb7175d5380fa72c04d68873ce77e6d"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="a290b11627ec2b7c25980f5687a98da86641cfe4"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2aa4a75c63cd6e93870a8bddbba45f863cbfd9a3"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

Просмотреть файл

@ -19,11 +19,11 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="84cbd4391fb7175d5380fa72c04d68873ce77e6d"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="a290b11627ec2b7c25980f5687a98da86641cfe4"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2aa4a75c63cd6e93870a8bddbba45f863cbfd9a3"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="93f9ba577f68d772093987c2f1c0a4ae293e1802"/>
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="3b3407510d6e2c60242e8b9b5f2bc1783ca0a0e4"/>
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="a89cebcccc1e067ebdb71a93194f4ee79d71bd69"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="ed2cf97a6c37a4bbd0bbbbffe06ec7136d8c79ff"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="34ea6163f9f0e0122fb0bb03607eccdca31ced7a"/>
<!-- Stock Android things -->

Просмотреть файл

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="ef937d1aca7c4cf89ecb5cc43ae8c21c2000a9db">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="84cbd4391fb7175d5380fa72c04d68873ce77e6d"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="a290b11627ec2b7c25980f5687a98da86641cfe4"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2aa4a75c63cd6e93870a8bddbba45f863cbfd9a3"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

Просмотреть файл

@ -17,7 +17,7 @@
</project>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="84cbd4391fb7175d5380fa72c04d68873ce77e6d"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="a290b11627ec2b7c25980f5687a98da86641cfe4"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2aa4a75c63cd6e93870a8bddbba45f863cbfd9a3"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="ed2cf97a6c37a4bbd0bbbbffe06ec7136d8c79ff"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="1b1d86462d3150dceacff927536ded9fcc168419"/>

Просмотреть файл

@ -1,9 +1,9 @@
{
"git": {
"git_revision": "84cbd4391fb7175d5380fa72c04d68873ce77e6d",
"git_revision": "a290b11627ec2b7c25980f5687a98da86641cfe4",
"remote": "https://git.mozilla.org/releases/gaia.git",
"branch": ""
},
"revision": "a7d22a159f8c412c7d8ebb371025b17563265c06",
"revision": "dbc540265f837510772bbcfdc7e9181b280b2551",
"repo_path": "integration/gaia-central"
}

Просмотреть файл

@ -17,7 +17,7 @@
</project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="84cbd4391fb7175d5380fa72c04d68873ce77e6d"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="a290b11627ec2b7c25980f5687a98da86641cfe4"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2aa4a75c63cd6e93870a8bddbba45f863cbfd9a3"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="ed2cf97a6c37a4bbd0bbbbffe06ec7136d8c79ff"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="1b1d86462d3150dceacff927536ded9fcc168419"/>

Просмотреть файл

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="52775e03a2d8532429dff579cb2cd56718e488c3">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="84cbd4391fb7175d5380fa72c04d68873ce77e6d"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="a290b11627ec2b7c25980f5687a98da86641cfe4"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2aa4a75c63cd6e93870a8bddbba45f863cbfd9a3"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

Просмотреть файл

@ -250,6 +250,7 @@ skip-if = e10s # Bug 653065 - Make the lightweight theme web installer ready for
[browser_bug597218.js]
[browser_bug609700.js]
[browser_bug623155.js]
skip-if = e10s && debug
[browser_bug623893.js]
[browser_bug624734.js]
[browser_bug633691.js]
@ -369,6 +370,7 @@ skip-if = e10s # Bug 1093155 - tries to use context menu from browser-chrome and
[browser_popupUI.js]
skip-if = buildapp == 'mulet' || e10s # Bug 1100707 - test fails in e10s because it can't get accel-w to close the popup (?)
[browser_popup_blocker.js]
skip-if = e10s && debug # Frequent bug 1125520 failures
[browser_printpreview.js]
skip-if = buildapp == 'mulet' || e10s # Bug 1101973 - breaks the next test in e10s, and may be responsible for later timeout after logging "Error: Channel closing: too late to send/recv, messages will be lost"
[browser_private_browsing_window.js]
@ -428,6 +430,7 @@ skip-if = buildapp == 'mulet'
skip-if = os == "linux" || os == "mac" # No tabs in titlebar on linux
# Disabled on OS X because of bug 967917
[browser_tabfocus.js]
skip-if = e10s && debug # Bug 907326
[browser_tabkeynavigation.js]
skip-if = e10s
[browser_tabopen_reflows.js]

Просмотреть файл

@ -61,6 +61,7 @@ skip-if = !crashreporter
[browser_CTP_drag_drop.js]
[browser_CTP_hide_overlay.js]
[browser_CTP_iframe.js]
skip-if = os == 'linux' || os == 'mac' # Bug 984821
[browser_CTP_multi_allow.js]
[browser_CTP_nonplugins.js]
[browser_CTP_notificationBar.js]

Просмотреть файл

@ -97,7 +97,15 @@ AudioChannelAgent::InitInternal(nsIDOMWindow* aWindow, int32_t aChannelType,
return NS_ERROR_FAILURE;
}
mWindow = aWindow;
if (aWindow) {
nsCOMPtr<nsPIDOMWindow> pWindow = do_QueryInterface(aWindow);
if (!pWindow->IsInnerWindow()) {
pWindow = pWindow->GetCurrentInnerWindow();
}
mWindow = pWindow.forget();
}
mAudioChannelType = aChannelType;
if (aUseWeakRef) {

Просмотреть файл

@ -37,6 +37,19 @@ using namespace mozilla;
using namespace mozilla::dom;
using namespace mozilla::hal;
// When a inner-window is destroyed we have to mute all the related
// AudioChannelAgents. In order to do this we have to notify them after purging
// AudioChannelService::mAgents.
struct MOZ_STACK_CLASS WindowDestroyedEnumeratorData
{
explicit WindowDestroyedEnumeratorData(uint64_t aInnerID)
: mInnerID(aInnerID)
{}
nsTArray<nsRefPtr<AudioChannelAgent>> mAgents;
uint64_t mInnerID;
};
StaticRefPtr<AudioChannelService> gAudioChannelService;
// Mappings from 'mozaudiochannel' attribute strings to an enumeration.
@ -775,11 +788,15 @@ AudioChannelService::WindowDestroyedEnumerator(AudioChannelAgent* aAgent,
nsAutoPtr<AudioChannelAgentData>& aData,
void* aPtr)
{
uint64_t* innerID = static_cast<uint64_t*>(aPtr);
MOZ_ASSERT(innerID);
auto* data = static_cast<WindowDestroyedEnumeratorData*>(aPtr);
MOZ_ASSERT(data);
nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aAgent->Window());
if (!window || window->WindowID() != *innerID) {
if (!window->IsInnerWindow()) {
window = window->GetCurrentInnerWindow();
}
if (!window || window->WindowID() != data->mInnerID) {
return PL_DHASH_NEXT;
}
@ -788,6 +805,7 @@ AudioChannelService::WindowDestroyedEnumerator(AudioChannelAgent* aAgent,
service->UnregisterType(aData->mChannel, aData->mElementHidden,
CONTENT_PROCESS_ID_MAIN, aData->mWithVideo);
data->mAgents.AppendElement(aAgent);
return PL_DHASH_REMOVE;
}
@ -893,7 +911,11 @@ AudioChannelService::Observe(nsISupports* aSubject, const char* aTopic, const ch
return rv;
}
mAgents.Enumerate(WindowDestroyedEnumerator, &innerID);
WindowDestroyedEnumeratorData data(innerID);
mAgents.Enumerate(WindowDestroyedEnumerator, &data);
for (uint32_t i = 0, len = data.mAgents.Length(); i < len; ++i) {
data.mAgents[i]->NotifyAudioChannelStateChanged();
}
#ifdef MOZ_WIDGET_GONK
bool active = AnyAudioChannelIsActive();

Просмотреть файл

@ -226,6 +226,7 @@
#include "nsLocation.h"
#include "mozilla/dom/FontFaceSet.h"
#include "mozilla/dom/BoxObject.h"
#include "gfxVR.h"
#ifdef MOZ_MEDIA_NAVIGATOR
#include "mozilla/MediaManager.h"
@ -11375,6 +11376,10 @@ nsDocument::IsFullScreenDoc()
return GetFullScreenElement() != nullptr;
}
FullScreenOptions::FullScreenOptions()
{
}
class nsCallRequestFullScreen : public nsRunnable
{
public:

Просмотреть файл

@ -1929,9 +1929,13 @@ nsFocusManager::Focus(nsPIDOMWindow* aWindow,
}
}
nsPresContext* presContext = presShell->GetPresContext();
IMEStateManager::OnChangeFocus(presContext, nullptr,
GetFocusMoveActionCause(aFlags));
if (!mFocusedContent) {
// When there is no focused content, IMEStateManager needs to adjust IME
// enabled state with the document.
nsPresContext* presContext = presShell->GetPresContext();
IMEStateManager::OnChangeFocus(presContext, nullptr,
GetFocusMoveActionCause(aFlags));
}
if (!aWindowRaised)
aWindow->UpdateCommands(NS_LITERAL_STRING("focus"), nullptr, 0);

Просмотреть файл

@ -29,7 +29,6 @@
#include "nsExpirationTracker.h"
#include "nsClassHashtable.h"
#include "prclist.h"
#include "gfxVR.h"
class imgIRequest;
class nsAString;
@ -97,6 +96,10 @@ class Loader;
class ImageLoader;
} // namespace css
namespace gfx {
class VRHMDInfo;
} // namespace gfx
namespace dom {
class AnimationTimeline;
class AnonymousContent;
@ -142,7 +145,7 @@ template<typename, typename> class CallbackObjectHolder;
typedef CallbackObjectHolder<NodeFilter, nsIDOMNodeFilter> NodeFilterHolder;
struct FullScreenOptions {
FullScreenOptions() { }
FullScreenOptions();
nsRefPtr<gfx::VRHMDInfo> mVRHMDDevice;
};

Просмотреть файл

@ -0,0 +1,26 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Bug 1004703 - ignore 'unsafe-inline' if nonce- or hash-source specified</title>
</head>
<body>
<div id="testdiv">a</div>
<!-- first script whitelisted by 'unsafe-inline' -->
<script type="application/javascript">
document.getElementById('testdiv').innerHTML += 'b';
</script>
<!-- second script whitelisted by hash -->
<!-- sha256-uJXAPKP5NZxnVMZMUkDofh6a9P3UMRc1CRTevVPS/rI= -->
<script type="application/javascript">
document.getElementById('testdiv').innerHTML += 'c';
</script>
<!-- thrid script whitelisted by nonce -->
<script type="application/javascript" nonce="FooNonce">
document.getElementById('testdiv').innerHTML += 'd';
</script>
</body>
</html>

Просмотреть файл

@ -0,0 +1 @@
document.getElementById("testdiv").innerHTML = "allowed";

Просмотреть файл

@ -0,0 +1,42 @@
/**
* Custom *.sjs specifically for the needs of
* Bug 921493 - CSP: test whitelisting of scheme-relative sources
*/
function handleRequest(request, response)
{
Components.utils.importGlobalProperties(["URLSearchParams"]);
let query = new URLSearchParams(request.queryString);
let scheme = query.get("scheme");
let policy = query.get("policy");
let linkUrl = scheme +
"://example.com/tests/dom/base/test/csp/file_scheme_relative_sources.js";
let html = "<!DOCTYPE HTML>" +
"<html>" +
"<head>" +
"<title>test schemeless sources within CSP</title>" +
"</head>" +
"<body> " +
"<div id='testdiv'>blocked</div>" +
// try to load a scheme relative script
"<script src='" + linkUrl + "'></script>" +
// have an inline script that reports back to the parent whether
// the script got loaded or not from within the sandboxed iframe.
"<script type='application/javascript'>" +
"window.onload = function() {" +
"var inner = document.getElementById('testdiv').innerHTML;" +
"window.parent.postMessage({ result: inner }, '*');" +
"}" +
"</script>" +
"</body>" +
"</html>";
response.setHeader("Cache-Control", "no-cache", false);
response.setHeader("Content-Type", "text/html", false);
response.setHeader("Content-Security-Policy", policy, false);
response.write(html);
}

Просмотреть файл

@ -84,6 +84,9 @@ support-files =
file_hash_source.html
file_dual_header_testserver.sjs
file_hash_source.html^headers^
file_scheme_relative_sources.js
file_scheme_relative_sources.sjs
file_ignore_unsafe_inline.html
file_self_none_as_hostname_confusion.html
file_self_none_as_hostname_confusion.html^headers^
file_csp_path_matching.html
@ -139,6 +142,9 @@ skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug)) || toolkit == 'and
skip-if = e10s || buildapp == 'b2g' # http-on-opening-request observers are not available in child processes
[test_hash_source.html]
skip-if = e10s || buildapp == 'b2g' # can't compute hashes in child process (bug 958702)
[test_scheme_relative_sources.html]
skip-if = buildapp == 'b2g' #no ssl support
[test_ignore_unsafe_inline.html]
[test_self_none_as_hostname_confusion.html]
[test_bug949549.html]
[test_csp_path_matching.html]

Просмотреть файл

@ -0,0 +1,110 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Bug 1004703 - ignore 'unsafe-inline' if nonce- or hash-source specified</title>
<!-- Including SimpleTest.js so we can use waitForExplicitFinish !-->
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<iframe style="width:100%;" id="testframe"></iframe>
<script class="testbody" type="text/javascript">
SimpleTest.waitForExplicitFinish();
/* Description of the test:
* We load a page that contains three scripts using different policies
* and make sure 'unsafe-inline' is ignored within script-src if hash-source
* or nonce-source is specified.
*
* The expected output of each test is a sequence of chars.
* E.g. the default char we expect is 'a', depending on what inline scripts
* are allowed to run we also expect 'b', 'c', 'd'.
*/
var POLICY_PREFIX = "default-src 'none'; script-src ";
var tests = [
{
policy: POLICY_PREFIX + "'unsafe-inline'",
description: "'unsafe-inline' allows all scripts to execute",
file: "file_ignore_unsafe_inline.html",
result: "abcd",
},
{
policy: POLICY_PREFIX + "'unsafe-inline' 'sha256-uJXAPKP5NZxnVMZMUkDofh6a9P3UMRc1CRTevVPS/rI='",
description: "defining a hash should only allow one script to execute",
file: "file_ignore_unsafe_inline.html",
result: "ac",
},
{
policy: POLICY_PREFIX + "'unsafe-inline' 'nonce-FooNonce'",
description: "defining a nonce should only allow one script to execute",
file: "file_ignore_unsafe_inline.html",
result: "ad",
},
{
policy: POLICY_PREFIX + "'unsafe-inline' 'sha256-uJXAPKP5NZxnVMZMUkDofh6a9P3UMRc1CRTevVPS/rI=' 'nonce-FooNonce'",
description: "defining hash and nonce should allow two scripts to execute",
file: "file_ignore_unsafe_inline.html",
result: "acd",
},
{
policy: POLICY_PREFIX + "'unsafe-inline' 'sha256-uJXAPKP5NZxnVMZMUkDofh6a9P3UMRc1CRTevVPS/rI=' 'nonce-FooNonce' 'unsafe-inline'",
description: "defining hash, nonce and 'unsafe-inline' twice should still only allow two scripts to execute",
file: "file_ignore_unsafe_inline.html",
result: "acd",
},
{
policy: "default-src 'unsafe-inline' 'sha256-uJXAPKP5NZxnVMZMUkDofh6a9P3UMRc1CRTevVPS/rI=' 'nonce-FooNonce' ",
description: "unsafe-inline should *not* be ignored within default-src even if hash or nonce is specified",
file: "file_ignore_unsafe_inline.html",
result: "abcd",
},
];
var counter = 0;
var curTest;
function loadNextTest() {
if (counter == tests.length) {
document.getElementById("testframe").removeEventListener("load", test, false);
SimpleTest.finish();
return;
}
curTest = tests[counter++];
var src = "file_csp_testserver.sjs?file=";
// append the file that should be served
src += escape("tests/dom/base/test/csp/" + curTest.file);
// append the CSP that should be used to serve the file
src += "&csp=" + escape(curTest.policy);
document.getElementById("testframe").addEventListener("load", test, false);
document.getElementById("testframe").src = src;
}
function test() {
try {
document.getElementById("testframe").removeEventListener('load', test, false);
var testframe = document.getElementById("testframe");
var divcontent = testframe.contentWindow.document.getElementById('testdiv').innerHTML;
// sort the characters to make sure the result is in ascending order
// in case handlers run out of order
divcontent = divcontent.split('').sort().join('');
is(divcontent, curTest.result, curTest.description);
}
catch (e) {
ok(false, "error: could not access content for test " + curTest.description + "!");
}
loadNextTest();
}
loadNextTest();
</script>
</body>
</html>

Просмотреть файл

@ -0,0 +1,91 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Bug 921493 - CSP: test whitelisting of scheme-relative sources</title>
<!-- Including SimpleTest.js so we can use waitForExplicitFinish !-->
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<iframe style="width:100%;" id="testframe"></iframe>
<script class="testbody" type="text/javascript">
SimpleTest.waitForExplicitFinish();
/* Description of the test:
* We load http and https pages and verify that scheme relative sources
* are allowed unless its a downgrade from https -> http.
*
* Please note that the policy contains 'unsafe-inline' so we can use
* an inline script to query the result from within the sandboxed iframe
* and report it back to the parent document.
*/
var POLICY = "default-src 'none'; script-src 'unsafe-inline' example.com;";
var tests = [
{
description: "http -> http",
from: "http",
to: "http",
result: "allowed",
},
{
description: "http -> https",
from: "http",
to: "https",
result: "allowed",
},
{
description: "https -> https",
from: "https",
to: "https",
result: "allowed",
},
{
description: "https -> http",
from: "https",
to: "http",
result: "blocked",
}
];
var counter = 0;
var curTest;
function loadNextTest() {
if (counter == tests.length) {
window.removeEventListener("message", receiveMessage, false);
SimpleTest.finish();
return;
}
curTest = tests[counter++];
var src = curTest.from +
"://example.com/tests/dom/base/test/csp/file_scheme_relative_sources.sjs" +
"?scheme=" + curTest.to +
"&policy=" + escape(POLICY);
document.getElementById("testframe").src = src;
}
// using a postMessage handler to report the result back from
// within the sandboxed iframe without 'allow-same-origin'.
window.addEventListener("message", receiveMessage, false);
function receiveMessage(event) {
is(event.data.result, curTest.result,
"should be " + curTest.result + " in test (" + curTest.description + ")!");
loadNextTest();
}
// get the test started
loadNextTest();
</script>
</body>
</html>

Просмотреть файл

@ -4,6 +4,7 @@
* 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 "BluetoothReplyRunnable.h"
#include "BluetoothService.h"
#include "BluetoothUtils.h"
#include "mozilla/dom/BluetoothGattCharacteristicBinding.h"
@ -12,6 +13,7 @@
#include "mozilla/dom/bluetooth/BluetoothGattDescriptor.h"
#include "mozilla/dom/bluetooth/BluetoothGattService.h"
#include "mozilla/dom/bluetooth/BluetoothTypes.h"
#include "mozilla/dom/Promise.h"
using namespace mozilla;
using namespace mozilla::dom;
@ -58,6 +60,64 @@ BluetoothGattCharacteristic::~BluetoothGattCharacteristic()
bs->UnregisterBluetoothSignalHandler(path, this);
}
already_AddRefed<Promise>
BluetoothGattCharacteristic::StartNotifications(ErrorResult& aRv)
{
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetParentObject());
if (!global) {
aRv.Throw(NS_ERROR_FAILURE);
return nullptr;
}
nsRefPtr<Promise> promise = Promise::Create(global, aRv);
NS_ENSURE_TRUE(!aRv.Failed(), nullptr);
BluetoothService* bs = BluetoothService::Get();
BT_ENSURE_TRUE_REJECT(bs, NS_ERROR_NOT_AVAILABLE);
BT_ENSURE_TRUE_REJECT(mService, NS_ERROR_NOT_AVAILABLE);
nsRefPtr<BluetoothReplyRunnable> result =
new BluetoothVoidReplyRunnable(
nullptr /* DOMRequest */,
promise,
NS_LITERAL_STRING("GattClientStartNotifications"));
bs->GattClientStartNotificationsInternal(mService->GetAppUuid(),
mService->GetServiceId(),
mCharId,
result);
return promise.forget();
}
already_AddRefed<Promise>
BluetoothGattCharacteristic::StopNotifications(ErrorResult& aRv)
{
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetParentObject());
if (!global) {
aRv.Throw(NS_ERROR_FAILURE);
return nullptr;
}
nsRefPtr<Promise> promise = Promise::Create(global, aRv);
NS_ENSURE_TRUE(!aRv.Failed(), nullptr);
BluetoothService* bs = BluetoothService::Get();
BT_ENSURE_TRUE_REJECT(bs, NS_ERROR_NOT_AVAILABLE);
BT_ENSURE_TRUE_REJECT(mService, NS_ERROR_NOT_AVAILABLE);
nsRefPtr<BluetoothReplyRunnable> result =
new BluetoothVoidReplyRunnable(
nullptr /* DOMRequest */,
promise,
NS_LITERAL_STRING("GattClientStopNotifications"));
bs->GattClientStopNotificationsInternal(mService->GetAppUuid(),
mService->GetServiceId(),
mCharId,
result);
return promise.forget();
}
void
BluetoothGattCharacteristic::HandleDescriptorsDiscovered(
const BluetoothValue& aValue)

Просмотреть файл

@ -15,6 +15,12 @@
#include "nsWrapperCache.h"
#include "nsPIDOMWindow.h"
namespace mozilla {
namespace dom {
class Promise;
}
}
BEGIN_BLUETOOTH_NAMESPACE
class BluetoothGattService;
@ -53,6 +59,12 @@ public:
return mCharId.mInstanceId;
}
/****************************************************************************
* Methods (Web API Implementation)
***************************************************************************/
already_AddRefed<Promise> StartNotifications(ErrorResult& aRv);
already_AddRefed<Promise> StopNotifications(ErrorResult& aRv);
/****************************************************************************
* Others
***************************************************************************/

Просмотреть файл

@ -953,7 +953,7 @@ public:
const nsAString& aPinCode,
BluetoothResultHandler* aRes) = 0;
virtual void SspReply(const nsAString& aBdAddr, const nsAString& aVariant,
virtual void SspReply(const nsAString& aBdAddr, BluetoothSspVariant aVariant,
bool aAccept, uint32_t aPasskey,
BluetoothResultHandler* aRes) = 0;

Просмотреть файл

@ -75,7 +75,7 @@ BluetoothPairingHandle::SetPinCode(const nsAString& aPinCode, ErrorResult& aRv)
nsRefPtr<Promise> promise = Promise::Create(global, aRv);
NS_ENSURE_TRUE(!aRv.Failed(), nullptr);
BT_ENSURE_TRUE_REJECT(mType.EqualsLiteral("enterpincodereq"),
BT_ENSURE_TRUE_REJECT(mType.EqualsLiteral(PAIRING_REQ_TYPE_ENTERPINCODE),
NS_ERROR_DOM_INVALID_STATE_ERR);
BluetoothService* bs = BluetoothService::Get();
@ -85,13 +85,13 @@ BluetoothPairingHandle::SetPinCode(const nsAString& aPinCode, ErrorResult& aRv)
new BluetoothVoidReplyRunnable(nullptr /* DOMRequest */,
promise,
NS_LITERAL_STRING("SetPinCode"));
bs->SetPinCodeInternal(mDeviceAddress, aPinCode, result);
bs->PinReplyInternal(mDeviceAddress, true /* accept */, aPinCode, result);
return promise.forget();
}
already_AddRefed<Promise>
BluetoothPairingHandle::SetPairingConfirmation(bool aConfirm, ErrorResult& aRv)
BluetoothPairingHandle::Accept(ErrorResult& aRv)
{
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetParentObject());
if (!global) {
@ -102,24 +102,79 @@ BluetoothPairingHandle::SetPairingConfirmation(bool aConfirm, ErrorResult& aRv)
nsRefPtr<Promise> promise = Promise::Create(global, aRv);
NS_ENSURE_TRUE(!aRv.Failed(), nullptr);
BT_ENSURE_TRUE_REJECT(mType.EqualsLiteral("pairingconfirmationreq"),
BT_ENSURE_TRUE_REJECT(mType.EqualsLiteral(PAIRING_REQ_TYPE_CONFIRMATION) ||
mType.EqualsLiteral(PAIRING_REQ_TYPE_CONSENT),
NS_ERROR_DOM_INVALID_STATE_ERR);
BluetoothService* bs = BluetoothService::Get();
BT_ENSURE_TRUE_REJECT(bs, NS_ERROR_NOT_AVAILABLE);
BluetoothSspVariant variant;
BT_ENSURE_TRUE_REJECT(GetSspVariant(variant), NS_ERROR_DOM_OPERATION_ERR);
nsRefPtr<BluetoothReplyRunnable> result =
new BluetoothVoidReplyRunnable(nullptr /* DOMRequest */,
promise,
NS_LITERAL_STRING("Accept"));
bs->SspReplyInternal(
mDeviceAddress, variant, true /* aAccept */, result);
return promise.forget();
}
already_AddRefed<Promise>
BluetoothPairingHandle::Reject(ErrorResult& aRv)
{
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetParentObject());
if (!global) {
aRv.Throw(NS_ERROR_FAILURE);
return nullptr;
}
nsRefPtr<Promise> promise = Promise::Create(global, aRv);
NS_ENSURE_TRUE(!aRv.Failed(), nullptr);
BluetoothService* bs = BluetoothService::Get();
BT_ENSURE_TRUE_REJECT(bs, NS_ERROR_NOT_AVAILABLE);
nsRefPtr<BluetoothReplyRunnable> result =
new BluetoothVoidReplyRunnable(nullptr /* DOMRequest */,
promise,
NS_LITERAL_STRING(
"SetPairingConfirmation"));
NS_LITERAL_STRING("Reject"));
if (mType.EqualsLiteral(PAIRING_REQ_TYPE_ENTERPINCODE)) { // Pin request
bs->PinReplyInternal(
mDeviceAddress, false /* aAccept */, EmptyString(), result);
} else { // Ssp request
BluetoothSspVariant variant;
BT_ENSURE_TRUE_REJECT(GetSspVariant(variant), NS_ERROR_DOM_OPERATION_ERR);
bs->SspReplyInternal(
mDeviceAddress, variant, false /* aAccept */, result);
}
bs->SetPairingConfirmationInternal(mDeviceAddress,
aConfirm,
result);
return promise.forget();
}
bool
BluetoothPairingHandle::GetSspVariant(BluetoothSspVariant& aVariant)
{
if (mType.EqualsLiteral(PAIRING_REQ_TYPE_DISPLAYPASSKEY)) {
aVariant = BluetoothSspVariant::SSP_VARIANT_PASSKEY_NOTIFICATION;
} else if (mType.EqualsLiteral(PAIRING_REQ_TYPE_CONFIRMATION)) {
aVariant = BluetoothSspVariant::SSP_VARIANT_PASSKEY_CONFIRMATION;
} else if (mType.EqualsLiteral(PAIRING_REQ_TYPE_CONSENT)) {
aVariant = BluetoothSspVariant::SSP_VARIANT_CONSENT;
} else {
BT_LOGR("Invalid SSP variant name: %s",
NS_ConvertUTF16toUTF8(mType).get());
aVariant = SSP_VARIANT_PASSKEY_CONFIRMATION; // silences compiler warning
return false;
}
return true;
}
JSObject*
BluetoothPairingHandle::WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto)

Просмотреть файл

@ -47,11 +47,15 @@ public:
aPasskey = mPasskey;
}
// Reply to the enterpincodereq pairing request
already_AddRefed<Promise>
SetPinCode(const nsAString& aPinCode, ErrorResult& aRv);
already_AddRefed<Promise>
SetPairingConfirmation(bool aConfirm, ErrorResult& aRv);
// Accept the pairingconfirmationreq or pairingconsentreq pairing request
already_AddRefed<Promise> Accept(ErrorResult& aRv);
// Reject the pairing request
already_AddRefed<Promise> Reject(ErrorResult& aRv);
private:
BluetoothPairingHandle(nsPIDOMWindow* aOwner,
@ -60,6 +64,15 @@ private:
const nsAString& aPasskey);
~BluetoothPairingHandle();
/**
* Map mType into a BluetoothSspVariant enum value.
*
* @param aVariant [out] BluetoothSspVariant value mapped from mType.
* @return a boolean value to indicate whether mType can map into a
* BluetoothSspVariant value.
*/
bool GetSspVariant(BluetoothSspVariant& aVariant);
nsCOMPtr<nsPIDOMWindow> mOwner;
nsString mDeviceAddress;
nsString mType;

Просмотреть файл

@ -236,13 +236,35 @@ public:
BluetoothProfileManagerBase* aManager) = 0;
virtual void
SetPinCodeInternal(const nsAString& aDeviceAddress, const nsAString& aPinCode,
PinReplyInternal(const nsAString& aDeviceAddress,
bool aAccept,
const nsAString& aPinCode,
BluetoothReplyRunnable* aRunnable) = 0;
virtual void
SspReplyInternal(const nsAString& aDeviceAddress,
BluetoothSspVariant aVariant,
bool aAccept,
BluetoothReplyRunnable* aRunnable) = 0;
/**
* Legacy method used by bluez only to reply pincode request.
*/
virtual void
SetPinCodeInternal(const nsAString& aDeviceAddress,
const nsAString& aPinCode,
BluetoothReplyRunnable* aRunnable) = 0;
/**
* Legacy method used by bluez only to reply passkey entry request.
*/
virtual void
SetPasskeyInternal(const nsAString& aDeviceAddress, uint32_t aPasskey,
BluetoothReplyRunnable* aRunnable) = 0;
/**
* Legacy method used by bluez only to reply pairing confirmation request.
*/
virtual void
SetPairingConfirmationInternal(const nsAString& aDeviceAddress, bool aConfirm,
BluetoothReplyRunnable* aRunnable) = 0;
@ -350,6 +372,26 @@ public:
DiscoverGattServicesInternal(const nsAString& aAppUuid,
BluetoothReplyRunnable* aRunnable) = 0;
/**
* Enable notifications of a given GATT characteristic.
* (platform specific implementation)
*/
virtual void
GattClientStartNotificationsInternal(const nsAString& aAppUuid,
const BluetoothGattServiceId& aServId,
const BluetoothGattId& aCharId,
BluetoothReplyRunnable* aRunnable) = 0;
/**
* Disable notifications of a given GATT characteristic.
* (platform specific implementation)
*/
virtual void
GattClientStopNotificationsInternal(const nsAString& aAppUuid,
const BluetoothGattServiceId& aServId,
const BluetoothGattId& aCharId,
BluetoothReplyRunnable* aRunnable) = 0;
/**
* Unregister a GATT client. (platform specific implementation)
*/

Просмотреть файл

@ -583,25 +583,6 @@ Convert(const nsAString& aIn, BluetoothServiceName& aOut)
return NS_OK;
}
nsresult
Convert(const nsAString& aIn, BluetoothSspVariant& aOut)
{
if (aIn.EqualsLiteral("PasskeyConfirmation")) {
aOut = SSP_VARIANT_PASSKEY_CONFIRMATION;
} else if (aIn.EqualsLiteral("PasskeyEntry")) {
aOut = SSP_VARIANT_PASSKEY_ENTRY;
} else if (aIn.EqualsLiteral("Consent")) {
aOut = SSP_VARIANT_CONSENT;
} else if (aIn.EqualsLiteral("PasskeyNotification")) {
aOut = SSP_VARIANT_PASSKEY_NOTIFICATION;
} else {
BT_LOGR("Invalid SSP variant name: %s", NS_ConvertUTF16toUTF8(aIn).get());
aOut = SSP_VARIANT_PASSKEY_CONFIRMATION; // silences compiler warning
return NS_ERROR_ILLEGAL_VALUE;
}
return NS_OK;
}
nsresult
Convert(BluetoothAclState aIn, bool& aOut)
{

Просмотреть файл

@ -221,9 +221,6 @@ Convert(const nsAString& aIn, BluetoothPropertyType& aOut);
nsresult
Convert(const nsAString& aIn, BluetoothServiceName& aOut);
nsresult
Convert(const nsAString& aIn, BluetoothSspVariant& aOut);
nsresult
Convert(BluetoothAclState aIn, bool& aOut);

Просмотреть файл

@ -569,7 +569,7 @@ public:
return rv;
}
nsresult SspReplyCmd(const nsAString& aBdAddr, const nsAString& aVariant,
nsresult SspReplyCmd(const nsAString& aBdAddr, BluetoothSspVariant aVariant,
bool aAccept, uint32_t aPasskey,
BluetoothResultHandler* aRes)
{
@ -580,8 +580,7 @@ public:
nsresult rv = PackPDU(
PackConversion<nsAString, BluetoothAddress>(aBdAddr),
PackConversion<nsAString, BluetoothSspVariant>(aVariant),
aAccept, aPasskey, *pdu);
aVariant, aAccept, aPasskey, *pdu);
if (NS_FAILED(rv)) {
return rv;
}
@ -2420,7 +2419,7 @@ BluetoothDaemonInterface::PinReply(const nsAString& aBdAddr, bool aAccept,
void
BluetoothDaemonInterface::SspReply(const nsAString& aBdAddr,
const nsAString& aVariant,
BluetoothSspVariant aVariant,
bool aAccept, uint32_t aPasskey,
BluetoothResultHandler* aRes)
{

Просмотреть файл

@ -83,7 +83,7 @@ public:
const nsAString& aPinCode,
BluetoothResultHandler* aRes);
void SspReply(const nsAString& aBdAddr, const nsAString& aVariant,
void SspReply(const nsAString& aBdAddr, BluetoothSspVariant aVariant,
bool aAccept, uint32_t aPasskey,
BluetoothResultHandler* aRes);

Просмотреть файл

@ -58,6 +58,8 @@ public:
mDiscoverRunnable = nullptr;
mUnregisterClientRunnable = nullptr;
mReadRemoteRssiRunnable = nullptr;
mRegisterNotificationsRunnable = nullptr;
mDeregisterNotificationsRunnable = nullptr;
}
void NotifyDiscoverCompleted(bool aSuccess)
@ -98,6 +100,8 @@ public:
nsRefPtr<BluetoothReplyRunnable> mDisconnectRunnable;
nsRefPtr<BluetoothReplyRunnable> mDiscoverRunnable;
nsRefPtr<BluetoothReplyRunnable> mReadRemoteRssiRunnable;
nsRefPtr<BluetoothReplyRunnable> mRegisterNotificationsRunnable;
nsRefPtr<BluetoothReplyRunnable> mDeregisterNotificationsRunnable;
nsRefPtr<BluetoothReplyRunnable> mUnregisterClientRunnable;
/**
@ -636,6 +640,151 @@ BluetoothGattManager::ReadRemoteRssi(int aClientIf,
new ReadRemoteRssiResultHandler(client));
}
class BluetoothGattManager::RegisterNotificationsResultHandler final
: public BluetoothGattClientResultHandler
{
public:
RegisterNotificationsResultHandler(BluetoothGattClient* aClient)
: mClient(aClient)
{
MOZ_ASSERT(mClient);
}
void RegisterNotification() override
{
MOZ_ASSERT(mClient->mRegisterNotificationsRunnable);
/**
* Resolve the promise directly if we successfully issued this request to
* stack.
*
* We resolve the promise here since bluedroid stack always returns
* incorrect connId in |RegisterNotificationNotification| and we cannot map
* back to the target client because of it.
* Please see Bug 1149043 for more information.
*/
DispatchReplySuccess(mClient->mRegisterNotificationsRunnable);
mClient->mRegisterNotificationsRunnable = nullptr;
}
void OnError(BluetoothStatus aStatus) override
{
BT_WARNING(
"BluetoothGattClientInterface::RegisterNotifications failed: %d",
(int)aStatus);
MOZ_ASSERT(mClient->mRegisterNotificationsRunnable);
DispatchReplyError(mClient->mRegisterNotificationsRunnable,
NS_LITERAL_STRING("RegisterNotifications failed"));
mClient->mRegisterNotificationsRunnable = nullptr;
}
private:
nsRefPtr<BluetoothGattClient> mClient;
};
void
BluetoothGattManager::RegisterNotifications(
const nsAString& aAppUuid, const BluetoothGattServiceId& aServId,
const BluetoothGattId& aCharId, BluetoothReplyRunnable* aRunnable)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aRunnable);
ENSURE_GATT_CLIENT_INTF_IS_READY_VOID(aRunnable);
size_t index = sClients->IndexOf(aAppUuid, 0 /* Start */, UuidComparator());
MOZ_ASSERT(index != sClients->NoIndex);
nsRefPtr<BluetoothGattClient> client = sClients->ElementAt(index);
// Reject the request if there is an ongoing request or client is already
// disconnected
if (client->mRegisterNotificationsRunnable || client->mConnId <= 0) {
DispatchReplyError(aRunnable,
NS_LITERAL_STRING("RegisterNotifications failed"));
return;
}
client->mRegisterNotificationsRunnable = aRunnable;
sBluetoothGattClientInterface->RegisterNotification(
client->mClientIf, client->mDeviceAddr, aServId, aCharId,
new RegisterNotificationsResultHandler(client));
}
class BluetoothGattManager::DeregisterNotificationsResultHandler final
: public BluetoothGattClientResultHandler
{
public:
DeregisterNotificationsResultHandler(BluetoothGattClient* aClient)
: mClient(aClient)
{
MOZ_ASSERT(mClient);
}
void DeregisterNotification() override
{
MOZ_ASSERT(mClient->mDeregisterNotificationsRunnable);
/**
* Resolve the promise directly if we successfully issued this request to
* stack.
*
* We resolve the promise here since bluedroid stack always returns
* incorrect connId in |RegisterNotificationNotification| and we cannot map
* back to the target client because of it.
* Please see Bug 1149043 for more information.
*/
DispatchReplySuccess(mClient->mDeregisterNotificationsRunnable);
mClient->mDeregisterNotificationsRunnable = nullptr;
}
void OnError(BluetoothStatus aStatus) override
{
BT_WARNING(
"BluetoothGattClientInterface::DeregisterNotifications failed: %d",
(int)aStatus);
MOZ_ASSERT(mClient->mDeregisterNotificationsRunnable);
DispatchReplyError(mClient->mDeregisterNotificationsRunnable,
NS_LITERAL_STRING("DeregisterNotifications failed"));
mClient->mDeregisterNotificationsRunnable = nullptr;
}
private:
nsRefPtr<BluetoothGattClient> mClient;
};
void
BluetoothGattManager::DeregisterNotifications(
const nsAString& aAppUuid, const BluetoothGattServiceId& aServId,
const BluetoothGattId& aCharId, BluetoothReplyRunnable* aRunnable)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aRunnable);
ENSURE_GATT_CLIENT_INTF_IS_READY_VOID(aRunnable);
size_t index = sClients->IndexOf(aAppUuid, 0 /* Start */, UuidComparator());
MOZ_ASSERT(index != sClients->NoIndex);
nsRefPtr<BluetoothGattClient> client = sClients->ElementAt(index);
// Reject the request if there is an ongoing request
if (client->mDeregisterNotificationsRunnable) {
DispatchReplyError(aRunnable,
NS_LITERAL_STRING("DeregisterNotifications failed"));
return;
}
client->mDeregisterNotificationsRunnable = aRunnable;
sBluetoothGattClientInterface->DeregisterNotification(
client->mClientIf, client->mDeviceAddr, aServId, aCharId,
new DeregisterNotificationsResultHandler(client));
}
//
// Notification Handlers
//
@ -999,7 +1148,25 @@ BluetoothGattManager::RegisterNotificationNotification(
int aConnId, int aIsRegister, BluetoothGattStatus aStatus,
const BluetoothGattServiceId& aServiceId,
const BluetoothGattId& aCharId)
{ }
{
MOZ_ASSERT(NS_IsMainThread());
BT_LOGD("aStatus = %d, aConnId = %d, aIsRegister = %d",
aStatus, aConnId, aIsRegister);
/**
* FIXME: Bug 1149043
*
* aConnId reported by bluedroid stack is wrong, with these limited
* information we have, we currently cannot map back to the client from this
* callback. Therefore, we resolve/reject the Promise for registering or
* deregistering notifications in their result handlers instead of this
* callback.
* We should resolve/reject the Promise for registering or deregistering
* notifications here if this bluedroid stack bug is fixed.
*
* Please see Bug 1149043 for more information.
*/
}
void
BluetoothGattManager::NotifyNotification(

Просмотреть файл

@ -46,6 +46,16 @@ public:
const nsAString& aDeviceAddr,
BluetoothReplyRunnable* aRunnable);
void RegisterNotifications(const nsAString& aAppUuid,
const BluetoothGattServiceId& aServId,
const BluetoothGattId& aCharId,
BluetoothReplyRunnable* aRunnable);
void DeregisterNotifications(const nsAString& aAppUuid,
const BluetoothGattServiceId& aServId,
const BluetoothGattId& aCharId,
BluetoothReplyRunnable* aRunnable);
private:
class CleanupResultHandler;
class CleanupResultHandlerRunnable;
@ -56,6 +66,8 @@ private:
class DisconnectResultHandler;
class DiscoverResultHandler;
class ReadRemoteRssiResultHandler;
class RegisterNotificationsResultHandler;
class DeregisterNotificationsResultHandler;
BluetoothGattManager();

Просмотреть файл

@ -80,25 +80,6 @@ Convert(const nsAString& aIn, bt_bdaddr_t& aOut)
return NS_OK;
}
nsresult
Convert(const nsAString& aIn, bt_ssp_variant_t& aOut)
{
if (aIn.EqualsLiteral("PasskeyConfirmation")) {
aOut = BT_SSP_VARIANT_PASSKEY_CONFIRMATION;
} else if (aIn.EqualsLiteral("PasskeyEntry")) {
aOut = BT_SSP_VARIANT_PASSKEY_ENTRY;
} else if (aIn.EqualsLiteral("Consent")) {
aOut = BT_SSP_VARIANT_CONSENT;
} else if (aIn.EqualsLiteral("PasskeyNotification")) {
aOut = BT_SSP_VARIANT_PASSKEY_NOTIFICATION;
} else {
BT_LOGR("Invalid SSP variant name: %s", NS_ConvertUTF16toUTF8(aIn).get());
aOut = BT_SSP_VARIANT_PASSKEY_CONFIRMATION; // silences compiler warning
return NS_ERROR_ILLEGAL_VALUE;
}
return NS_OK;
}
nsresult
Convert(const uint8_t aIn[16], bt_uuid_t& aOut)
{

Просмотреть файл

@ -110,9 +110,6 @@ Convert(ConvertNamedValue& aIn, bt_property_t& aOut);
nsresult
Convert(const nsAString& aIn, bt_bdaddr_t& aOut);
nsresult
Convert(const nsAString& aIn, bt_ssp_variant_t& aOut);
inline nsresult
Convert(const bt_ssp_variant_t& aIn, BluetoothSspVariant& aOut)
{
@ -131,6 +128,24 @@ Convert(const bt_ssp_variant_t& aIn, BluetoothSspVariant& aOut)
return NS_OK;
}
inline nsresult
Convert(const BluetoothSspVariant& aIn, bt_ssp_variant_t& aOut)
{
static const bt_ssp_variant_t sSspVariant[] = {
CONVERT(SSP_VARIANT_PASSKEY_CONFIRMATION,
BT_SSP_VARIANT_PASSKEY_CONFIRMATION),
CONVERT(SSP_VARIANT_PASSKEY_ENTRY, BT_SSP_VARIANT_PASSKEY_ENTRY),
CONVERT(SSP_VARIANT_CONSENT, BT_SSP_VARIANT_CONSENT),
CONVERT(SSP_VARIANT_PASSKEY_NOTIFICATION,
BT_SSP_VARIANT_PASSKEY_NOTIFICATION)
};
if (aIn >= MOZ_ARRAY_LENGTH(sSspVariant)) {
return NS_ERROR_ILLEGAL_VALUE;
}
aOut = sSspVariant[aIn];
return NS_OK;
}
inline nsresult
Convert(const bool& aIn, uint8_t& aOut)
{

Просмотреть файл

@ -769,7 +769,7 @@ BluetoothHALInterface::PinReply(const nsAString& aBdAddr, bool aAccept,
void
BluetoothHALInterface::SspReply(const nsAString& aBdAddr,
const nsAString& aVariant,
BluetoothSspVariant aVariant,
bool aAccept, uint32_t aPasskey,
BluetoothResultHandler* aRes)
{

Просмотреть файл

@ -69,7 +69,7 @@ public:
const nsAString& aPinCode,
BluetoothResultHandler* aRes);
void SspReply(const nsAString& aBdAddr, const nsAString& aVariant,
void SspReply(const nsAString& aBdAddr, BluetoothSspVariant aVariant,
bool aAccept, uint32_t aPasskey,
BluetoothResultHandler* aRes);

Просмотреть файл

@ -768,25 +768,18 @@ private:
};
void
BluetoothServiceBluedroid::SetPinCodeInternal(
const nsAString& aDeviceAddress, const nsAString& aPinCode,
BluetoothReplyRunnable* aRunnable)
BluetoothServiceBluedroid::PinReplyInternal(
const nsAString& aDeviceAddress, bool aAccept,
const nsAString& aPinCode, BluetoothReplyRunnable* aRunnable)
{
MOZ_ASSERT(NS_IsMainThread());
ENSURE_BLUETOOTH_IS_READY_VOID(aRunnable);
sBtInterface->PinReply(aDeviceAddress, true, aPinCode,
new PinReplyResultHandler(aRunnable));
sBtInterface->PinReply(aDeviceAddress, aAccept, aPinCode,
new PinReplyResultHandler(aRunnable));
}
void
BluetoothServiceBluedroid::SetPasskeyInternal(
const nsAString& aDeviceAddress, uint32_t aPasskey,
BluetoothReplyRunnable* aRunnable)
{
return;
}
class BluetoothServiceBluedroid::SspReplyResultHandler final
: public BluetoothResultHandler
@ -811,19 +804,43 @@ private:
};
void
BluetoothServiceBluedroid::SetPairingConfirmationInternal(
const nsAString& aDeviceAddress, bool aConfirm,
BluetoothReplyRunnable* aRunnable)
BluetoothServiceBluedroid::SspReplyInternal(
const nsAString& aDeviceAddress, BluetoothSspVariant aVariant,
bool aAccept, BluetoothReplyRunnable* aRunnable)
{
MOZ_ASSERT(NS_IsMainThread());
ENSURE_BLUETOOTH_IS_READY_VOID(aRunnable);
sBtInterface->SspReply(aDeviceAddress,
NS_ConvertUTF8toUTF16("PasskeyConfirmation"),
aConfirm, 0, new SspReplyResultHandler(aRunnable));
sBtInterface->SspReply(aDeviceAddress, aVariant, aAccept, 0 /* passkey */,
new SspReplyResultHandler(aRunnable));
}
void
BluetoothServiceBluedroid::SetPinCodeInternal(
const nsAString& aDeviceAddress, const nsAString& aPinCode,
BluetoothReplyRunnable* aRunnable)
{
// Legacy method used by bluez only.
}
void
BluetoothServiceBluedroid::SetPasskeyInternal(
const nsAString& aDeviceAddress, uint32_t aPasskey,
BluetoothReplyRunnable* aRunnable)
{
// Legacy method used by bluez only.
}
void
BluetoothServiceBluedroid::SetPairingConfirmationInternal(
const nsAString& aDeviceAddress, bool aConfirm,
BluetoothReplyRunnable* aRunnable)
{
// Legacy method used by bluez only.
}
void
BluetoothServiceBluedroid::NextBluetoothProfileController()
{
@ -1131,6 +1148,36 @@ BluetoothServiceBluedroid::DiscoverGattServicesInternal(
gatt->Discover(aAppUuid, aRunnable);
}
void
BluetoothServiceBluedroid::GattClientStartNotificationsInternal(
const nsAString& aAppUuid, const BluetoothGattServiceId& aServId,
const BluetoothGattId& aCharId, BluetoothReplyRunnable* aRunnable)
{
MOZ_ASSERT(NS_IsMainThread());
ENSURE_BLUETOOTH_IS_READY_VOID(aRunnable);
BluetoothGattManager* gatt = BluetoothGattManager::Get();
ENSURE_GATT_MGR_IS_READY_VOID(gatt, aRunnable);
gatt->RegisterNotifications(aAppUuid, aServId, aCharId, aRunnable);
}
void
BluetoothServiceBluedroid::GattClientStopNotificationsInternal(
const nsAString& aAppUuid, const BluetoothGattServiceId& aServId,
const BluetoothGattId& aCharId, BluetoothReplyRunnable* aRunnable)
{
MOZ_ASSERT(NS_IsMainThread());
ENSURE_BLUETOOTH_IS_READY_VOID(aRunnable);
BluetoothGattManager* gatt = BluetoothGattManager::Get();
ENSURE_GATT_MGR_IS_READY_VOID(gatt, aRunnable);
gatt->DeregisterNotifications(aAppUuid, aServId, aCharId, aRunnable);
}
void
BluetoothServiceBluedroid::UnregisterGattClientInternal(
int aClientIf, BluetoothReplyRunnable* aRunnable)

Просмотреть файл

@ -81,15 +81,30 @@ public:
BluetoothReplyRunnable* aRunnable);
virtual void
SetPinCodeInternal(const nsAString& aDeviceAddress, const nsAString& aPinCode,
PinReplyInternal(const nsAString& aDeviceAddress,
bool aAccept,
const nsAString& aPinCode,
BluetoothReplyRunnable* aRunnable);
virtual void
SspReplyInternal(const nsAString& aDeviceAddress,
BluetoothSspVariant aVariant,
bool aAccept,
BluetoothReplyRunnable* aRunnable);
virtual void
SetPinCodeInternal(const nsAString& aDeviceAddress,
const nsAString& aPinCode,
BluetoothReplyRunnable* aRunnable);
virtual void
SetPasskeyInternal(const nsAString& aDeviceAddress, uint32_t aPasskey,
SetPasskeyInternal(const nsAString& aDeviceAddress,
uint32_t aPasskey,
BluetoothReplyRunnable* aRunnable);
virtual void
SetPairingConfirmationInternal(const nsAString& aDeviceAddress, bool aConfirm,
SetPairingConfirmationInternal(const nsAString& aDeviceAddress,
bool aConfirm,
BluetoothReplyRunnable* aRunnable);
virtual void
@ -188,6 +203,20 @@ public:
DiscoverGattServicesInternal(const nsAString& aAppUuid,
BluetoothReplyRunnable* aRunnable) override;
virtual void
GattClientStartNotificationsInternal(
const nsAString& aAppUuid,
const BluetoothGattServiceId& aServId,
const BluetoothGattId& aCharId,
BluetoothReplyRunnable* aRunnable) override;
virtual void
GattClientStopNotificationsInternal(
const nsAString& aAppUuid,
const BluetoothGattServiceId& aServId,
const BluetoothGattId& aCharId,
BluetoothReplyRunnable* aRunnable) override;
virtual void
UnregisterGattClientInternal(int aClientIf,
BluetoothReplyRunnable* aRunnable) override;

Просмотреть файл

@ -4277,6 +4277,10 @@ BluetoothDBusService::UpdateNotification(ControlEventId aEventId,
DispatchToDBusThread(task);
}
//
// Methods for BT APIv2 implementation which currently only supports bluedroid
//
void
BluetoothDBusService::ConnectGattClientInternal(
const nsAString& aAppUuid, const nsAString& aDeviceAddress,
@ -4297,6 +4301,20 @@ BluetoothDBusService::DiscoverGattServicesInternal(
{
}
void
BluetoothDBusService::GattClientStartNotificationsInternal(
const nsAString& aAppUuid, const BluetoothGattServiceId& aServId,
const BluetoothGattId& aCharId, BluetoothReplyRunnable* aRunnable)
{
}
void
BluetoothDBusService::GattClientStopNotificationsInternal(
const nsAString& aAppUuid, const BluetoothGattServiceId& aServId,
const BluetoothGattId& aCharId, BluetoothReplyRunnable* aRunnable)
{
}
void
BluetoothDBusService::UnregisterGattClientInternal(
int aClientIf, BluetoothReplyRunnable* aRunnable)
@ -4309,3 +4327,17 @@ BluetoothDBusService::GattClientReadRemoteRssiInternal(
BluetoothReplyRunnable* aRunnable)
{
}
void
BluetoothDBusService::PinReplyInternal(
const nsAString& aDeviceAddress, bool aAccept,
const nsAString& aPinCode, BluetoothReplyRunnable* aRunnable)
{
}
void
BluetoothDBusService::SspReplyInternal(
const nsAString& aDeviceAddress, BluetoothSspVariant aVariant,
bool aAccept, BluetoothReplyRunnable* aRunnable)
{
}

Просмотреть файл

@ -94,7 +94,20 @@ public:
BluetoothReplyRunnable* aRunnable) override;
virtual void
SetPinCodeInternal(const nsAString& aDeviceAddress, const nsAString& aPinCode,
PinReplyInternal(const nsAString& aDeviceAddress,
bool aAccept,
const nsAString& aPinCode,
BluetoothReplyRunnable* aRunnable)
virtual void
SspReplyInternal(const nsAString& aDeviceAddress,
BluetoothSspVariant aVariant,
bool aAccept,
BluetoothReplyRunnable* aRunnable)
virtual void
SetPinCodeInternal(const nsAString& aDeviceAddress,
const nsAString& aPinCode,
BluetoothReplyRunnable* aRunnable) override;
virtual void
@ -102,7 +115,8 @@ public:
BluetoothReplyRunnable* aRunnable) override;
virtual void
SetPairingConfirmationInternal(const nsAString& aDeviceAddress, bool aConfirm,
SetPairingConfirmationInternal(const nsAString& aDeviceAddress,
bool aConfirm,
BluetoothReplyRunnable* aRunnable) override;
virtual void
@ -199,6 +213,20 @@ public:
DiscoverGattServicesInternal(const nsAString& aAppUuid,
BluetoothReplyRunnable* aRunnable) override;
virtual void
GattClientStartNotificationsInternal(
const nsAString& aAppUuid,
const BluetoothGattServiceId& aServId,
const BluetoothGattId& aCharId,
BluetoothReplyRunnable* aRunnable) override;
virtual void
GattClientStopNotificationsInternal(
const nsAString& aAppUuid,
const BluetoothGattServiceId& aServId,
const BluetoothGattId& aCharId,
BluetoothReplyRunnable* aRunnable) override;
virtual void
UnregisterGattClientInternal(int aClientIf,
BluetoothReplyRunnable* aRunnable) override;

Просмотреть файл

@ -20,6 +20,14 @@ struct ParamTraits<mozilla::dom::bluetooth::BluetoothObjectType>
mozilla::dom::bluetooth::TYPE_INVALID>
{ };
template <>
struct ParamTraits<mozilla::dom::bluetooth::BluetoothSspVariant>
: public ContiguousEnumSerializer<
mozilla::dom::bluetooth::BluetoothSspVariant,
mozilla::dom::bluetooth::SSP_VARIANT_PASSKEY_CONFIRMATION,
mozilla::dom::bluetooth::SSP_VARIANT_PASSKEY_NOTIFICATION>
{ };
template <>
struct ParamTraits<mozilla::dom::bluetooth::BluetoothStatus>
: public ContiguousEnumSerializer<

Просмотреть файл

@ -212,6 +212,10 @@ BluetoothParent::RecvPBluetoothRequestConstructor(
return actor->DoRequest(aRequest.get_ConnectedDevicePropertiesRequest());
case Request::TFetchUuidsRequest:
return actor->DoRequest(aRequest.get_FetchUuidsRequest());
case Request::TPinReplyRequest:
return actor->DoRequest(aRequest.get_PinReplyRequest());
case Request::TSspReplyRequest:
return actor->DoRequest(aRequest.get_SspReplyRequest());
case Request::TSetPinCodeRequest:
return actor->DoRequest(aRequest.get_SetPinCodeRequest());
case Request::TSetPasskeyRequest:
@ -256,6 +260,12 @@ BluetoothParent::RecvPBluetoothRequestConstructor(
return actor->DoRequest(aRequest.get_DisconnectGattClientRequest());
case Request::TDiscoverGattServicesRequest:
return actor->DoRequest(aRequest.get_DiscoverGattServicesRequest());
case Request::TGattClientStartNotificationsRequest:
return actor->DoRequest(
aRequest.get_GattClientStartNotificationsRequest());
case Request::TGattClientStopNotificationsRequest:
return actor->DoRequest(
aRequest.get_GattClientStopNotificationsRequest());
case Request::TUnregisterGattClientRequest:
return actor->DoRequest(aRequest.get_UnregisterGattClientRequest());
case Request::TGattClientReadRemoteRssiRequest:
@ -470,6 +480,34 @@ BluetoothRequestParent::DoRequest(const FetchUuidsRequest& aRequest)
return true;
}
bool
BluetoothRequestParent::DoRequest(const PinReplyRequest& aRequest)
{
MOZ_ASSERT(mService);
MOZ_ASSERT(mRequestType == Request::TPinReplyRequest);
mService->PinReplyInternal(aRequest.address(),
aRequest.accept(),
aRequest.pinCode(),
mReplyRunnable.get());
return true;
}
bool
BluetoothRequestParent::DoRequest(const SspReplyRequest& aRequest)
{
MOZ_ASSERT(mService);
MOZ_ASSERT(mRequestType == Request::TSspReplyRequest);
mService->SspReplyInternal(aRequest.address(),
aRequest.variant(),
aRequest.accept(),
mReplyRunnable.get());
return true;
}
bool
BluetoothRequestParent::DoRequest(const SetPinCodeRequest& aRequest)
{
@ -733,6 +771,36 @@ BluetoothRequestParent::DoRequest(const DiscoverGattServicesRequest& aRequest)
return true;
}
bool
BluetoothRequestParent::DoRequest(
const GattClientStartNotificationsRequest& aRequest)
{
MOZ_ASSERT(mService);
MOZ_ASSERT(mRequestType == Request::TGattClientStartNotificationsRequest);
mService->GattClientStartNotificationsInternal(aRequest.appUuid(),
aRequest.servId(),
aRequest.charId(),
mReplyRunnable.get());
return true;
}
bool
BluetoothRequestParent::DoRequest(
const GattClientStopNotificationsRequest& aRequest)
{
MOZ_ASSERT(mService);
MOZ_ASSERT(mRequestType == Request::TGattClientStopNotificationsRequest);
mService->GattClientStopNotificationsInternal(aRequest.appUuid(),
aRequest.servId(),
aRequest.charId(),
mReplyRunnable.get());
return true;
}
bool
BluetoothRequestParent::DoRequest(const UnregisterGattClientRequest& aRequest)
{

Просмотреть файл

@ -173,6 +173,12 @@ protected:
bool
DoRequest(const DenyPairingConfirmationRequest& aRequest);
bool
DoRequest(const PinReplyRequest& aRequest);
bool
DoRequest(const SspReplyRequest& aRequest);
bool
DoRequest(const ConnectRequest& aRequest);
@ -226,6 +232,12 @@ protected:
bool
DoRequest(const DiscoverGattServicesRequest& aRequest);
bool
DoRequest(const GattClientStartNotificationsRequest& aRequest);
bool
DoRequest(const GattClientStopNotificationsRequest& aRequest);
bool
DoRequest(const UnregisterGattClientRequest& aRequest);

Просмотреть файл

@ -208,6 +208,28 @@ BluetoothServiceChildProcess::UpdateSdpRecords(const nsAString& aDeviceAddress,
MOZ_CRASH("This should never be called!");
}
void
BluetoothServiceChildProcess::PinReplyInternal(
const nsAString& aDeviceAddress, bool aAccept,
const nsAString& aPinCode, BluetoothReplyRunnable* aRunnable)
{
SendRequest(aRunnable,
PinReplyRequest(nsString(aDeviceAddress),
aAccept,
nsString(aPinCode)));
}
void
BluetoothServiceChildProcess::SspReplyInternal(
const nsAString& aDeviceAddress, BluetoothSspVariant aVariant,
bool aAccept, BluetoothReplyRunnable* aRunnable)
{
SendRequest(aRunnable,
SspReplyRequest(nsString(aDeviceAddress),
aVariant,
aAccept));
}
void
BluetoothServiceChildProcess::SetPinCodeInternal(
const nsAString& aDeviceAddress,
@ -405,6 +427,24 @@ BluetoothServiceChildProcess::DiscoverGattServicesInternal(
DiscoverGattServicesRequest(nsString(aAppUuid)));
}
void
BluetoothServiceChildProcess::GattClientStartNotificationsInternal(
const nsAString& aAppUuid, const BluetoothGattServiceId& aServId,
const BluetoothGattId& aCharId, BluetoothReplyRunnable* aRunnable)
{
SendRequest(aRunnable,
GattClientStartNotificationsRequest(nsString(aAppUuid), aServId, aCharId));
}
void
BluetoothServiceChildProcess::GattClientStopNotificationsInternal(
const nsAString& aAppUuid, const BluetoothGattServiceId& aServId,
const BluetoothGattId& aCharId, BluetoothReplyRunnable* aRunnable)
{
SendRequest(aRunnable,
GattClientStopNotificationsRequest(nsString(aAppUuid), aServId, aCharId));
}
void
BluetoothServiceChildProcess::UnregisterGattClientInternal(
int aClientIf, BluetoothReplyRunnable* aRunnable)

Просмотреть файл

@ -110,6 +110,18 @@ public:
BluetoothReplyRunnable* aRunnable)
override;
virtual void
PinReplyInternal(const nsAString& aDeviceAddress,
bool aAccept,
const nsAString& aPinCode,
BluetoothReplyRunnable* aRunnable) override;
virtual void
SspReplyInternal(const nsAString& aDeviceAddress,
BluetoothSspVariant aVariant,
bool aAccept,
BluetoothReplyRunnable* aRunnable) override;
virtual void
Connect(const nsAString& aDeviceAddress,
uint32_t aCod,
@ -206,6 +218,20 @@ public:
DiscoverGattServicesInternal(const nsAString& aAppUuid,
BluetoothReplyRunnable* aRunnable) override;
virtual void
GattClientStartNotificationsInternal(
const nsAString& aAppUuid,
const BluetoothGattServiceId& aServId,
const BluetoothGattId& aCharId,
BluetoothReplyRunnable* aRunnable) override;
virtual void
GattClientStopNotificationsInternal(
const nsAString& aAppUuid,
const BluetoothGattServiceId& aServId,
const BluetoothGattId& aCharId,
BluetoothReplyRunnable* aRunnable) override;
virtual void
UnregisterGattClientInternal(int aClientIf,
BluetoothReplyRunnable* aRunnable) override;

Просмотреть файл

@ -8,6 +8,8 @@ using mozilla::dom::bluetooth::BluetoothGattId
from "mozilla/dom/bluetooth/BluetoothCommon.h";
using mozilla::dom::bluetooth::BluetoothGattServiceId
from "mozilla/dom/bluetooth/BluetoothCommon.h";
using mozilla::dom::bluetooth::BluetoothSspVariant
from "mozilla/dom/bluetooth/BluetoothCommon.h";
using mozilla::dom::bluetooth::BluetoothStatus
from "mozilla/dom/bluetooth/BluetoothCommon.h";
@ -28,7 +30,9 @@ union BluetoothValue
nsString[];
uint8_t[];
BluetoothNamedValue[];
BluetoothGattId;
BluetoothGattId[];
BluetoothGattServiceId;
BluetoothGattServiceId[];
};

Просмотреть файл

@ -64,6 +64,20 @@ struct UnpairRequest
nsString address;
};
struct PinReplyRequest
{
nsString address;
bool accept;
nsString pinCode;
};
struct SspReplyRequest
{
nsString address;
BluetoothSspVariant variant;
bool accept;
};
struct SetPinCodeRequest
{
nsString path;
@ -193,6 +207,20 @@ struct DiscoverGattServicesRequest
nsString appUuid;
};
struct GattClientStartNotificationsRequest
{
nsString appUuid;
BluetoothGattServiceId servId;
BluetoothGattId charId;
};
struct GattClientStopNotificationsRequest
{
nsString appUuid;
BluetoothGattServiceId servId;
BluetoothGattId charId;
};
struct UnregisterGattClientRequest
{
int clientIf;
@ -215,6 +243,8 @@ union Request
StopDiscoveryRequest;
PairRequest;
UnpairRequest;
PinReplyRequest;
SspReplyRequest;
SetPinCodeRequest;
SetPasskeyRequest;
ConfirmPairingConfirmationRequest;
@ -239,6 +269,8 @@ union Request
ConnectGattClientRequest;
DisconnectGattClientRequest;
DiscoverGattServicesRequest;
GattClientStartNotificationsRequest;
GattClientStopNotificationsRequest;
UnregisterGattClientRequest;
GattClientReadRemoteRssiRequest;
};

Просмотреть файл

@ -753,15 +753,13 @@ function addEventHandlerForPairingRequest(aAdapter, aSpecifiedBdAddress) {
let device = evt.device;
if (!aSpecifiedBdAddress || device.address == aSpecifiedBdAddress) {
let confirm = true;
evt.handle.setPairingConfirmation(confirm).then(
evt.handle.accept().then(
function onResolve() {
log(" - 'setPairingConfirmation' resolve.");
log(" - 'accept' resolve.");
cleanupPairingListener(aAdapter.pairingReqs);
},
function onReject() {
log(" - 'setPairingConfirmation' reject.");
log(" - 'accept' reject.");
cleanupPairingListener(aAdapter.pairingReqs);
});
}
@ -772,7 +770,15 @@ function addEventHandlerForPairingRequest(aAdapter, aSpecifiedBdAddress) {
let device = evt.device;
if (!aSpecifiedBdAddress || device.address == aSpecifiedBdAddress) {
cleanupPairingListener(aAdapter.pairingReqs);
evt.handle.accept().then(
function onResolve() {
log(" - 'accept' resolve.");
cleanupPairingListener(aAdapter.pairingReqs);
},
function onReject() {
log(" - 'accept' reject.");
cleanupPairingListener(aAdapter.pairingReqs);
});
}
};
}

Просмотреть файл

@ -43,7 +43,7 @@
// - BluetoothPairingEvent.handle
//
// - BluetoothPairingHandle.setPinCode()
// - BluetoothPairingHandle.setPairingConfirmation()
// - BluetoothPairingHandle.accept()
//
///////////////////////////////////////////////////////////////////////////////

Просмотреть файл

@ -1425,6 +1425,8 @@ protected:
nsTArray<WebGLRefPtr<WebGLTexture> > mBoundCubeMapTextures;
nsTArray<WebGLRefPtr<WebGLTexture> > mBound3DTextures;
void ResolveTexturesForDraw() const;
WebGLRefPtr<WebGLProgram> mCurrentProgram;
RefPtr<const webgl::LinkedProgramInfo> mActiveProgramLinkInfo;

Просмотреть файл

@ -48,7 +48,9 @@ WebGLContext::DrawInstanced_check(const char* info)
return true;
}
bool WebGLContext::DrawArrays_check(GLint first, GLsizei count, GLsizei primcount, const char* info)
bool
WebGLContext::DrawArrays_check(GLint first, GLsizei count, GLsizei primcount,
const char* info)
{
if (first < 0 || count < 0) {
ErrorInvalidValue("%s: negative first or count", info);

Просмотреть файл

@ -240,6 +240,7 @@ WebGLContext::BindTexture(GLenum rawTarget, WebGLTexture* newTex)
default:
return ErrorInvalidEnumInfo("bindTexture: target", rawTarget);
}
const TexTarget target(rawTarget);
if (newTex) {
// silently ignore a deleted texture
@ -250,29 +251,16 @@ WebGLContext::BindTexture(GLenum rawTarget, WebGLTexture* newTex)
return ErrorInvalidOperation("bindTexture: this texture has already been bound to a different target");
}
const TexTarget target(rawTarget);
WebGLTextureFakeBlackStatus currentTexFakeBlackStatus = WebGLTextureFakeBlackStatus::NotNeeded;
if (*currentTexPtr) {
currentTexFakeBlackStatus = (*currentTexPtr)->ResolvedFakeBlackStatus();
}
WebGLTextureFakeBlackStatus newTexFakeBlackStatus = WebGLTextureFakeBlackStatus::NotNeeded;
if (newTex) {
newTexFakeBlackStatus = newTex->ResolvedFakeBlackStatus();
}
*currentTexPtr = newTex;
if (currentTexFakeBlackStatus != newTexFakeBlackStatus) {
SetFakeBlackStatus(WebGLContextFakeBlackStatus::Unknown);
}
MakeContextCurrent();
if (newTex)
if (newTex) {
SetFakeBlackStatus(WebGLContextFakeBlackStatus::Unknown);
newTex->Bind(target);
else
gl->fBindTexture(target.get(), 0 /* == texturename */);
} else {
gl->fBindTexture(target.get(), 0);
}
}
void WebGLContext::BlendEquation(GLenum mode)

Просмотреть файл

@ -7,6 +7,7 @@
#include "angle/ShaderLang.h"
#include "GLContext.h"
#include "mozilla/Preferences.h"
#include "MurmurHash3.h"
#include "nsPrintfCString.h"
#include "nsTArray.h"
@ -42,6 +43,18 @@ ChooseValidatorCompileOptions(const ShBuiltInResources& resources,
options |= SH_LIMIT_EXPRESSION_COMPLEXITY;
}
if (Preferences::GetBool("webgl.all-angle-options", false)) {
return options |
SH_VALIDATE_LOOP_INDEXING |
SH_UNROLL_FOR_LOOP_WITH_INTEGER_INDEX |
SH_UNROLL_FOR_LOOP_WITH_SAMPLER_ARRAY_INDEX |
SH_EMULATE_BUILT_IN_FUNCTIONS |
SH_CLAMP_INDIRECT_ARRAY_BOUNDS |
SH_UNFOLD_SHORT_CIRCUIT |
SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS |
SH_REGENERATE_STRUCT_NAMES;
}
#ifndef XP_MACOSX
// We want to do this everywhere, but to do this on Mac, we need
// to do it only on Mac OSX > 10.6 as this causes the shader

Просмотреть файл

@ -146,6 +146,8 @@ GetEventMessageName(uint32_t aMessage)
return "NS_COMPOSITION_CHANGE";
case NS_COMPOSITION_COMMIT_AS_IS:
return "NS_COMPOSITION_COMMIT_AS_IS";
case NS_COMPOSITION_COMMIT:
return "NS_COMPOSITION_COMMIT";
default:
return "unacceptable event message";
}

Просмотреть файл

@ -30,14 +30,20 @@ helper.addMessageListener("fail", function onFail(message) {
helper.addMessageListener("file.opened", onFileOpened);
helper.sendAsyncMessage("file.open", "test_bug1146116.txt");
function getGlobal(thing) {
return SpecialPowers.unwrap(SpecialPowers.Cu.getGlobalForObject(thing));
}
function onFileOpened(message) {
const file = message.domFile;
const elem = document.getElementById("file");
isnot(SpecialPowers.Cu.getGlobalForObject(elem), window,
is(getGlobal(elem), window,
"getGlobal() works as expected");
isnot(getGlobal(file), window,
"File from MessageManager is wrapped");
SpecialPowers.wrap(elem).mozSetFileArray([file]);
is(SpecialPowers.unwrap(SpecialPowers.Cu.getGlobalForObject(elem.files[0])),
window, "File read back from input element is not wrapped");
is(getGlobal(elem.files[0]), window,
"File read back from input element is not wrapped");
helper.addMessageListener("file.removed", onFileRemoved);
helper.sendAsyncMessage("file.remove", null);
}

Просмотреть файл

@ -49,6 +49,7 @@
#include "mozilla/layers/PCompositorChild.h"
#include "mozilla/layers/SharedBufferManagerChild.h"
#include "mozilla/net/NeckoChild.h"
#include "mozilla/plugins/PluginInstanceParent.h"
#include "mozilla/plugins/PluginModuleParent.h"
#if defined(MOZ_CONTENT_SANDBOX)
@ -2672,6 +2673,26 @@ ContentChild::GetBrowserOrId(TabChild* aTabChild)
}
}
bool
ContentChild::RecvUpdateWindow(const uintptr_t& aChildId)
{
#if defined(XP_WIN)
NS_ASSERTION(aChildId, "Expected child hwnd value for remote plugin instance.");
mozilla::plugins::PluginInstanceParent* parentInstance =
mozilla::plugins::PluginInstanceParent::LookupPluginInstanceByID(aChildId);
NS_ASSERTION(parentInstance, "Expected matching plugin instance");
if (parentInstance) {
// sync! update call to the plugin instance that forces the
// plugin to paint its child window.
parentInstance->CallUpdateWindow();
}
return true;
#else
NS_NOTREACHED("ContentChild::RecvUpdateWindow calls unexpected on this platform.");
return false;
#endif
}
// This code goes here rather than nsGlobalWindow.cpp because nsGlobalWindow.cpp
// can't include ContentChild.h since it includes windows.h.

Просмотреть файл

@ -384,6 +384,7 @@ public:
const base::ProcessId& aProcessId) override;
virtual bool RecvLoadPluginResult(const uint32_t& aPluginId,
const bool& aResult) override;
virtual bool RecvUpdateWindow(const uintptr_t& aChildId) override;
virtual bool RecvStartProfiler(const uint32_t& aEntries,
const double& aInterval,

Просмотреть файл

@ -874,6 +874,27 @@ ContentParent::GetInitialProcessPriority(Element* aFrameElement)
PROCESS_PRIORITY_FOREGROUND;
}
#if defined(XP_WIN)
extern const wchar_t* kPluginWidgetContentParentProperty;
/*static*/ void
ContentParent::SendAsyncUpdate(nsIWidget* aWidget)
{
if (!aWidget || aWidget->Destroyed()) {
return;
}
printf_stderr("TabParent::SendAsyncUpdate()\n");
// Fire off an async request to the plugin to paint its window
HWND hwnd = (HWND)aWidget->GetNativeData(NS_NATIVE_WINDOW);
NS_ASSERTION(hwnd, "Expected valid hwnd value.");
ContentParent* cp = reinterpret_cast<ContentParent*>(
::GetPropW(hwnd, kPluginWidgetContentParentProperty));
if (cp && !cp->IsDestroyed()) {
cp->SendUpdateWindow((uintptr_t)hwnd);
}
}
#endif // defined(XP_WIN)
bool
ContentParent::PreallocatedProcessReady()
{

Просмотреть файл

@ -35,6 +35,7 @@ class nsIDumpGCAndCCLogsCallback;
class nsIMemoryReporter;
class nsITimer;
class ParentIdleListener;
class nsIWidget;
namespace mozilla {
class PRemoteSpellcheckEngineParent;
@ -144,6 +145,20 @@ public:
static void NotifyUpdatedDictionaries();
#if defined(XP_WIN)
/**
* Windows helper for firing off an update window request to a plugin
* instance.
*
* aWidget - the eWindowType_plugin_ipc_chrome widget associated with
* this plugin window.
*/
static void SendAsyncUpdate(nsIWidget* aWidget);
#endif
// Let managees query if it is safe to send messages.
bool IsDestroyed() { return !mIPCOpen; }
virtual bool RecvCreateChildProcess(const IPCTabContext& aContext,
const hal::ProcessPriority& aPriority,
const TabId& aOpenerTabId,

Просмотреть файл

@ -27,6 +27,7 @@ using class mozilla::gfx::Matrix from "mozilla/gfx/Matrix.h";
using struct gfxSize from "gfxPoint.h";
using CSSRect from "Units.h";
using LayoutDeviceIntRect from "Units.h";
using mozilla::LayoutDeviceIntPoint from "Units.h";
using ScreenIntSize from "Units.h";
using struct mozilla::layers::FrameMetrics from "FrameMetrics.h";
using struct mozilla::layers::ScrollableLayerGuid from "FrameMetrics.h";
@ -332,6 +333,14 @@ parent:
sync IsParentWindowMainWidgetVisible() returns (bool visible);
/**
* Content process forward from PuppetWidget for synth mouse move
* events.
*
* aPoint a synth point relative to the window
*/
sync SynthesizeNativeMouseMove(LayoutDeviceIntPoint aPoint);
/**
* Gets the DPI of the screen corresponding to this browser.
*/

Просмотреть файл

@ -582,6 +582,12 @@ child:
async LoadProcessScript(nsString url);
/**
* Requests a full native update of a native plugin child window. This is
* a Windows specific call.
*/
async UpdateWindow(uintptr_t aChildId);
parent:
/**
* Tell the parent process a new accessible document has been created.

Просмотреть файл

@ -31,11 +31,7 @@ sync protocol PPluginWidget {
parent:
async __delete__();
parent:
sync Create() returns (nsresult aResult);
async Destroy();
async SetFocus(bool aRaise);
/**
@ -45,18 +41,6 @@ parent:
* native HWND of the plugin widget.
*/
sync GetNativePluginPort() returns (uintptr_t value);
child:
/**
* Event indicating the parent is shutting down.
* aWhichSide - indicates which side intititated the shutdown.
*/
async ParentShutdown(uint16_t aWhichSide);
/**
* Requests a full update of the plugin window.
*/
async UpdateWindow(uintptr_t aChildId);
};
}

Просмотреть файл

@ -267,7 +267,8 @@ public:
Create(nsIContentChild* aManager, const TabId& aTabId, const TabContext& aContext, uint32_t aChromeFlags);
bool IsRootContentDocument();
// Let managees query if it is safe to send messages.
bool IsDestroyed() { return mDestroyed; }
const TabId GetTabId() const {
MOZ_ASSERT(mUniqueId != 0);
return mUniqueId;

Просмотреть файл

@ -2233,6 +2233,17 @@ TabParent::RecvIsParentWindowMainWidgetVisible(bool* aIsVisible)
return NS_SUCCEEDED(rv);
}
bool
TabParent::RecvSynthesizeNativeMouseMove(const mozilla::LayoutDeviceIntPoint& aPoint)
{
// The widget associated with the browser window
nsCOMPtr<nsIWidget> widget = GetWidget();
if (widget) {
widget->SynthesizeNativeMouseMove(aPoint);
}
return true;
}
bool
TabParent::RecvGetDPI(float* aValue)
{

Просмотреть файл

@ -198,6 +198,7 @@ public:
virtual bool RecvSetBackgroundColor(const nscolor& aValue) override;
virtual bool RecvSetStatus(const uint32_t& aType, const nsString& aStatus) override;
virtual bool RecvIsParentWindowMainWidgetVisible(bool* aIsVisible) override;
virtual bool RecvSynthesizeNativeMouseMove(const mozilla::LayoutDeviceIntPoint& aPoint) override;
virtual bool RecvShowTooltip(const uint32_t& aX, const uint32_t& aY, const nsString& aTooltip) override;
virtual bool RecvHideTooltip() override;
virtual bool RecvGetDPI(float* aValue) override;

Просмотреть файл

@ -29,6 +29,13 @@ couldNotProcessUnknownDirective = Couldn't process unknown directive '%1$S'
# LOCALIZATION NOTE (ignoringUnknownOption):
# %1$S is the option that could not be understood
ignoringUnknownOption = Ignoring unknown option %1$S
# LOCALIZATION NOTE (ignoringDuplicateSrc):
# %1$S defines the duplicate src
ignoringDuplicateSrc = Ignoring duplicate source %1$S
# LOCALIZATION NOTE (ignoringSrcWithinScriptSrc):
# %1$S is the ignored src
# script-src is a directive name and should not be localized
ignoringSrcWithinScriptSrc = Ignoring "%1$S" within script-src: nonce-source or hash-source specified
# LOCALIZATION NOTE (reportURInotHttpsOrHttp2):
# %1$S is the ETLD of the report URI that is not HTTP or HTTPS
reportURInotHttpsOrHttp2 = The report URI (%1$S) should be an HTTP or HTTPS URI.

Просмотреть файл

@ -1,8 +1,7 @@
/* 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/. */
/*
/*
* ManifestProcessor
* Implementation of processing algorithms from:
* http://www.w3.org/2008/webapps/manifest/
@ -11,347 +10,359 @@
* or individual parts of a manifest object. A manifest is just a
* standard JS object that has been cleaned up.
*
* .process(jsonText, manifestURL, docURL);
* .process({jsonText,manifestURL,docURL});
*
* TODO: The constructor should accept the UA's supported orientations.
* TODO: The constructor should accept the UA's supported display modes.
* TODO: hook up developer tools to issueDeveloperWarning (1086997).
* TODO: hook up developer tools to console. (1086997).
*/
/*globals Components*/
/*exported EXPORTED_SYMBOLS */
/*JSLint options in comment below: */
/*globals Components, XPCOMUtils*/
'use strict';
this.EXPORTED_SYMBOLS = ['ManifestProcessor'];
const imports = {};
const {
utils: Cu,
classes: Cc,
interfaces: Ci
} = Components;
const imports = {};
Cu.import('resource://gre/modules/Services.jsm', imports);
Cu.import('resource://gre/modules/XPCOMUtils.jsm');
Cu.importGlobalProperties(['URL']);
const securityManager = imports.Services.scriptSecurityManager;
const netutil = Cc['@mozilla.org/network/util;1'].getService(Ci.nsINetUtil);
const defaultDisplayMode = 'browser';
const displayModes = new Set([
'fullscreen',
'standalone',
'minimal-ui',
XPCOMUtils.defineLazyModuleGetter(imports, 'Services',
'resource://gre/modules/Services.jsm');
imports.netutil = Cc['@mozilla.org/network/util;1'].getService(Ci.nsINetUtil);
// Helper function extracts values from manifest members
// and reports conformance violations.
function extractValue({
objectName,
object,
property,
expectedType,
trim
}, console) {
const value = object[property];
const isArray = Array.isArray(value);
// We need to special-case "array", as it's not a JS primitive.
const type = (isArray) ? 'array' : typeof value;
if (type !== expectedType) {
if (type !== 'undefined') {
let msg = `Expected the ${objectName}'s ${property} `;
msg += `member to a be a ${expectedType}.`;
console.log(msg);
}
return undefined;
}
// Trim string and returned undefined if the empty string.
const shouldTrim = expectedType === 'string' && value && trim;
if (shouldTrim) {
return value.trim() || undefined;
}
return value;
}
const displayModes = new Set(['fullscreen', 'standalone', 'minimal-ui',
'browser'
]);
const orientationTypes = new Set([
'any',
'natural',
'landscape',
'portrait',
'portrait-primary',
'portrait-secondary',
'landscape-primary',
const orientationTypes = new Set(['any', 'natural', 'landscape', 'portrait',
'portrait-primary', 'portrait-secondary', 'landscape-primary',
'landscape-secondary'
]);
const {
ConsoleAPI
} = Cu.import('resource://gre/modules/devtools/Console.jsm');
this.ManifestProcessor = function ManifestProcessor() {};
/**
* process method: processes json text into a clean manifest
* that conforms with the W3C specification.
* @param jsonText - the JSON string to be processd.
* @param manifestURL - the URL of the manifest, to resolve URLs.
* @param docURL - the URL of the owner doc, for security checks
*/
this.ManifestProcessor.prototype.process = function({
jsonText: jsonText,
manifestURL: manifestURL,
docLocation: docURL
}) {
/*
* This helper function is used to extract values from manifest members.
* It also reports conformance violations.
*/
function extractValue(obj) {
let value = obj.object[obj.property];
//we need to special-case "array", as it's not a JS primitive
const type = (Array.isArray(value)) ? 'array' : typeof value;
function ManifestProcessor() {}
if (type !== obj.expectedType) {
if (type !== 'undefined') {
let msg = `Expected the ${obj.objectName}'s ${obj.property}`;
msg += `member to a be a ${obj.expectedType}.`;
issueDeveloperWarning(msg);
}
value = undefined;
// Static getters
Object.defineProperties(ManifestProcessor, {
'defaultDisplayMode': {
get: function() {
return 'browser';
}
},
'displayModes': {
get: function() {
return displayModes;
}
},
'orientationTypes': {
get: function() {
return orientationTypes;
}
return value;
}
});
function issueDeveloperWarning(msg) {
//https://bugzilla.mozilla.org/show_bug.cgi?id=1086997
}
ManifestProcessor.prototype = {
function processNameMember(manifest) {
const obj = {
objectName: 'manifest',
object: manifest,
property: 'name',
expectedType: 'string'
// process method: processes json text into a clean manifest
// that conforms with the W3C specification. Takes an object
// expecting the following dictionary items:
// * jsonText: the JSON string to be processd.
// * manifestURL: the URL of the manifest, to resolve URLs.
// * docURL: the URL of the owner doc, for security checks.
process({
jsonText, manifestURL, docURL
}) {
const console = new ConsoleAPI({
prefix: 'Web Manifest: '
});
let rawManifest = {};
try {
rawManifest = JSON.parse(jsonText);
} catch (e) {}
if (typeof rawManifest !== 'object' || rawManifest === null) {
let msg = 'Manifest needs to be an object.';
console.warn(msg);
rawManifest = {};
}
const processedManifest = {
start_url: processStartURLMember(rawManifest, manifestURL, docURL),
display: processDisplayMember(rawManifest),
orientation: processOrientationMember(rawManifest),
name: processNameMember(rawManifest),
icons: IconsProcessor.process(rawManifest, manifestURL, console),
short_name: processShortNameMember(rawManifest),
};
let value = extractValue(obj);
return (value) ? value.trim() : value;
}
processedManifest.scope = processScopeMember(rawManifest, manifestURL,
docURL, processedManifest.start_url);
return processedManifest;
function processShortNameMember(manifest) {
const obj = {
objectName: 'manifest',
object: manifest,
property: 'short_name',
expectedType: 'string'
};
let value = extractValue(obj);
return (value) ? value.trim() : value;
}
function processOrientationMember(manifest) {
const obj = {
objectName: 'manifest',
object: manifest,
property: 'orientation',
expectedType: 'string'
};
let value = extractValue(obj);
value = (value) ? value.trim() : undefined;
//The spec special-cases orientation to return the empty string
return (orientationTypes.has(value)) ? value : '';
}
function processDisplayMember(manifest) {
const obj = {
objectName: 'manifest',
object: manifest,
property: 'display',
expectedType: 'string'
};
let value = extractValue(obj);
value = (value) ? value.trim() : value;
return (displayModes.has(value)) ? value : defaultDisplayMode;
}
function processScopeMember(manifest, manifestURL, docURL, startURL) {
const spec = {
function processNameMember(aManifest) {
const spec = {
objectName: 'manifest',
object: manifest,
object: aManifest,
property: 'name',
expectedType: 'string',
trim: true
};
return extractValue(spec, console);
}
function processShortNameMember(aManifest) {
const spec = {
objectName: 'manifest',
object: aManifest,
property: 'short_name',
expectedType: 'string',
trim: true
};
return extractValue(spec, console);
}
function processOrientationMember(aManifest) {
const spec = {
objectName: 'manifest',
object: aManifest,
property: 'orientation',
expectedType: 'string',
trim: true
};
const value = extractValue(spec, console);
if (ManifestProcessor.orientationTypes.has(value)) {
return value;
}
// The spec special-cases orientation to return the empty string.
return '';
}
function processDisplayMember(aManifest) {
const spec = {
objectName: 'manifest',
object: aManifest,
property: 'display',
expectedType: 'string',
trim: true
};
const value = extractValue(spec, console);
if (ManifestProcessor.displayModes.has(value)) {
return value;
}
return ManifestProcessor.defaultDisplayMode;
}
function processScopeMember(aManifest, aManifestURL, aDocURL, aStartURL) {
const spec = {
objectName: 'manifest',
object: aManifest,
property: 'scope',
expectedType: 'string',
dontTrim: true
},
value = extractValue(spec);
let scopeURL;
try {
scopeURL = new URL(value, manifestURL);
} catch (e) {
let msg = 'The URL of scope is invalid.';
issueDeveloperWarning(msg);
return undefined;
trim: false
};
const value = extractValue(spec, console);
let scopeURL;
try {
scopeURL = new URL(value, aManifestURL);
} catch (e) {
let msg = 'The URL of scope is invalid.';
console.warn(msg);
return undefined;
}
if (scopeURL.origin !== aDocURL.origin) {
let msg = 'Scope needs to be same-origin as Document.';
console.warn(msg);
return undefined;
}
// If start URL is not within scope of scope URL:
let isSameOrigin = aStartURL && aStartURL.origin !== scopeURL.origin;
if (isSameOrigin || !aStartURL.pathname.startsWith(scopeURL.pathname)) {
let msg =
'The start URL is outside the scope, so scope is invalid.';
console.warn(msg);
return undefined;
}
return scopeURL;
}
if (scopeURL.origin !== docURL.origin) {
let msg = 'Scope needs to be same-origin as Document.';
issueDeveloperWarning(msg);
return undefined;
}
//If start URL is not within scope of scope URL:
if (startURL && startURL.origin !== scopeURL.origin || !startURL.pathname.startsWith(scopeURL.pathname)) {
let msg = 'The start URL is outside the scope, so scope is invalid.';
issueDeveloperWarning(msg);
return undefined;
}
return scopeURL;
}
function processStartURLMember(manifest, manifestURL, docURL) {
const obj = {
objectName: 'manifest',
object: manifest,
property: 'start_url',
expectedType: 'string'
};
let value = extractValue(obj),
result = new URL(docURL),
targetURI = makeURI(result),
sameOrigin = false,
potentialResult,
referrerURI;
if (value === undefined || value === '') {
return result;
}
try {
potentialResult = new URL(value, manifestURL);
} catch (e) {
issueDeveloperWarning('Invalid URL.');
return result;
}
referrerURI = makeURI(potentialResult);
try {
securityManager.checkSameOriginURI(referrerURI, targetURI, false);
sameOrigin = true;
} catch (e) {}
if (!sameOrigin) {
let msg = 'start_url must be same origin as document.';
issueDeveloperWarning(msg);
} else {
result = potentialResult;
}
return result;
//Converts a URL to a Gecko URI
function makeURI(webURL) {
return imports.Services.io.newURI(webURL.toString(), null, null);
}
}
//Constants used by IconsProcessor
const onlyDecimals = /^\d+$/,
anyRegEx = new RegExp('any', 'i');
function IconsProcessor() {}
IconsProcessor.prototype.processIcons = function(manifest, baseURL) {
const obj = {
function processStartURLMember(aManifest, aManifestURL, aDocURL) {
const spec = {
objectName: 'manifest',
object: manifest,
property: 'icons',
expectedType: 'array'
},
icons = [];
let value = extractValue(obj);
if (Array.isArray(value)) {
//filter out icons with no "src" or src is empty string
let processableIcons = value.filter(
icon => icon && Object.prototype.hasOwnProperty.call(icon, 'src') && icon.src !== ''
);
for (let potentialIcon of processableIcons) {
let src = processSrcMember(potentialIcon, baseURL)
if(src !== undefined){
let icon = {
src: src,
type: processTypeMember(potentialIcon),
sizes: processSizesMember(potentialIcon),
density: processDensityMember(potentialIcon)
};
icons.push(icon);
}
object: aManifest,
property: 'start_url',
expectedType: 'string',
trim: false
};
let result = new URL(aDocURL);
const value = extractValue(spec, console);
if (value === undefined || value === '') {
return result;
}
let potentialResult;
try {
potentialResult = new URL(value, aManifestURL);
} catch (e) {
console.warn('Invalid URL.');
return result;
}
if (potentialResult.origin !== aDocURL.origin) {
let msg = 'start_url must be same origin as document.';
console.warn(msg);
} else {
result = potentialResult;
}
}
return icons;
function processTypeMember(icon) {
const charset = {},
hadCharset = {},
obj = {
objectName: 'icon',
object: icon,
property: 'type',
expectedType: 'string'
};
let value = extractValue(obj),
isParsable = (typeof value === 'string' && value.length > 0);
value = (isParsable) ? netutil.parseContentType(value.trim(), charset, hadCharset) : undefined;
return (value === '') ? undefined : value;
}
function processDensityMember(icon) {
const hasDensity = Object.prototype.hasOwnProperty.call(icon, 'density'),
rawValue = (hasDensity) ? icon.density : undefined,
value = parseFloat(rawValue),
result = (Number.isNaN(value) || value === +Infinity || value <= 0) ? 1.0 : value;
return result;
}
}
};
this.ManifestProcessor = ManifestProcessor;
function processSrcMember(icon, baseURL) {
const obj = {
objectName: 'icon',
object: icon,
property: 'src',
expectedType: 'string'
},
value = extractValue(obj);
let url;
if (typeof value === 'string' && value.trim() !== '') {
try {
url = new URL(value, baseURL);
} catch (e) {}
}
return url;
function IconsProcessor() {}
// Static getters
Object.defineProperties(IconsProcessor,{
'onlyDecimals': {
get: function() {
return /^\d+$/;
}
function processSizesMember(icon) {
const sizes = new Set(),
obj = {
objectName: 'icon',
object: icon,
property: 'sizes',
expectedType: 'string'
};
let value = extractValue(obj);
value = (value) ? value.trim() : value;
if (value) {
//split on whitespace and filter out invalid values
let validSizes = value.split(/\s+/).filter(isValidSizeValue);
validSizes.forEach((size) => sizes.add(size));
}
return sizes;
/*
* Implementation of HTML's link@size attribute checker
*/
function isValidSizeValue(size) {
if (anyRegEx.test(size)) {
return true;
}
size = size.toLowerCase();
if (!size.contains('x') || size.indexOf('x') !== size.lastIndexOf('x')) {
return false;
}
//split left of x for width, after x for height
const width = size.substring(0, size.indexOf('x'));
const height = size.substring(size.indexOf('x') + 1, size.length);
const isValid = !(height.startsWith('0') || width.startsWith('0') || !onlyDecimals.test(width + height));
return isValid;
}
},
'anyRegEx': {
get: function() {
return new RegExp('any', 'i');
}
}
});
IconsProcessor.process = function(aManifest, aBaseURL, console) {
const spec = {
objectName: 'manifest',
object: aManifest,
property: 'icons',
expectedType: 'array',
trim: false
};
const icons = [];
const value = extractValue(spec, console);
if (Array.isArray(value)) {
// Filter out icons whose "src" is not useful.
value.filter(item => !!processSrcMember(item, aBaseURL))
.map(toIconObject)
.forEach(icon => icons.push(icon));
}
return icons;
function processIconsMember(manifest, manifestURL) {
const iconsProcessor = new IconsProcessor();
return iconsProcessor.processIcons(manifest, manifestURL);
function toIconObject(aIconData) {
return {
src: processSrcMember(aIconData, aBaseURL),
type: processTypeMember(aIconData),
sizes: processSizesMember(aIconData),
density: processDensityMember(aIconData)
};
}
//Processing starts here!
let manifest = {};
try {
manifest = JSON.parse(jsonText);
if (typeof manifest !== 'object' || manifest === null) {
let msg = 'Manifest needs to be an object.';
issueDeveloperWarning(msg);
manifest = {};
function processTypeMember(aIcon) {
const charset = {};
const hadCharset = {};
const spec = {
objectName: 'icon',
object: aIcon,
property: 'type',
expectedType: 'string',
trim: true
};
let value = extractValue(spec, console);
if (value) {
value = imports.netutil.parseContentType(value, charset, hadCharset);
}
} catch (e) {
issueDeveloperWarning(e);
return value || undefined;
}
const processedManifest = {
start_url: processStartURLMember(manifest, manifestURL, docURL),
display: processDisplayMember(manifest),
orientation: processOrientationMember(manifest),
name: processNameMember(manifest),
icons: processIconsMember(manifest, manifestURL),
short_name: processShortNameMember(manifest)
};
processedManifest.scope = processScopeMember(manifest, manifestURL, docURL, processedManifest.start_url);
return processedManifest;
};
function processDensityMember(aIcon) {
const value = parseFloat(aIcon.density);
const validNum = Number.isNaN(value) || value === +Infinity || value <=
0;
return (validNum) ? 1.0 : value;
}
function processSrcMember(aIcon, aBaseURL) {
const spec = {
objectName: 'icon',
object: aIcon,
property: 'src',
expectedType: 'string',
trim: false
};
const value = extractValue(spec, console);
let url;
if (value && value.length) {
try {
url = new URL(value, aBaseURL);
} catch (e) {}
}
return url;
}
function processSizesMember(aIcon) {
const sizes = new Set(),
spec = {
objectName: 'icon',
object: aIcon,
property: 'sizes',
expectedType: 'string',
trim: true
},
value = extractValue(spec, console);
if (value) {
// Split on whitespace and filter out invalid values.
value.split(/\s+/)
.filter(isValidSizeValue)
.forEach(size => sizes.add(size));
}
return sizes;
// Implementation of HTML's link@size attribute checker.
function isValidSizeValue(aSize) {
const size = aSize.toLowerCase();
if (IconsProcessor.anyRegEx.test(aSize)) {
return true;
}
if (!size.contains('x') || size.indexOf('x') !== size.lastIndexOf('x')) {
return false;
}
// Split left of x for width, after x for height.
const widthAndHeight = size.split('x');
const w = widthAndHeight.shift();
const h = widthAndHeight.join('x');
const validStarts = !w.startsWith('0') && !h.startsWith('0');
const validDecimals = IconsProcessor.onlyDecimals.test(w + h);
return (validStarts && validDecimals);
}
}
};

Просмотреть файл

@ -6,7 +6,7 @@
const bsp = SpecialPowers.Cu.import('resource://gre/modules/ManifestProcessor.jsm'),
processor = new bsp.ManifestProcessor(),
manifestURL = new URL(document.location.origin + '/manifest.json'),
docLocation = new URL('', document.location.origin),
docURL = new URL('', document.location.origin),
seperators = '\u2028\u2029\u0020\u00A0\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000',
lineTerminators = '\u000D\u000A\u2028\u2029',
whiteSpace = `${seperators}${lineTerminators}`,
@ -16,5 +16,5 @@ const bsp = SpecialPowers.Cu.import('resource://gre/modules/ManifestProcessor.js
data = {
jsonText: '{}',
manifestURL: manifestURL,
docLocation: docLocation
docURL: docURL
};

Просмотреть файл

@ -20,7 +20,7 @@ invalidJson.forEach((testString) => {
var expected = `Expect to recover from invalid JSON: ${testString}`;
data.jsonText = testString;
var result = processor.process(data);
SimpleTest.ok(result.start_url.href === docLocation.href, true, expected);
SimpleTest.ok(result.start_url.href === docURL.href, true, expected);
});
var validButUnhelpful = ["1", 1, "", "[{}]", "null"];
@ -28,7 +28,7 @@ validButUnhelpful.forEach((testString) => {
var expected = `Expect to recover from invalid JSON: ${testString}`;
data.jsonText = testString;
var result = processor.process(data);
SimpleTest.ok(result.start_url.href === docLocation.href, true, expected);
SimpleTest.ok(result.start_url.href === docURL.href, true, expected);
});
</script>
</head>

Просмотреть файл

@ -21,7 +21,7 @@ typeTests.forEach((type) => {
start_url: type
});
var result = processor.process(data);
ise(result.start_url.toString(), docLocation.toString(), expected);
ise(result.start_url.toString(), docURL.toString(), expected);
});
//Not same origin
@ -30,7 +30,7 @@ data.jsonText = JSON.stringify({
start_url: 'http://not-same-origin'
});
var result = processor.process(data);
ise(result.start_url.toString(), docLocation.toString(), expected);
ise(result.start_url.toString(), docURL.toString(), expected);
//Empty string test
var expected = `Expect empty string for start_url to become document's URL.`;
@ -38,7 +38,7 @@ data.jsonText = JSON.stringify({
start_url: ''
});
var result = processor.process(data);
ise(result.start_url.toString(), docLocation.toString(), expected);
ise(result.start_url.toString(), docURL.toString(), expected);
//Resolve URLs relative to manfiest
var URLs = ['path', '/path', '../../path',

Просмотреть файл

@ -0,0 +1 @@
Cache-Control: no-store

Просмотреть файл

@ -0,0 +1 @@
Cache-Control: no-store

Просмотреть файл

@ -0,0 +1 @@
Cache-Control: no-store

Просмотреть файл

@ -0,0 +1 @@
Cache-Control: no-store

Просмотреть файл

@ -0,0 +1 @@
Cache-Control: no-store

Просмотреть файл

@ -0,0 +1 @@
Cache-Control: no-store

Просмотреть файл

@ -0,0 +1 @@
Cache-Control: no-store

Просмотреть файл

@ -0,0 +1 @@
Cache-Control: no-store

Просмотреть файл

@ -0,0 +1 @@
Cache-Control: no-store

Просмотреть файл

@ -0,0 +1 @@
Cache-Control: no-store

Просмотреть файл

@ -0,0 +1 @@
Cache-Control: no-store

Просмотреть файл

@ -0,0 +1 @@
Cache-Control: no-store

Просмотреть файл

@ -0,0 +1 @@
Cache-Control: no-store

Просмотреть файл

@ -0,0 +1 @@
Cache-Control: no-store

Просмотреть файл

@ -0,0 +1 @@
Cache-Control: no-store

Просмотреть файл

@ -0,0 +1 @@
Cache-Control: no-store

Просмотреть файл

@ -0,0 +1 @@
Cache-Control: no-store

Просмотреть файл

@ -0,0 +1 @@
Cache-Control: no-store

Просмотреть файл

@ -0,0 +1 @@
Cache-Control: no-store

Просмотреть файл

@ -0,0 +1 @@
Cache-Control: no-store

Просмотреть файл

@ -0,0 +1 @@
Cache-Control: no-store

Просмотреть файл

@ -0,0 +1 @@
Cache-Control: no-store

Просмотреть файл

@ -0,0 +1 @@
Cache-Control: no-store

Просмотреть файл

@ -0,0 +1 @@
Cache-Control: no-store

Просмотреть файл

@ -0,0 +1 @@
Cache-Control: no-store

Просмотреть файл

@ -0,0 +1 @@
Cache-Control: no-store

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше