mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-01-19 01:10:22 +00:00
Merge m-c to inbound.
This commit is contained in:
commit
0667febab1
@ -1,4 +1,4 @@
|
||||
{
|
||||
"revision": "2977ae6150d723b2763e9e76da00aa1fb3c31678",
|
||||
"revision": "23fea49fdb66496bd9b1a3e8cbe5b9dfaf9b88c1",
|
||||
"repo_path": "/integration/gaia-central"
|
||||
}
|
||||
|
@ -245,7 +245,7 @@
|
||||
<menupopup id="toolbar-context-menu"
|
||||
onpopupshowing="onViewToolbarsPopupShowing(event, document.getElementById('viewToolbarsMenuSeparator'));">
|
||||
<menuitem oncommand="gCustomizeMode.addToPanel(document.popupNode)"
|
||||
accesskey="&customizeMenu.addToPanel.accesskey;"
|
||||
accesskey="&customizeMenu.moveToPanel.accesskey;"
|
||||
label="&customizeMenu.moveToPanel.label;"
|
||||
class="customize-context-moveToPanel"/>
|
||||
<menuitem oncommand="gCustomizeMode.removeFromArea(document.popupNode)"
|
||||
|
@ -37,6 +37,10 @@ let UI = {
|
||||
},
|
||||
|
||||
onUnload: function() {
|
||||
for (let [target, toolbox] of this._handledTargets) {
|
||||
toolbox.destroy();
|
||||
}
|
||||
|
||||
window.removeEventListener("unload", this.onUnload);
|
||||
window.removeEventListener("message", this.onMessage);
|
||||
if (this.connection) {
|
||||
@ -62,6 +66,7 @@ let UI = {
|
||||
this.selectTab("projects");
|
||||
break;
|
||||
case "toolbox-raise":
|
||||
window.top.focus();
|
||||
this.selectTab(json.uid);
|
||||
break;
|
||||
case "toolbox-close":
|
||||
@ -158,7 +163,8 @@ let UI = {
|
||||
|
||||
openAndShowToolboxForTarget: function(target, name, icon) {
|
||||
let host = devtools.Toolbox.HostType.CUSTOM;
|
||||
if (!this._handledTargets.has(target)) {
|
||||
let toolbox = gDevTools.getToolbox(target);
|
||||
if (!toolbox) {
|
||||
let uid = "uid" + this._toolboxTabCursor++;
|
||||
let iframe = this.createToolboxTab(name, icon, uid);
|
||||
let options = { customIframe: iframe , uid: uid };
|
||||
@ -170,12 +176,6 @@ let UI = {
|
||||
});
|
||||
});
|
||||
} else {
|
||||
let toolbox = this._handledTargets.get(target);
|
||||
if (!toolbox) {
|
||||
// Target is handled, but toolbox is still being
|
||||
// created.
|
||||
return promise.resolve(null);
|
||||
}
|
||||
return gDevTools.showToolbox(target, null, host);
|
||||
}
|
||||
}
|
||||
|
@ -238,7 +238,7 @@ StyleEditorUI.prototype = {
|
||||
{
|
||||
let onFileSelected = function(file) {
|
||||
if (!file) {
|
||||
this.emit("error", LOAD_ERROR);
|
||||
// nothing selected
|
||||
return;
|
||||
}
|
||||
NetUtil.asyncFetch(file, (stream, status) => {
|
||||
|
@ -413,6 +413,37 @@ nsFrameLoader::ReallyStartLoading()
|
||||
return rv;
|
||||
}
|
||||
|
||||
class DelayedStartLoadingRunnable : public nsRunnable
|
||||
{
|
||||
public:
|
||||
DelayedStartLoadingRunnable(nsFrameLoader* aFrameLoader)
|
||||
: mFrameLoader(aFrameLoader)
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
// Retry the request.
|
||||
mFrameLoader->ReallyStartLoading();
|
||||
|
||||
// We delayed nsFrameLoader::ReallyStartLoading() after the child process is
|
||||
// ready and might not be able to notify the remote browser in
|
||||
// UpdatePositionAndSize() when reflow finished. Retrigger reflow.
|
||||
nsIFrame* frame = mFrameLoader->GetPrimaryFrameOfOwningContent();
|
||||
if (!frame) {
|
||||
return NS_OK;
|
||||
}
|
||||
frame->InvalidateFrame();
|
||||
frame->PresContext()->PresShell()->
|
||||
FrameNeedsReflow(frame, nsIPresShell::eResize, NS_FRAME_IS_DIRTY);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
nsRefPtr<nsFrameLoader> mFrameLoader;
|
||||
};
|
||||
|
||||
nsresult
|
||||
nsFrameLoader::ReallyStartLoadingInternal()
|
||||
{
|
||||
@ -427,6 +458,13 @@ nsFrameLoader::ReallyStartLoadingInternal()
|
||||
|
||||
if (mRemoteFrame) {
|
||||
if (!mRemoteBrowser) {
|
||||
if (Preferences::GetBool("dom.ipc.processPrelaunch.enabled", false) &&
|
||||
!ContentParent::PreallocatedProcessReady()) {
|
||||
ContentParent::RunAfterPreallocatedProcessReady(
|
||||
new DelayedStartLoadingRunnable(this));
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
TryRemoteBrowser();
|
||||
|
||||
if (!mRemoteBrowser) {
|
||||
|
@ -97,7 +97,7 @@ class MediaRecorder::Session: public nsIObserver
|
||||
nsRefPtr<Session> mSession;
|
||||
};
|
||||
|
||||
// Record thread task.
|
||||
// Record thread task and it run in Media Encoder thread.
|
||||
// Fetch encoded Audio/Video data from MediaEncoder.
|
||||
class ExtractRunnable : public nsRunnable
|
||||
{
|
||||
@ -114,7 +114,7 @@ class MediaRecorder::Session: public nsIObserver
|
||||
}
|
||||
|
||||
private:
|
||||
nsRefPtr<Session> mSession;
|
||||
Session* mSession;
|
||||
};
|
||||
|
||||
// For Ensure recorder has tracks to record.
|
||||
|
@ -919,8 +919,8 @@ BrowserElementChild.prototype = {
|
||||
this._pendingSetInputMethodActive.push(data);
|
||||
return;
|
||||
}
|
||||
sendAsyncMsg('got-set-input-method-active', msgData);
|
||||
msgData.successRv = null;
|
||||
sendAsyncMsg('got-set-input-method-active', msgData);
|
||||
return;
|
||||
}
|
||||
// Unwrap to access webpage content.
|
||||
|
@ -378,10 +378,6 @@ MozInputMethod.prototype = {
|
||||
},
|
||||
|
||||
get mgmt() {
|
||||
if (!WindowMap.isActive(this._window)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return this._mgmt;
|
||||
},
|
||||
|
||||
@ -695,8 +691,8 @@ MozInputContext.prototype = {
|
||||
contextId: self._contextId,
|
||||
requestId: resolverId,
|
||||
text: text,
|
||||
beforeLength: offset || 0,
|
||||
afterLength: length || 0
|
||||
offset: offset || 0,
|
||||
length: length || 0
|
||||
});
|
||||
});
|
||||
},
|
||||
|
@ -585,13 +585,13 @@ let FormAssistant = {
|
||||
case "Forms:ReplaceSurroundingText": {
|
||||
CompositionManager.endComposition('');
|
||||
|
||||
let text = json.text;
|
||||
let beforeLength = json.beforeLength;
|
||||
let afterLength = json.afterLength;
|
||||
let selectionRange = getSelectionRange(target);
|
||||
|
||||
replaceSurroundingText(target, text, selectionRange[0], beforeLength,
|
||||
afterLength);
|
||||
replaceSurroundingText(target,
|
||||
json.text,
|
||||
selectionRange[0],
|
||||
selectionRange[1],
|
||||
json.offset,
|
||||
json.length);
|
||||
|
||||
if (json.requestId) {
|
||||
sendAsyncMessage("Forms:ReplaceSurroundingText:Result:OK", {
|
||||
@ -1064,25 +1064,24 @@ function getPlaintextEditor(element) {
|
||||
return editor;
|
||||
}
|
||||
|
||||
function replaceSurroundingText(element, text, selectionStart, beforeLength,
|
||||
afterLength) {
|
||||
function replaceSurroundingText(element, text, selectionStart, selectionEnd,
|
||||
offset, length) {
|
||||
let editor = FormAssistant.editor;
|
||||
if (!editor) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check the parameters.
|
||||
if (beforeLength < 0) {
|
||||
beforeLength = 0;
|
||||
let start = selectionStart + offset;
|
||||
if (start < 0) {
|
||||
start = 0;
|
||||
}
|
||||
if (afterLength < 0) {
|
||||
afterLength = 0;
|
||||
if (length < 0) {
|
||||
length = 0;
|
||||
}
|
||||
let end = start + length;
|
||||
|
||||
let start = selectionStart - beforeLength;
|
||||
let end = selectionStart + afterLength;
|
||||
|
||||
if (beforeLength != 0 || afterLength != 0) {
|
||||
if (selectionStart != start || selectionEnd != end) {
|
||||
// Change selection range before replacing.
|
||||
setSelectionRange(element, start, end);
|
||||
}
|
||||
|
@ -7,4 +7,5 @@ support-files =
|
||||
|
||||
[test_basic.html]
|
||||
[test_bug944397.html]
|
||||
[test_bug949059.html]
|
||||
[test_sendkey_cancel.html]
|
||||
|
@ -82,7 +82,7 @@ function test_sendKey() {
|
||||
function test_deleteSurroundingText() {
|
||||
// Remove one character before current cursor position and move the cursor
|
||||
// position back to 2.
|
||||
gContext.deleteSurroundingText(1, 0).then(function() {
|
||||
gContext.deleteSurroundingText(-1, 1).then(function() {
|
||||
ok(true, 'deleteSurroundingText finished');
|
||||
is(gContext.textBeforeCursor + gContext.textAfterCursor, 'Yuan',
|
||||
'deleteSurroundingText should changed the input field correctly.');
|
||||
@ -95,7 +95,7 @@ function test_deleteSurroundingText() {
|
||||
|
||||
function test_replaceSurroundingText() {
|
||||
// Replace 'Yuan' with 'Xulei'.
|
||||
gContext.replaceSurroundingText('Xulei', 2, 2).then(function() {
|
||||
gContext.replaceSurroundingText('Xulei', -2, 4).then(function() {
|
||||
ok(true, 'replaceSurroundingText finished');
|
||||
is(gContext.textBeforeCursor + gContext.textAfterCursor, 'Xulei',
|
||||
'replaceSurroundingText changed the input field correctly.');
|
||||
|
@ -51,6 +51,19 @@ function runTest() {
|
||||
keyboard.setAttribute('mozbrowser', true);
|
||||
document.body.appendChild(keyboard);
|
||||
|
||||
// Bug 953044 setInputMethodActive(false) before input method app loads should
|
||||
// always succeed.
|
||||
let req = keyboard.setInputMethodActive(false);
|
||||
req.onsuccess = function() {
|
||||
ok(true, 'setInputMethodActive before loading succeeded.');
|
||||
};
|
||||
|
||||
req.onerror = function() {
|
||||
ok(false, 'setInputMethodActive before loading failed: ' + this.error.name);
|
||||
clearTimeout(timeoutId);
|
||||
inputmethod_cleanup();
|
||||
};
|
||||
|
||||
let path = location.pathname;
|
||||
let imeUrl = location.protocol + '//' + location.host +
|
||||
path.substring(0, path.lastIndexOf('/')) +
|
||||
|
40
dom/inputmethod/mochitest/test_bug949059.html
Normal file
40
dom/inputmethod/mochitest/test_bug949059.html
Normal file
@ -0,0 +1,40 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=949059
|
||||
-->
|
||||
<head>
|
||||
<title>Test "mgmt" property of MozInputMethod.</title>
|
||||
<script type="application/javascript;version=1.7" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript;version=1.7" src="inputmethod_common.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=949059">Mozilla Bug 949059</a>
|
||||
<p id="display"></p>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="application/javascript;version=1.7">
|
||||
|
||||
inputmethod_setup(function() {
|
||||
runTest();
|
||||
});
|
||||
|
||||
function runTest() {
|
||||
let im = navigator.mozInputMethod;
|
||||
|
||||
// Treat current page as an input method and activate it.
|
||||
SpecialPowers.wrap(im).setActive(true);
|
||||
ok(im.mgmt, 'The mgmt property should not be null.');
|
||||
|
||||
// Deactivate current page.
|
||||
SpecialPowers.wrap(im).setActive(false);
|
||||
ok(im.mgmt, 'The mgmt property should not be null.');
|
||||
|
||||
inputmethod_cleanup();
|
||||
}
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -488,6 +488,24 @@ ContentParent::GetInitialProcessPriority(Element* aFrameElement)
|
||||
PROCESS_PRIORITY_FOREGROUND;
|
||||
}
|
||||
|
||||
bool
|
||||
ContentParent::PreallocatedProcessReady()
|
||||
{
|
||||
#ifdef MOZ_NUWA_PROCESS
|
||||
return PreallocatedProcessManager::PreallocatedProcessReady();
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
ContentParent::RunAfterPreallocatedProcessReady(nsIRunnable* aRequest)
|
||||
{
|
||||
#ifdef MOZ_NUWA_PROCESS
|
||||
PreallocatedProcessManager::RunAfterPreallocatedProcessReady(aRequest);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*static*/ TabParent*
|
||||
ContentParent::CreateBrowserOrApp(const TabContext& aContext,
|
||||
Element* aFrameElement)
|
||||
@ -562,6 +580,14 @@ ContentParent::CreateBrowserOrApp(const TabContext& aContext,
|
||||
p = MaybeTakePreallocatedAppProcess(manifestURL, privs,
|
||||
initialPriority);
|
||||
if (!p) {
|
||||
#ifdef MOZ_NUWA_PROCESS
|
||||
if (Preferences::GetBool("dom.ipc.processPrelaunch.enabled",
|
||||
false)) {
|
||||
// Returning nullptr from here so the frame loader will retry
|
||||
// later when we have a spare process.
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
NS_WARNING("Unable to use pre-allocated app process");
|
||||
p = new ContentParent(ownApp,
|
||||
/* isForBrowserElement = */ false,
|
||||
|
@ -86,6 +86,9 @@ public:
|
||||
*/
|
||||
static void JoinAllSubprocesses();
|
||||
|
||||
static bool PreallocatedProcessReady();
|
||||
static void RunAfterPreallocatedProcessReady(nsIRunnable* aRequest);
|
||||
|
||||
static already_AddRefed<ContentParent>
|
||||
GetNewOrUsed(bool aForBrowserElement = false);
|
||||
|
||||
|
@ -55,7 +55,9 @@ public:
|
||||
void PublishSpareProcess(ContentParent* aContent);
|
||||
void MaybeForgetSpare(ContentParent* aContent);
|
||||
void OnNuwaReady();
|
||||
bool PreallocatedProcessReady();
|
||||
already_AddRefed<ContentParent> GetSpareProcess();
|
||||
void RunAfterPreallocatedProcessReady(nsIRunnable* aRunnable);
|
||||
|
||||
private:
|
||||
void OnNuwaForkTimeout();
|
||||
@ -69,6 +71,8 @@ private:
|
||||
nsAutoTArray<nsRefPtr<ContentParent>, 4> mSpareProcesses;
|
||||
nsTArray<CancelableTask*> mNuwaForkWaitTasks;
|
||||
|
||||
nsTArray<nsCOMPtr<nsIRunnable> > mDelayedContentParentRequests;
|
||||
|
||||
// Nuwa process is ready for creating new process.
|
||||
bool mIsNuwaReady;
|
||||
#endif
|
||||
@ -220,6 +224,18 @@ PreallocatedProcessManagerImpl::AllocateNow()
|
||||
|
||||
#ifdef MOZ_NUWA_PROCESS
|
||||
|
||||
void
|
||||
PreallocatedProcessManagerImpl::RunAfterPreallocatedProcessReady(nsIRunnable* aRequest)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
mDelayedContentParentRequests.AppendElement(aRequest);
|
||||
|
||||
if (!mPreallocateAppProcessTask) {
|
||||
// This is an urgent NuwaFork() request.
|
||||
DelayedNuwaFork();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PreallocatedProcessManagerImpl::ScheduleDelayedNuwaFork()
|
||||
{
|
||||
@ -302,6 +318,12 @@ PreallocatedProcessManagerImpl::PublishSpareProcess(ContentParent* aContent)
|
||||
}
|
||||
|
||||
mSpareProcesses.AppendElement(aContent);
|
||||
|
||||
if (!mDelayedContentParentRequests.IsEmpty()) {
|
||||
nsCOMPtr<nsIRunnable> runnable = mDelayedContentParentRequests[0];
|
||||
mDelayedContentParentRequests.RemoveElementAt(0);
|
||||
NS_DispatchToMainThread(runnable);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -309,6 +331,13 @@ PreallocatedProcessManagerImpl::MaybeForgetSpare(ContentParent* aContent)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (!mDelayedContentParentRequests.IsEmpty()) {
|
||||
if (!mPreallocateAppProcessTask) {
|
||||
// This NuwaFork request is urgent. Don't delay it.
|
||||
DelayedNuwaFork();
|
||||
}
|
||||
}
|
||||
|
||||
if (mSpareProcesses.RemoveElement(aContent)) {
|
||||
return;
|
||||
}
|
||||
@ -338,6 +367,13 @@ PreallocatedProcessManagerImpl::OnNuwaReady()
|
||||
NuwaFork();
|
||||
}
|
||||
|
||||
bool
|
||||
PreallocatedProcessManagerImpl::PreallocatedProcessReady()
|
||||
{
|
||||
return !mSpareProcesses.IsEmpty();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PreallocatedProcessManagerImpl::OnNuwaForkTimeout()
|
||||
{
|
||||
@ -473,6 +509,19 @@ PreallocatedProcessManager::OnNuwaReady()
|
||||
{
|
||||
GetPPMImpl()->OnNuwaReady();
|
||||
}
|
||||
|
||||
/*static */ bool
|
||||
PreallocatedProcessManager::PreallocatedProcessReady()
|
||||
{
|
||||
return GetPPMImpl()->PreallocatedProcessReady();
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
PreallocatedProcessManager::RunAfterPreallocatedProcessReady(nsIRunnable* aRequest)
|
||||
{
|
||||
GetPPMImpl()->RunAfterPreallocatedProcessReady(aRequest);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -11,6 +11,8 @@
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIObserver.h"
|
||||
|
||||
class nsIRunnable;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
class ContentParent;
|
||||
@ -82,6 +84,8 @@ public:
|
||||
static void PublishSpareProcess(ContentParent* aContent);
|
||||
static void MaybeForgetSpare(ContentParent* aContent);
|
||||
static void OnNuwaReady();
|
||||
static bool PreallocatedProcessReady();
|
||||
static void RunAfterPreallocatedProcessReady(nsIRunnable* aRunnable);
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
@ -11061,6 +11061,15 @@ let BerTlvHelper = {
|
||||
retrieveFileIdentifier: function retrieveFileIdentifier(length) {
|
||||
return {fileId : (GsmPDUHelper.readHexOctet() << 8) +
|
||||
GsmPDUHelper.readHexOctet()};
|
||||
},
|
||||
|
||||
searchForNextTag: function searchForNextTag(tag, iter) {
|
||||
for (let [index, tlv] in iter) {
|
||||
if (tlv.tag === tag) {
|
||||
return tlv;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
};
|
||||
BerTlvHelper[BER_FCP_TEMPLATE_TAG] = function BER_FCP_TEMPLATE_TAG(length) {
|
||||
@ -11342,9 +11351,60 @@ let ICCIOHelper = {
|
||||
processICCIOGetResponse: function processICCIOGetResponse(options) {
|
||||
let strLen = Buf.readInt32();
|
||||
|
||||
let peek = GsmPDUHelper.readHexOctet();
|
||||
Buf.seekIncoming(-1 * Buf.PDU_HEX_OCTET_SIZE);
|
||||
if (peek === BER_FCP_TEMPLATE_TAG) {
|
||||
this.processUSimGetResponse(options, strLen / 2);
|
||||
} else {
|
||||
this.processSimGetResponse(options);
|
||||
}
|
||||
Buf.readStringDelimiter(strLen);
|
||||
|
||||
if (options.callback) {
|
||||
options.callback(options);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Helper function for processing USIM get response.
|
||||
*/
|
||||
processUSimGetResponse: function processUSimGetResponse(options, octetLen) {
|
||||
let berTlv = BerTlvHelper.decode(octetLen);
|
||||
// See TS 102 221 Table 11.4 for the content order of getResponse.
|
||||
let iter = Iterator(berTlv.value);
|
||||
let tlv = BerTlvHelper.searchForNextTag(BER_FCP_FILE_DESCRIPTOR_TAG,
|
||||
iter);
|
||||
if (!tlv || (tlv.value.fileStructure !== UICC_EF_STRUCTURE[options.type])) {
|
||||
throw new Error("Expected EF type " + UICC_EF_STRUCTURE[options.type] +
|
||||
" but read " + tlv.value.fileStructure);
|
||||
}
|
||||
|
||||
if (tlv.value.fileStructure === UICC_EF_STRUCTURE[EF_TYPE_LINEAR_FIXED] ||
|
||||
tlv.value.fileStructure === UICC_EF_STRUCTURE[EF_TYPE_CYCLIC]) {
|
||||
options.recordSize = tlv.value.recordLength;
|
||||
options.totalRecords = tlv.value.numOfRecords;
|
||||
}
|
||||
|
||||
tlv = BerTlvHelper.searchForNextTag(BER_FCP_FILE_IDENTIFIER_TAG, iter);
|
||||
if (!tlv || (tlv.value.fileId !== options.fileId)) {
|
||||
throw new Error("Expected file ID " + options.fileId.toString(16) +
|
||||
" but read " + fileId.toString(16));
|
||||
}
|
||||
|
||||
tlv = BerTlvHelper.searchForNextTag(BER_FCP_FILE_SIZE_DATA_TAG, iter);
|
||||
if (!tlv) {
|
||||
throw new Error("Unexpected file size data");
|
||||
}
|
||||
options.fileSize = tlv.value.fileSizeData;
|
||||
},
|
||||
|
||||
/**
|
||||
* Helper function for processing SIM get response.
|
||||
*/
|
||||
processSimGetResponse: function processSimGetResponse(options) {
|
||||
// The format is from TS 51.011, clause 9.2.1
|
||||
|
||||
// Skip RFU, data[0] data[1]
|
||||
// Skip RFU, data[0] data[1].
|
||||
Buf.seekIncoming(2 * Buf.PDU_HEX_OCTET_SIZE);
|
||||
|
||||
// File size, data[2], data[3]
|
||||
@ -11378,6 +11438,7 @@ let ICCIOHelper = {
|
||||
throw new Error("Expected EF type " + options.type + " but read " + efType);
|
||||
}
|
||||
|
||||
// TODO: Bug 952025.
|
||||
// Length of a record, data[14].
|
||||
// Only available for LINEAR_FIXED and CYCLIC.
|
||||
if (efType == EF_TYPE_LINEAR_FIXED || efType == EF_TYPE_CYCLIC) {
|
||||
@ -11386,12 +11447,6 @@ let ICCIOHelper = {
|
||||
} else {
|
||||
Buf.seekIncoming(1 * Buf.PDU_HEX_OCTET_SIZE);
|
||||
}
|
||||
|
||||
Buf.readStringDelimiter(strLen);
|
||||
|
||||
if (options.callback) {
|
||||
options.callback(options);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -2733,15 +2733,6 @@ add_test(function test_fcp_template_for_transparent_structure() {
|
||||
let pduHelper = worker.GsmPDUHelper;
|
||||
let berHelper = worker.BerTlvHelper;
|
||||
|
||||
berHelper.searchForNextTag = function searchForNextTag(tag, iter) {
|
||||
for (let [index, tlv] in iter) {
|
||||
if (tlv.tag === tag) {
|
||||
return tlv;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
let tag_test = [
|
||||
0x62,
|
||||
0x22,
|
||||
@ -2779,15 +2770,6 @@ add_test(function test_fcp_template_for_linear_fixed_structure() {
|
||||
let pduHelper = worker.GsmPDUHelper;
|
||||
let berHelper = worker.BerTlvHelper;
|
||||
|
||||
berHelper.searchForNextTag = function searchForNextTag(tag, iter) {
|
||||
for (let [index, tlv] in iter) {
|
||||
if (tlv.tag === tag) {
|
||||
return tlv;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
let tag_test = [
|
||||
0x62,
|
||||
0x1E,
|
||||
@ -2818,3 +2800,73 @@ add_test(function test_fcp_template_for_linear_fixed_structure() {
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
add_test(function test_icc_io_get_response_for_transparent_structure() {
|
||||
let worker = newUint8Worker();
|
||||
let buf = worker.Buf;
|
||||
let iccioHelper = worker.ICCIOHelper;
|
||||
let pduHelper = worker.GsmPDUHelper;
|
||||
|
||||
let responseArray = [
|
||||
// SIM response.
|
||||
[0x00, 0x00, 0x00, 0x0A, 0x2F, 0xE2, 0x04, 0x00, 0x0A, 0xA0, 0xAA, 0x00,
|
||||
0x02, 0x00, 0x00],
|
||||
// USIM response.
|
||||
[0x62, 0x22, 0x82, 0x02, 0x41, 0x21, 0x83, 0x02, 0x2F, 0xE2, 0xA5, 0x09,
|
||||
0xC1, 0x04, 0x40, 0x0F, 0xF5, 0x55, 0x92, 0x01, 0x00, 0x8A, 0x01, 0x05,
|
||||
0x8B, 0x03, 0x2F, 0x06, 0x0B, 0x80, 0x02, 0x00, 0x0A, 0x88, 0x01, 0x10]
|
||||
];
|
||||
|
||||
for (let i = 0; i < responseArray.length; i++) {
|
||||
let strLen = responseArray[i].length * 2;
|
||||
buf.writeInt32(strLen);
|
||||
for (let j = 0; j < responseArray[i].length; j++) {
|
||||
pduHelper.writeHexOctet(responseArray[i][j]);
|
||||
}
|
||||
buf.writeStringDelimiter(strLen);
|
||||
|
||||
let options = {fileId: ICC_EF_ICCID,
|
||||
type: EF_TYPE_TRANSPARENT};
|
||||
iccioHelper.processICCIOGetResponse(options);
|
||||
|
||||
do_check_eq(options.fileSize, 0x0A);
|
||||
}
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
add_test(function test_icc_io_get_response_for_linear_fixed_structure() {
|
||||
let worker = newUint8Worker();
|
||||
let buf = worker.Buf;
|
||||
let iccioHelper = worker.ICCIOHelper;
|
||||
let pduHelper = worker.GsmPDUHelper;
|
||||
|
||||
let responseArray = [
|
||||
// SIM response.
|
||||
[0x00, 0x00, 0x00, 0x1A, 0x6F, 0x40, 0x04, 0x00, 0x11, 0xA0, 0xAA, 0x00,
|
||||
0x02, 0x01, 0x1A],
|
||||
// USIM response.
|
||||
[0x62, 0x1E, 0x82, 0x05, 0x42, 0x21, 0x00, 0x1A, 0x01, 0x83, 0x02, 0x6F,
|
||||
0x40, 0xA5, 0x03, 0x92, 0x01, 0x00, 0x8A, 0x01, 0x07, 0x8B, 0x03, 0x6F,
|
||||
0x06, 0x02, 0x80, 0x02, 0x00, 0x1A, 0x88, 0x00]
|
||||
];
|
||||
|
||||
for (let i = 0; i < responseArray.length; i++) {
|
||||
let strLen = responseArray[i].length * 2;
|
||||
buf.writeInt32(strLen);
|
||||
for (let j = 0; j < responseArray[i].length; j++) {
|
||||
pduHelper.writeHexOctet(responseArray[i][j]);
|
||||
}
|
||||
buf.writeStringDelimiter(strLen);
|
||||
|
||||
let options = {fileId: ICC_EF_MSISDN,
|
||||
type: EF_TYPE_LINEAR_FIXED};
|
||||
iccioHelper.processICCIOGetResponse(options);
|
||||
|
||||
do_check_eq(options.fileSize, 0x1A);
|
||||
do_check_eq(options.recordSize, 0x1A);
|
||||
do_check_eq(options.totalRecords, 0x01);
|
||||
}
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
@ -89,7 +89,7 @@ interface MozInputContext: EventTarget {
|
||||
readonly attribute long selectionStart;
|
||||
readonly attribute long selectionEnd;
|
||||
|
||||
// The start and stop position of the selection.
|
||||
// The text before and after the begining of the selected text.
|
||||
readonly attribute DOMString? textBeforeCursor;
|
||||
readonly attribute DOMString? textAfterCursor;
|
||||
|
||||
|
@ -3812,6 +3812,15 @@ class _GenerateProtocolActorCode(ipdl.ast.Visitor):
|
||||
static=1))
|
||||
clonemanagees.addstmt(otherstmt)
|
||||
|
||||
# Keep track of types created with an INOUT ctor. We need to call
|
||||
# Register() or RegisterID() for them depending on the side the managee
|
||||
# is created.
|
||||
inoutCtorTypes = []
|
||||
for msg in p.messageDecls:
|
||||
msgtype = msg.decl.type
|
||||
if msgtype.isCtor() and msgtype.isInout():
|
||||
inoutCtorTypes.append(msgtype.constructedType())
|
||||
|
||||
actorvar = ExprVar('actor')
|
||||
for managee in p.managesStmts:
|
||||
block = StmtBlock()
|
||||
@ -3827,6 +3836,19 @@ class _GenerateProtocolActorCode(ipdl.ast.Visitor):
|
||||
init=Param(Type.UINT32, ivar.name, ExprLiteral.ZERO),
|
||||
cond=ExprBinary(ivar, '<', _callCxxArrayLength(kidsvar)),
|
||||
update=ExprPrefixUnop(ivar, '++'))
|
||||
|
||||
registerstmt = StmtExpr(ExprCall(p.registerIDMethod(),
|
||||
args=[actorvar, _actorId(actorvar)]))
|
||||
# Implement if (actor id > 0) then Register() else RegisterID()
|
||||
if manageeipdltype in inoutCtorTypes:
|
||||
registerif = StmtIf(ExprBinary(_actorId(actorvar),
|
||||
'>',
|
||||
ExprLiteral.ZERO))
|
||||
registerif.addifstmt(StmtExpr(ExprCall(p.registerMethod(),
|
||||
args=[actorvar])))
|
||||
registerif.addelsestmt(registerstmt)
|
||||
registerstmt = registerif
|
||||
|
||||
forstmt.addstmts([
|
||||
StmtExpr(ExprAssn(
|
||||
actorvar,
|
||||
@ -3847,8 +3869,7 @@ class _GenerateProtocolActorCode(ipdl.ast.Visitor):
|
||||
p.channelForSubactor())),
|
||||
StmtExpr(ExprAssn(_actorState(actorvar), _actorState(ithkid))),
|
||||
StmtExpr(_callCxxArrayInsertSorted(manageearray, actorvar)),
|
||||
StmtExpr(ExprCall(p.registerIDMethod(),
|
||||
args=[actorvar, _actorId(actorvar)])),
|
||||
registerstmt,
|
||||
StmtExpr(ExprCall(
|
||||
ExprSelect(actorvar,
|
||||
'->',
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -9,6 +9,8 @@ include $(topsrcdir)/config/makefiles/rcs.mk
|
||||
LOCAL_INCLUDES += -I$(topsrcdir)/xpcom/build
|
||||
LOCAL_INCLUDES += -I$(topsrcdir)/xpcom/threads
|
||||
|
||||
DEFINES += -DMOZ_APP_VERSION='"$(MOZ_APP_VERSION)"'
|
||||
|
||||
MOZ_HISTOGRAMS_VERSION ?= $(call getSourceRepo)/rev/$(firstword $(shell hg -R $(topsrcdir) parent --template='{node|short}\n' 2>/dev/null))
|
||||
ifdef MOZ_HISTOGRAMS_VERSION
|
||||
DEFINES += -DHISTOGRAMS_FILE_VERSION='$(MOZ_HISTOGRAMS_VERSION)'
|
||||
|
@ -23,6 +23,8 @@
|
||||
#include "nsCOMArray.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsXPCOMPrivate.h"
|
||||
#include "nsIXULAppInfo.h"
|
||||
#include "nsVersionComparator.h"
|
||||
#include "mozilla/MemoryReporting.h"
|
||||
#include "mozilla/ModuleUtils.h"
|
||||
#include "nsIXPConnect.h"
|
||||
@ -57,6 +59,8 @@
|
||||
#include "shared-libraries.h"
|
||||
#endif
|
||||
|
||||
#define EXPIRED_ID "__expired__"
|
||||
|
||||
namespace {
|
||||
|
||||
using namespace base;
|
||||
@ -388,9 +392,11 @@ struct TelemetryHistogram {
|
||||
uint32_t bucketCount;
|
||||
uint32_t histogramType;
|
||||
uint32_t id_offset;
|
||||
uint32_t expiration_offset;
|
||||
bool extendedStatisticsOK;
|
||||
|
||||
const char *id() const;
|
||||
const char *expiration() const;
|
||||
};
|
||||
|
||||
#include "TelemetryHistogramData.inc"
|
||||
@ -402,31 +408,27 @@ TelemetryHistogram::id() const
|
||||
return &gHistogramStringTable[this->id_offset];
|
||||
}
|
||||
|
||||
bool
|
||||
TelemetryHistogramType(Histogram *h, uint32_t *result)
|
||||
const char *
|
||||
TelemetryHistogram::expiration() const
|
||||
{
|
||||
switch (h->histogram_type()) {
|
||||
case Histogram::HISTOGRAM:
|
||||
*result = nsITelemetry::HISTOGRAM_EXPONENTIAL;
|
||||
break;
|
||||
case Histogram::LINEAR_HISTOGRAM:
|
||||
*result = nsITelemetry::HISTOGRAM_LINEAR;
|
||||
break;
|
||||
case Histogram::BOOLEAN_HISTOGRAM:
|
||||
*result = nsITelemetry::HISTOGRAM_BOOLEAN;
|
||||
break;
|
||||
case Histogram::FLAG_HISTOGRAM:
|
||||
*result = nsITelemetry::HISTOGRAM_FLAG;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
return &gHistogramStringTable[this->expiration_offset];
|
||||
}
|
||||
|
||||
bool
|
||||
IsExpired(const char *expiration){
|
||||
static Version current_version = Version(MOZ_APP_VERSION);
|
||||
MOZ_ASSERT(expiration);
|
||||
return strcmp(expiration, "never") && (mozilla::Version(expiration) <= current_version);
|
||||
}
|
||||
|
||||
bool
|
||||
IsExpired(const Histogram *histogram){
|
||||
return histogram->histogram_name() == EXPIRED_ID;
|
||||
}
|
||||
|
||||
nsresult
|
||||
HistogramGet(const char *name, uint32_t min, uint32_t max, uint32_t bucketCount,
|
||||
uint32_t histogramType, Histogram **result)
|
||||
HistogramGet(const char *name, const char *expiration, uint32_t min, uint32_t max,
|
||||
uint32_t bucketCount, uint32_t histogramType, Histogram **result)
|
||||
{
|
||||
if (histogramType != nsITelemetry::HISTOGRAM_BOOLEAN
|
||||
&& histogramType != nsITelemetry::HISTOGRAM_FLAG) {
|
||||
@ -441,6 +443,14 @@ HistogramGet(const char *name, uint32_t min, uint32_t max, uint32_t bucketCount,
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
|
||||
if (IsExpired(expiration)) {
|
||||
name = EXPIRED_ID;
|
||||
min = 1;
|
||||
max = 2;
|
||||
bucketCount = 3;
|
||||
histogramType = nsITelemetry::HISTOGRAM_LINEAR;
|
||||
}
|
||||
|
||||
switch (histogramType) {
|
||||
case nsITelemetry::HISTOGRAM_EXPONENTIAL:
|
||||
*result = Histogram::FactoryGet(name, min, max, bucketCount, Histogram::kUmaTargetedHistogramFlag);
|
||||
@ -472,20 +482,22 @@ GetHistogramByEnumId(Telemetry::ID id, Histogram **ret)
|
||||
}
|
||||
|
||||
const TelemetryHistogram &p = gHistograms[id];
|
||||
nsresult rv = HistogramGet(p.id(), p.min, p.max, p.bucketCount, p.histogramType, &h);
|
||||
nsresult rv = HistogramGet(p.id(), p.expiration(), p.min, p.max, p.bucketCount, p.histogramType, &h);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
#ifdef DEBUG
|
||||
// Check that the C++ Histogram code computes the same ranges as the
|
||||
// Python histogram code.
|
||||
const struct bounds &b = gBucketLowerBoundIndex[id];
|
||||
if (b.length != 0) {
|
||||
MOZ_ASSERT(size_t(b.length) == h->bucket_count(),
|
||||
"C++/Python bucket # mismatch");
|
||||
for (int i = 0; i < b.length; ++i) {
|
||||
MOZ_ASSERT(gBucketLowerBounds[b.offset + i] == h->ranges(i),
|
||||
"C++/Python bucket mismatch");
|
||||
if (!IsExpired(p.expiration())) {
|
||||
const struct bounds &b = gBucketLowerBoundIndex[id];
|
||||
if (b.length != 0) {
|
||||
MOZ_ASSERT(size_t(b.length) == h->bucket_count(),
|
||||
"C++/Python bucket # mismatch");
|
||||
for (int i = 0; i < b.length; ++i) {
|
||||
MOZ_ASSERT(gBucketLowerBounds[b.offset + i] == h->ranges(i),
|
||||
"C++/Python bucket mismatch");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -966,12 +978,13 @@ TelemetryImpl::InitMemoryReporter() {
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
TelemetryImpl::NewHistogram(const nsACString &name, uint32_t min, uint32_t max,
|
||||
uint32_t bucketCount, uint32_t histogramType,
|
||||
TelemetryImpl::NewHistogram(const nsACString &name, const nsACString &expiration, uint32_t min,
|
||||
uint32_t max, uint32_t bucketCount, uint32_t histogramType,
|
||||
JSContext *cx, JS::Value *ret)
|
||||
{
|
||||
Histogram *h;
|
||||
nsresult rv = HistogramGet(PromiseFlatCString(name).get(), min, max, bucketCount, histogramType, &h);
|
||||
nsresult rv = HistogramGet(PromiseFlatCString(name).get(), PromiseFlatCString(expiration).get(),
|
||||
min, max, bucketCount, histogramType, &h);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
h->ClearFlags(Histogram::kUmaTargetedHistogramFlag);
|
||||
@ -1089,20 +1102,23 @@ NS_IMETHODIMP
|
||||
TelemetryImpl::HistogramFrom(const nsACString &name, const nsACString &existing_name,
|
||||
JSContext *cx, JS::Value *ret)
|
||||
{
|
||||
Histogram *existing;
|
||||
nsresult rv = GetHistogramByName(existing_name, &existing);
|
||||
if (NS_FAILED(rv))
|
||||
Telemetry::ID id;
|
||||
nsresult rv = GetHistogramEnumId(PromiseFlatCString(existing_name).get(), &id);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
const TelemetryHistogram &p = gHistograms[id];
|
||||
|
||||
uint32_t histogramType;
|
||||
bool success = TelemetryHistogramType(existing, &histogramType);
|
||||
if (!success)
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
Histogram *existing;
|
||||
rv = GetHistogramByEnumId(id, &existing);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
Histogram *clone;
|
||||
rv = HistogramGet(PromiseFlatCString(name).get(), existing->declared_min(),
|
||||
existing->declared_max(), existing->bucket_count(),
|
||||
histogramType, &clone);
|
||||
rv = HistogramGet(PromiseFlatCString(name).get(), p.expiration(),
|
||||
existing->declared_min(), existing->declared_max(),
|
||||
existing->bucket_count(), p.histogramType, &clone);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
@ -1302,7 +1318,7 @@ TelemetryImpl::GetHistogramSnapshots(JSContext *cx, JS::Value *ret)
|
||||
JS::Rooted<JSObject*> hobj(cx);
|
||||
for (HistogramIterator it = hs.begin(); it != hs.end(); ++it) {
|
||||
Histogram *h = *it;
|
||||
if (!ShouldReflectHistogram(h) || IsEmpty(h)) {
|
||||
if (!ShouldReflectHistogram(h) || IsEmpty(h) || IsExpired(h)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -1333,7 +1349,7 @@ TelemetryImpl::CreateHistogramForAddon(const nsACString &name,
|
||||
AddonHistogramInfo &info)
|
||||
{
|
||||
Histogram *h;
|
||||
nsresult rv = HistogramGet(PromiseFlatCString(name).get(),
|
||||
nsresult rv = HistogramGet(PromiseFlatCString(name).get(), "never",
|
||||
info.min, info.max, info.bucketCount,
|
||||
info.histogramType, &h);
|
||||
if (NS_FAILED(rv)) {
|
||||
@ -1950,15 +1966,21 @@ NS_IMETHODIMP
|
||||
TelemetryImpl::RegisteredHistograms(uint32_t *aCount, char*** aHistograms)
|
||||
{
|
||||
size_t count = ArrayLength(gHistograms);
|
||||
size_t offset = 0;
|
||||
char** histograms = static_cast<char**>(nsMemory::Alloc(count * sizeof(char*)));
|
||||
|
||||
for (size_t i = 0; i < count; ++i) {
|
||||
if (IsExpired(gHistograms[i].expiration())) {
|
||||
offset++;
|
||||
continue;
|
||||
}
|
||||
|
||||
const char* h = gHistograms[i].id();
|
||||
size_t len = strlen(h);
|
||||
histograms[i] = static_cast<char*>(nsMemory::Clone(h, len+1));
|
||||
histograms[i - offset] = static_cast<char*>(nsMemory::Clone(h, len+1));
|
||||
}
|
||||
|
||||
*aCount = count;
|
||||
*aCount = count - offset;
|
||||
*aHistograms = histograms;
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -47,19 +47,23 @@ class StringTable:
|
||||
return ", ".join(map(toCChar, string))
|
||||
f.write("const char %s[] = {\n" % name)
|
||||
for (string, offset) in entries[:-1]:
|
||||
f.write(" /* %5d */ %s, '\\0',\n"
|
||||
% (offset, explodeToCharArray(string)))
|
||||
e = explodeToCharArray(string)
|
||||
if e:
|
||||
f.write(" /* %5d */ %s, '\\0',\n"
|
||||
% (offset, explodeToCharArray(string)))
|
||||
else:
|
||||
f.write(" /* %5d */ '\\0',\n" % offset)
|
||||
f.write(" /* %5d */ %s, '\\0' };\n\n"
|
||||
% (entries[-1][1], explodeToCharArray(entries[-1][0])))
|
||||
|
||||
def print_array_entry(histogram, name_index):
|
||||
def print_array_entry(histogram, name_index, exp_index):
|
||||
cpp_guard = histogram.cpp_guard()
|
||||
if cpp_guard:
|
||||
print "#if defined(%s)" % cpp_guard
|
||||
print " { %s, %s, %s, %s, %d, %s }," \
|
||||
print " { %s, %s, %s, %s, %d, %d, %s }," \
|
||||
% (histogram.low(), histogram.high(),
|
||||
histogram.n_buckets(), histogram.nsITelemetry_kind(),
|
||||
name_index,
|
||||
name_index, exp_index,
|
||||
"true" if histogram.extended_statistics_ok() else "false")
|
||||
if cpp_guard:
|
||||
print "#endif"
|
||||
@ -70,7 +74,8 @@ def write_histogram_table(histograms):
|
||||
print "const TelemetryHistogram gHistograms[] = {"
|
||||
for histogram in histograms:
|
||||
name_index = table.stringIndex(histogram.name())
|
||||
print_array_entry(histogram, name_index)
|
||||
exp_index = table.stringIndex(histogram.expiration())
|
||||
print_array_entry(histogram, name_index, exp_index)
|
||||
print "};"
|
||||
|
||||
strtab_name = "gHistogramStringTable"
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
import json
|
||||
import math
|
||||
import re
|
||||
|
||||
from collections import OrderedDict
|
||||
|
||||
@ -54,7 +55,7 @@ def exponential_buckets(dmin, dmax, n_buckets):
|
||||
ret_array[bucket_index] = current
|
||||
return ret_array
|
||||
|
||||
always_allowed_keys = ['kind', 'description', 'cpp_guard']
|
||||
always_allowed_keys = ['kind', 'description', 'cpp_guard', 'expires_in_version']
|
||||
|
||||
class Histogram:
|
||||
"""A class for representing a histogram definition."""
|
||||
@ -75,6 +76,7 @@ symbol that should guard C/C++ definitions associated with the histogram."""
|
||||
self._kind = definition['kind']
|
||||
self._cpp_guard = definition.get('cpp_guard')
|
||||
self._extended_statistics_ok = definition.get('extended_statistics_ok', False)
|
||||
self._expiration = definition.get('expires_in_version')
|
||||
self.compute_bucket_parameters(definition)
|
||||
table = { 'boolean': 'BOOLEAN',
|
||||
'flag': 'FLAG',
|
||||
@ -97,6 +99,10 @@ symbol that should guard C/C++ definitions associated with the histogram."""
|
||||
Will be one of 'boolean', 'flag', 'enumerated', 'linear', or 'exponential'."""
|
||||
return self._kind
|
||||
|
||||
def expiration(self):
|
||||
"""Return the expiration version of the histogram."""
|
||||
return self._expiration
|
||||
|
||||
def nsITelemetry_kind(self):
|
||||
"""Return the nsITelemetry constant corresponding to the kind of
|
||||
the histogram."""
|
||||
@ -162,6 +168,19 @@ is enabled."""
|
||||
table_dispatch(definition['kind'], table,
|
||||
lambda allowed_keys: Histogram.check_keys(name, definition, allowed_keys))
|
||||
|
||||
Histogram.check_expiration(name, definition)
|
||||
|
||||
@staticmethod
|
||||
def check_expiration(name, definition):
|
||||
expiration = definition['expires_in_version']
|
||||
|
||||
if not expiration:
|
||||
return
|
||||
|
||||
if not re.match(r'[1-9][0-9]*\..*|never', expiration):
|
||||
raise BaseException, '%s not permitted as an expiration version for %s; the complete version name is required ' \
|
||||
'(see https://developer.mozilla.org/en-US/docs/Performance/Adding_a_new_Telemetry_probe)' % (expiration, name)
|
||||
|
||||
@staticmethod
|
||||
def check_keys(name, definition, allowed_keys):
|
||||
for key in definition.iterkeys():
|
||||
|
@ -12,7 +12,7 @@ interface nsIFetchTelemetryDataCallback : nsISupports
|
||||
void complete();
|
||||
};
|
||||
|
||||
[scriptable, uuid(cb97b7b4-dce6-45fa-be6a-47e436a9aef9)]
|
||||
[scriptable, uuid(3bdb3c83-1ac0-482a-9c3d-b15141174af4)]
|
||||
interface nsITelemetry : nsISupports
|
||||
{
|
||||
/**
|
||||
@ -139,6 +139,7 @@ interface nsITelemetry : nsISupports
|
||||
* Create and return a histogram. Parameters:
|
||||
*
|
||||
* @param name Unique histogram name
|
||||
* @param expiration Expiration version
|
||||
* @param min - Minimal bucket size
|
||||
* @param max - Maximum bucket size
|
||||
* @param bucket_count - number of buckets in the histogram.
|
||||
@ -149,7 +150,7 @@ interface nsITelemetry : nsISupports
|
||||
* clear() - Zeros out the histogram's buckets and sum
|
||||
*/
|
||||
[implicit_jscontext]
|
||||
jsval newHistogram(in ACString name, in uint32_t min, in uint32_t max, in uint32_t bucket_count, in unsigned long histogram_type);
|
||||
jsval newHistogram(in ACString name, in ACString expiration, in uint32_t min, in uint32_t max, in uint32_t bucket_count, in unsigned long histogram_type);
|
||||
|
||||
/**
|
||||
* Create a histogram using the current state of an existing histogram. The
|
||||
|
@ -44,6 +44,16 @@ var httpserver = new HttpServer();
|
||||
var serverStarted = false;
|
||||
var gFinished = false;
|
||||
|
||||
function test_expired_histogram() {
|
||||
var histogram_id = "FOOBAR";
|
||||
var dummy = Telemetry.newHistogram(histogram_id, "30", 1, 2, 3, Telemetry.HISTOGRAM_EXPONENTIAL);
|
||||
|
||||
dummy.add(1);
|
||||
|
||||
do_check_eq(TelemetryPing.getPayload()["histograms"][histogram_id], undefined);
|
||||
do_check_eq(TelemetryPing.getPayload()["histograms"]["TELEMETRY_TEST_EXPIRED"], undefined);
|
||||
}
|
||||
|
||||
function telemetry_ping () {
|
||||
TelemetryPing.gatherStartup();
|
||||
TelemetryPing.enableLoadSaveNotifications();
|
||||
@ -98,7 +108,7 @@ function nonexistentServerObserver(aSubject, aTopic, aData) {
|
||||
}
|
||||
|
||||
function setupTestData() {
|
||||
Telemetry.newHistogram(IGNORE_HISTOGRAM, 1, 2, 3, Telemetry.HISTOGRAM_BOOLEAN);
|
||||
Telemetry.newHistogram(IGNORE_HISTOGRAM, "never", 1, 2, 3, Telemetry.HISTOGRAM_BOOLEAN);
|
||||
Telemetry.histogramFrom(IGNORE_CLONED_HISTOGRAM, IGNORE_HISTOGRAM_TO_CLONE);
|
||||
Services.startup.interrupted = true;
|
||||
Telemetry.registerAddonHistogram(ADDON_NAME, ADDON_HISTOGRAM, 1, 5, 6,
|
||||
@ -499,6 +509,7 @@ function actualTest() {
|
||||
registerFakePluginHost();
|
||||
|
||||
runInvalidJSONTest();
|
||||
test_expired_histogram();
|
||||
|
||||
addWrappedObserver(nonexistentServerObserver, "telemetry-test-xhr-complete");
|
||||
telemetry_ping();
|
||||
|
@ -9,9 +9,26 @@ const INT_MAX = 0x7FFFFFFF;
|
||||
const Telemetry = Cc["@mozilla.org/base/telemetry;1"].getService(Ci.nsITelemetry);
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
function test_expired_histogram() {
|
||||
var histogram_id = "FOOBAR";
|
||||
var test_expired_id = "TELEMETRY_TEST_EXPIRED";
|
||||
var clone_id = "ExpiredClone";
|
||||
var dummy = Telemetry.newHistogram(histogram_id, "28.0a1", 1, 2, 3, Telemetry.HISTOGRAM_EXPONENTIAL);
|
||||
var dummy_clone = Telemetry.histogramFrom(clone_id, test_expired_id);
|
||||
var rh = Telemetry.registeredHistograms([]);
|
||||
|
||||
dummy.add(1);
|
||||
dummy_clone.add(1);
|
||||
|
||||
do_check_eq(Telemetry.histogramSnapshots["__expired__"], undefined);
|
||||
do_check_eq(Telemetry.histogramSnapshots[histogram_id], undefined);
|
||||
do_check_eq(Telemetry.histogramSnapshots[test_expired_id], undefined);
|
||||
do_check_eq(Telemetry.histogramSnapshots[clone_id], undefined);
|
||||
do_check_eq(rh[test_expired_id], undefined);
|
||||
}
|
||||
|
||||
function test_histogram(histogram_type, name, min, max, bucket_count) {
|
||||
var h = Telemetry.newHistogram(name, min, max, bucket_count, histogram_type);
|
||||
|
||||
var h = Telemetry.newHistogram(name, "never", min, max, bucket_count, histogram_type);
|
||||
var r = h.snapshot().ranges;
|
||||
var sum = 0;
|
||||
var log_sum = 0;
|
||||
@ -109,7 +126,7 @@ function expect_success(f) {
|
||||
|
||||
function test_boolean_histogram()
|
||||
{
|
||||
var h = Telemetry.newHistogram("test::boolean histogram", 99,1,4, Telemetry.HISTOGRAM_BOOLEAN);
|
||||
var h = Telemetry.newHistogram("test::boolean histogram", "never", 99,1,4, Telemetry.HISTOGRAM_BOOLEAN);
|
||||
var r = h.snapshot().ranges;
|
||||
// boolean histograms ignore numeric parameters
|
||||
do_check_eq(uneval(r), uneval([0, 1, 2]))
|
||||
@ -131,7 +148,7 @@ function test_boolean_histogram()
|
||||
|
||||
function test_flag_histogram()
|
||||
{
|
||||
var h = Telemetry.newHistogram("test::flag histogram", 130, 4, 5, Telemetry.HISTOGRAM_FLAG);
|
||||
var h = Telemetry.newHistogram("test::flag histogram", "never", 130, 4, 5, Telemetry.HISTOGRAM_FLAG);
|
||||
var r = h.snapshot().ranges;
|
||||
// Flag histograms ignore numeric parameters.
|
||||
do_check_eq(uneval(r), uneval([0, 1, 2]))
|
||||
@ -312,7 +329,7 @@ function test_addons() {
|
||||
|
||||
// Check that telemetry doesn't record in private mode
|
||||
function test_privateMode() {
|
||||
var h = Telemetry.newHistogram("test::private_mode_boolean", 1,2,3, Telemetry.HISTOGRAM_BOOLEAN);
|
||||
var h = Telemetry.newHistogram("test::private_mode_boolean", "never", 1,2,3, Telemetry.HISTOGRAM_BOOLEAN);
|
||||
var orig = h.snapshot();
|
||||
Telemetry.canRecord = false;
|
||||
h.add(1);
|
||||
@ -349,10 +366,10 @@ function run_test()
|
||||
for each (let histogram_type in kinds) {
|
||||
let [min, max, bucket_count] = [1, INT_MAX - 1, 10]
|
||||
test_histogram(histogram_type, "test::"+histogram_type, min, max, bucket_count);
|
||||
|
||||
|
||||
const nh = Telemetry.newHistogram;
|
||||
expect_fail(function () nh("test::min", 0, max, bucket_count, histogram_type));
|
||||
expect_fail(function () nh("test::bucket_count", min, max, 1, histogram_type));
|
||||
expect_fail(function () nh("test::min", "never", 0, max, bucket_count, histogram_type));
|
||||
expect_fail(function () nh("test::bucket_count", "never", min, max, 1, histogram_type));
|
||||
}
|
||||
|
||||
// Instantiate the storage for this histogram and make sure it doesn't
|
||||
@ -367,4 +384,5 @@ function run_test()
|
||||
test_privateMode();
|
||||
test_addons();
|
||||
test_extended_stats();
|
||||
test_expired_histogram();
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ netOffline=The application is currently in offline mode and can't access the net
|
||||
deniedPortAccess=The application tried to access a network port that it should not have access to. The application has canceled the request for your protection.
|
||||
proxyResolveFailure=The application is configured to use a proxy server that can't be found.
|
||||
proxyConnectFailure=The application is configured to use a proxy server that is refusing connections.
|
||||
contentEncodingError=The application recieved a response from a server which used an invalid or unsupported form of compression.
|
||||
contentEncodingError=The application received a response from a server which used an invalid or unsupported form of compression.
|
||||
unsafeContentType=The application cannot continue because it accessed a file type that may not be safe to open. Please contact the application authors to inform them of this problem.
|
||||
cspFrameAncestorBlocked=This application tried to access a resource that has a content security policy that prevents it from being embedded in this way.
|
||||
corruptedContentError=The application cannot continue loading because an error in the data transmission was detected.
|
||||
|
@ -52,13 +52,13 @@ SpecifiedWarning=Use of attributes' specified attribute is deprecated. It always
|
||||
OwnerElementWarning=Use of attributes' ownerElement attribute is deprecated.
|
||||
NodeValueWarning=Use of attributes' nodeValue attribute is deprecated. Use value instead.
|
||||
TextContentWarning=Use of attributes' textContent attribute is deprecated. Use value instead.
|
||||
EnablePrivilegeWarning=Use of enablePrivilege is deprecated. Please use code that runs with the system principal (e.g. an extension) instead.
|
||||
nsIJSONDecodeDeprecatedWarning=nsIJSON.decode is deprecated. Please use JSON.parse instead.
|
||||
nsIJSONEncodeDeprecatedWarning=nsIJSON.encode is deprecated. Please use JSON.stringify instead.
|
||||
EnablePrivilegeWarning=Use of enablePrivilege is deprecated. Please use code that runs with the system principal (e.g. an extension) instead.
|
||||
nsIJSONDecodeDeprecatedWarning=nsIJSON.decode is deprecated. Please use JSON.parse instead.
|
||||
nsIJSONEncodeDeprecatedWarning=nsIJSON.encode is deprecated. Please use JSON.stringify instead.
|
||||
nsIDOMWindowInternalWarning=Use of nsIDOMWindowInternal is deprecated. Use nsIDOMWindow instead.
|
||||
InputEncodingWarning=Use of inputEncoding is deprecated.
|
||||
# LOCALIZATION NOTE: Do not translate "MozBeforePaint" and "mozRequestAnimationFrame"
|
||||
MozBeforePaintWarning=MozBeforePaint events are no longer supported. mozRequestAnimationFrame must be passed a non-null callback argument.
|
||||
MozBeforePaintWarning=MozBeforePaint events are no longer supported. mozRequestAnimationFrame must be passed a non-null callback argument.
|
||||
FullScreenDeniedBlocked=Request for full-screen was denied because this domain has been blocked from full-screen by user.
|
||||
FullScreenDeniedDisabled=Request for full-screen was denied because full-screen API is disabled by user preference.
|
||||
FullScreenDeniedFocusedPlugin=Request for full-screen was denied because a windowed plugin is focused.
|
||||
@ -111,7 +111,7 @@ NoExposedPropsWarning=Exposing chrome JS objects to content without __exposedPro
|
||||
# LOCALIZATION NOTE: Do not translate "Mutation Event" and "MutationObserver"
|
||||
MutationEventWarning=Use of Mutation Events is deprecated. Use MutationObserver instead.
|
||||
# LOCALIZATION NOTE: Do not translate "Blob", "mozSlice", or "slice"
|
||||
MozSliceWarning=Use of mozSlice on the Blob object is deprecated. Use slice instead.
|
||||
MozSliceWarning=Use of mozSlice on the Blob object is deprecated. Use slice instead.
|
||||
# LOCALIZATION NOTE: Do not translate "Components"
|
||||
ComponentsWarning=The Components object is deprecated. It will soon be removed.
|
||||
PluginHangUITitle=Warning: Unresponsive plugin
|
||||
@ -119,21 +119,21 @@ PluginHangUIMessage=%S may be busy, or it may have stopped responding. You can s
|
||||
PluginHangUIWaitButton=Continue
|
||||
PluginHangUIStopButton=Stop plugin
|
||||
# LOCALIZATION NOTE: Do not translate "mozHidden", "mozVisibilityState", "hidden", or "visibilityState"
|
||||
PrefixedVisibilityApiWarning='mozHidden' and 'mozVisibilityState' are deprecated. Please use the unprefixed 'hidden' and 'visibilityState' instead.
|
||||
PrefixedVisibilityApiWarning='mozHidden' and 'mozVisibilityState' are deprecated. Please use the unprefixed 'hidden' and 'visibilityState' instead.
|
||||
# LOCALIZATION NOTE: Do not translate "NodeIterator" or "detach()".
|
||||
NodeIteratorDetachWarning=Calling detach() on a NodeIterator no longer has an effect.
|
||||
# LOCALIZATION NOTE: Do not translate "Mozilla Audio Data API" and "Web Audio API".
|
||||
MozAudioDataWarning=The Mozilla Audio Data API is deprecated. Please use the Web Audio API instead.
|
||||
MozAudioDataWarning=The Mozilla Audio Data API is deprecated. Please use the Web Audio API instead.
|
||||
# LOCALIZATION NOTE: Do not translate "LenientThis" and "this"
|
||||
LenientThisWarning=Ignoring get or set of property that has [LenientThis] because the "this" object is incorrect.
|
||||
# LOCALIZATION NOTE: Do not translate "nsIDOMWindowUtils", "getWindowWithOuterId", or "nsIWindowMediator"
|
||||
GetWindowWithOuterIdWarning=Use of nsIDOMWindowUtils.getOuterWindowWithId() is deprecated. Instead, use the nsIWindowMediator method of the same name.
|
||||
GetWindowWithOuterIdWarning=Use of nsIDOMWindowUtils.getOuterWindowWithId() is deprecated. Instead, use the nsIWindowMediator method of the same name.
|
||||
# LOCALIZATION NOTE: Do not translate "getPreventDefault" or "defaultPrevented".
|
||||
GetPreventDefaultWarning=Use of getPreventDefault() is deprecated. Use defaultPrevented instead.
|
||||
GetPreventDefaultWarning=Use of getPreventDefault() is deprecated. Use defaultPrevented instead.
|
||||
# LOCALIZATION NOTE: Do not translate "getUserData", "setUserData", "WeakMap", or "element.dataset".
|
||||
GetSetUserDataWarning=Use of getUserData() or setUserData() is deprecated. Use WeakMap or element.dataset instead.
|
||||
GetSetUserDataWarning=Use of getUserData() or setUserData() is deprecated. Use WeakMap or element.dataset instead.
|
||||
# LOCALIZATION NOTE: Do not translate "mozGetAsFile" or "toBlob"
|
||||
MozGetAsFileWarning=The non-standard mozGetAsFile method is deprecated and will soon be removed. Use the standard toBlob method instead.
|
||||
MozGetAsFileWarning=The non-standard mozGetAsFile method is deprecated and will soon be removed. Use the standard toBlob method instead.
|
||||
# LOCALIZATION NOTE: Do not translate "captureEvents()" or "addEventListener()"
|
||||
UseOfCaptureEventsWarning=Use of captureEvents() is deprecated. To upgrade your code, use the DOM 2 addEventListener() method. For more help http://developer.mozilla.org/en/docs/DOM:element.addEventListener
|
||||
# LOCALIZATION NOTE: Do not translate "releaseEvents()" or "removeEventListener()"
|
||||
@ -143,4 +143,4 @@ UseOfDOM3LoadMethodWarning=Use of document.load() is deprecated. To upgrade your
|
||||
# LOCALIZATION NOTE: Do not translate "window.showModalDialog()" or "window.open()"
|
||||
ShowModalDialogWarning=Use of window.showModalDialog() is deprecated. Use window.open() instead. For more help https://developer.mozilla.org/en-US/docs/Web/API/Window.open
|
||||
# LOCALIZATION NOTE: Do not translate "window._content" or "window.content"
|
||||
Window_ContentWarning=window._content is deprecated. Please use window.content instead.
|
||||
Window_ContentWarning=window._content is deprecated. Please use window.content instead.
|
||||
|
Loading…
x
Reference in New Issue
Block a user