mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge m-c to inbound
This commit is contained in:
commit
adf51a28f6
1
.hgtags
1
.hgtags
@ -102,3 +102,4 @@ ba2cc1eda988a1614d8986ae145d28e1268409b9 FIREFOX_AURORA_29_BASE
|
|||||||
83c9853e136451474dfa6d1aaa60a7fca7d2d83a FIREFOX_AURORA_30_BASE
|
83c9853e136451474dfa6d1aaa60a7fca7d2d83a FIREFOX_AURORA_30_BASE
|
||||||
cfde3603b0206e119abea76fdd6e134b634348f1 FIREFOX_AURORA_31_BASE
|
cfde3603b0206e119abea76fdd6e134b634348f1 FIREFOX_AURORA_31_BASE
|
||||||
16f3cac5e8fe471e12f76d6a94a477b14e78df7c FIREFOX_AURORA_32_BASE
|
16f3cac5e8fe471e12f76d6a94a477b14e78df7c FIREFOX_AURORA_32_BASE
|
||||||
|
dc23164ba2a289a8b22902e30990c77d9677c214 FIREFOX_AURORA_33_BASE
|
||||||
|
2
CLOBBER
2
CLOBBER
@ -22,4 +22,4 @@
|
|||||||
# changes to stick? As of bug 928195, this shouldn't be necessary! Please
|
# changes to stick? As of bug 928195, this shouldn't be necessary! Please
|
||||||
# don't change CLOBBER for WebIDL changes any more.
|
# don't change CLOBBER for WebIDL changes any more.
|
||||||
|
|
||||||
Clobber to work around bug 959928.
|
Merge day clobber
|
3
addon-sdk/source/examples/actor-repl/README.md
Normal file
3
addon-sdk/source/examples/actor-repl/README.md
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# Actor REPL
|
||||||
|
|
||||||
|
Simple REPL for a Firefox debugging protocol.
|
File diff suppressed because one or more lines are too long
264
addon-sdk/source/examples/actor-repl/data/codemirror.css
Normal file
264
addon-sdk/source/examples/actor-repl/data/codemirror.css
Normal file
@ -0,0 +1,264 @@
|
|||||||
|
/* BASICS */
|
||||||
|
|
||||||
|
.CodeMirror {
|
||||||
|
/* Set height, width, borders, and global font properties here */
|
||||||
|
font-family: monospace;
|
||||||
|
height: 300px;
|
||||||
|
}
|
||||||
|
.CodeMirror-scroll {
|
||||||
|
/* Set scrolling behaviour here */
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* PADDING */
|
||||||
|
|
||||||
|
.CodeMirror-lines {
|
||||||
|
padding: 4px 0; /* Vertical padding around content */
|
||||||
|
}
|
||||||
|
.CodeMirror pre {
|
||||||
|
padding: 0 4px; /* Horizontal padding of content */
|
||||||
|
}
|
||||||
|
|
||||||
|
.CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
|
||||||
|
background-color: white; /* The little square between H and V scrollbars */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* GUTTER */
|
||||||
|
|
||||||
|
.CodeMirror-gutters {
|
||||||
|
border-right: 1px solid #ddd;
|
||||||
|
background-color: #f7f7f7;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
.CodeMirror-linenumbers {}
|
||||||
|
.CodeMirror-linenumber {
|
||||||
|
padding: 0 3px 0 5px;
|
||||||
|
min-width: 20px;
|
||||||
|
text-align: right;
|
||||||
|
color: #999;
|
||||||
|
-moz-box-sizing: content-box;
|
||||||
|
box-sizing: content-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* CURSOR */
|
||||||
|
|
||||||
|
.CodeMirror div.CodeMirror-cursor {
|
||||||
|
border-left: 1px solid black;
|
||||||
|
z-index: 3;
|
||||||
|
}
|
||||||
|
/* Shown when moving in bi-directional text */
|
||||||
|
.CodeMirror div.CodeMirror-secondarycursor {
|
||||||
|
border-left: 1px solid silver;
|
||||||
|
}
|
||||||
|
.CodeMirror.cm-keymap-fat-cursor div.CodeMirror-cursor {
|
||||||
|
width: auto;
|
||||||
|
border: 0;
|
||||||
|
background: #7e7;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
/* Can style cursor different in overwrite (non-insert) mode */
|
||||||
|
.CodeMirror div.CodeMirror-cursor.CodeMirror-overwrite {}
|
||||||
|
|
||||||
|
.cm-tab { display: inline-block; }
|
||||||
|
|
||||||
|
.CodeMirror-ruler {
|
||||||
|
border-left: 1px solid #ccc;
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* DEFAULT THEME */
|
||||||
|
|
||||||
|
.cm-s-default .cm-keyword {color: #708;}
|
||||||
|
.cm-s-default .cm-atom {color: #219;}
|
||||||
|
.cm-s-default .cm-number {color: #164;}
|
||||||
|
.cm-s-default .cm-def {color: #00f;}
|
||||||
|
.cm-s-default .cm-variable {color: black;}
|
||||||
|
.cm-s-default .cm-variable-2 {color: #05a;}
|
||||||
|
.cm-s-default .cm-variable-3 {color: #085;}
|
||||||
|
.cm-s-default .cm-property {color: black;}
|
||||||
|
.cm-s-default .cm-operator {color: black;}
|
||||||
|
.cm-s-default .cm-comment {color: #a50;}
|
||||||
|
.cm-s-default .cm-string {color: #a11;}
|
||||||
|
.cm-s-default .cm-string-2 {color: #f50;}
|
||||||
|
.cm-s-default .cm-meta {color: #555;}
|
||||||
|
.cm-s-default .cm-qualifier {color: #555;}
|
||||||
|
.cm-s-default .cm-builtin {color: #30a;}
|
||||||
|
.cm-s-default .cm-bracket {color: #997;}
|
||||||
|
.cm-s-default .cm-tag {color: #170;}
|
||||||
|
.cm-s-default .cm-attribute {color: #00c;}
|
||||||
|
.cm-s-default .cm-header {color: blue;}
|
||||||
|
.cm-s-default .cm-quote {color: #090;}
|
||||||
|
.cm-s-default .cm-hr {color: #999;}
|
||||||
|
.cm-s-default .cm-link {color: #00c;}
|
||||||
|
|
||||||
|
.cm-negative {color: #d44;}
|
||||||
|
.cm-positive {color: #292;}
|
||||||
|
.cm-header, .cm-strong {font-weight: bold;}
|
||||||
|
.cm-em {font-style: italic;}
|
||||||
|
.cm-link {text-decoration: underline;}
|
||||||
|
|
||||||
|
.cm-s-default .cm-error {color: #f00;}
|
||||||
|
.cm-invalidchar {color: #f00;}
|
||||||
|
|
||||||
|
div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;}
|
||||||
|
div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
|
||||||
|
.CodeMirror-activeline-background {background: #e8f2ff;}
|
||||||
|
|
||||||
|
/* STOP */
|
||||||
|
|
||||||
|
/* The rest of this file contains styles related to the mechanics of
|
||||||
|
the editor. You probably shouldn't touch them. */
|
||||||
|
|
||||||
|
.CodeMirror {
|
||||||
|
line-height: 1;
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
background: white;
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.CodeMirror-scroll {
|
||||||
|
/* 30px is the magic margin used to hide the element's real scrollbars */
|
||||||
|
/* See overflow: hidden in .CodeMirror */
|
||||||
|
margin-bottom: -30px; margin-right: -30px;
|
||||||
|
padding-bottom: 30px;
|
||||||
|
height: 100%;
|
||||||
|
outline: none; /* Prevent dragging from highlighting the element */
|
||||||
|
position: relative;
|
||||||
|
-moz-box-sizing: content-box;
|
||||||
|
box-sizing: content-box;
|
||||||
|
}
|
||||||
|
.CodeMirror-sizer {
|
||||||
|
position: relative;
|
||||||
|
border-right: 30px solid transparent;
|
||||||
|
-moz-box-sizing: content-box;
|
||||||
|
box-sizing: content-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The fake, visible scrollbars. Used to force redraw during scrolling
|
||||||
|
before actuall scrolling happens, thus preventing shaking and
|
||||||
|
flickering artifacts. */
|
||||||
|
.CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 6;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.CodeMirror-vscrollbar {
|
||||||
|
right: 0; top: 0;
|
||||||
|
overflow-x: hidden;
|
||||||
|
overflow-y: scroll;
|
||||||
|
}
|
||||||
|
.CodeMirror-hscrollbar {
|
||||||
|
bottom: 0; left: 0;
|
||||||
|
overflow-y: hidden;
|
||||||
|
overflow-x: scroll;
|
||||||
|
}
|
||||||
|
.CodeMirror-scrollbar-filler {
|
||||||
|
right: 0; bottom: 0;
|
||||||
|
}
|
||||||
|
.CodeMirror-gutter-filler {
|
||||||
|
left: 0; bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.CodeMirror-gutters {
|
||||||
|
position: absolute; left: 0; top: 0;
|
||||||
|
padding-bottom: 30px;
|
||||||
|
z-index: 3;
|
||||||
|
}
|
||||||
|
.CodeMirror-gutter {
|
||||||
|
white-space: normal;
|
||||||
|
height: 100%;
|
||||||
|
-moz-box-sizing: content-box;
|
||||||
|
box-sizing: content-box;
|
||||||
|
padding-bottom: 30px;
|
||||||
|
margin-bottom: -32px;
|
||||||
|
display: inline-block;
|
||||||
|
/* Hack to make IE7 behave */
|
||||||
|
*zoom:1;
|
||||||
|
*display:inline;
|
||||||
|
}
|
||||||
|
.CodeMirror-gutter-elt {
|
||||||
|
position: absolute;
|
||||||
|
cursor: default;
|
||||||
|
z-index: 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.CodeMirror-lines {
|
||||||
|
cursor: text;
|
||||||
|
}
|
||||||
|
.CodeMirror pre {
|
||||||
|
/* Reset some styles that the rest of the page might have set */
|
||||||
|
-moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0;
|
||||||
|
border-width: 0;
|
||||||
|
background: transparent;
|
||||||
|
font-family: inherit;
|
||||||
|
font-size: inherit;
|
||||||
|
margin: 0;
|
||||||
|
white-space: pre;
|
||||||
|
word-wrap: normal;
|
||||||
|
line-height: inherit;
|
||||||
|
color: inherit;
|
||||||
|
z-index: 2;
|
||||||
|
position: relative;
|
||||||
|
overflow: visible;
|
||||||
|
}
|
||||||
|
.CodeMirror-wrap pre {
|
||||||
|
word-wrap: break-word;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
word-break: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.CodeMirror-linebackground {
|
||||||
|
position: absolute;
|
||||||
|
left: 0; right: 0; top: 0; bottom: 0;
|
||||||
|
z-index: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.CodeMirror-linewidget {
|
||||||
|
position: relative;
|
||||||
|
z-index: 2;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.CodeMirror-widget {}
|
||||||
|
|
||||||
|
.CodeMirror-wrap .CodeMirror-scroll {
|
||||||
|
overflow-x: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.CodeMirror-measure {
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
height: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
.CodeMirror-measure pre { position: static; }
|
||||||
|
|
||||||
|
.CodeMirror div.CodeMirror-cursor {
|
||||||
|
position: absolute;
|
||||||
|
visibility: hidden;
|
||||||
|
border-right: none;
|
||||||
|
width: 0;
|
||||||
|
}
|
||||||
|
.CodeMirror-focused div.CodeMirror-cursor {
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
.CodeMirror-selected { background: #d9d9d9; }
|
||||||
|
.CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; }
|
||||||
|
|
||||||
|
.cm-searching {
|
||||||
|
background: #ffa;
|
||||||
|
background: rgba(255, 255, 0, .4);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* IE7 hack to prevent it from returning funny offsetTops on the spans */
|
||||||
|
.CodeMirror span { *vertical-align: text-bottom; }
|
||||||
|
|
||||||
|
@media print {
|
||||||
|
/* Hide the cursor when printing */
|
||||||
|
.CodeMirror div.CodeMirror-cursor {
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
}
|
108
addon-sdk/source/examples/actor-repl/data/index.html
Normal file
108
addon-sdk/source/examples/actor-repl/data/index.html
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
<!-- 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/. -->
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<link rel="stylesheet" href="./codemirror.css">
|
||||||
|
<link rel="stylesheet" href="./main.css">
|
||||||
|
<script src="./codemirror-compressed.js"></script>
|
||||||
|
<views>
|
||||||
|
<section class="task cm-s-default">
|
||||||
|
<pre class="request "></pre>
|
||||||
|
<pre class="response"><span class="one"></span><span class="two"></span><span class="three"></span></pre>
|
||||||
|
</section>
|
||||||
|
</views>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<pre class="input"></pre>
|
||||||
|
</body>
|
||||||
|
<script>
|
||||||
|
function debounce(fn, ms) {
|
||||||
|
var id
|
||||||
|
return function(...args) {
|
||||||
|
clearTimeout(id)
|
||||||
|
id = setTimeout(fn, ms, ...args)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Try(fn) {
|
||||||
|
return function(...args) {
|
||||||
|
try { return fn(...args) }
|
||||||
|
catch (error) { return null }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var parse = Try(JSON.parse)
|
||||||
|
|
||||||
|
function send(editor) {
|
||||||
|
var input = editor.getWrapperElement().parentNode
|
||||||
|
var code = editor.getValue().trim()
|
||||||
|
var packet = parse(code)
|
||||||
|
if (packet) {
|
||||||
|
var task = document.querySelector("views .task").cloneNode(true)
|
||||||
|
var request = task.querySelector(".request")
|
||||||
|
var response = task.querySelector(".response")
|
||||||
|
|
||||||
|
input.parentNode.insertBefore(task, input)
|
||||||
|
|
||||||
|
CodeMirror.runMode(JSON.stringify(packet, 2, 2),
|
||||||
|
"application/json",
|
||||||
|
request)
|
||||||
|
response.classList.add("pending")
|
||||||
|
|
||||||
|
editor.setValue("")
|
||||||
|
document.activeElement.scrollIntoView()
|
||||||
|
|
||||||
|
port.postMessage(packet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var editor = CodeMirror(document.querySelector(".input"), {
|
||||||
|
autofocus: true,
|
||||||
|
mode: "application/json",
|
||||||
|
matchBrackets: true,
|
||||||
|
value: '{"to": "root", "type": "requestTypes"}',
|
||||||
|
extraKeys: {"Cmd-Enter": send,
|
||||||
|
"Ctrl-Enter": send}
|
||||||
|
});
|
||||||
|
editor.on("change", debounce(function(editor) {
|
||||||
|
var input = editor.getWrapperElement().parentNode;
|
||||||
|
if (parse(editor.getValue().trim()))
|
||||||
|
input.classList.remove("invalid")
|
||||||
|
else
|
||||||
|
input.classList.add("invalid")
|
||||||
|
}, 800))
|
||||||
|
</script>
|
||||||
|
<script>
|
||||||
|
window.addEventListener("message", event => {
|
||||||
|
console.log("REPL", event);
|
||||||
|
window.port = event.ports[0];
|
||||||
|
port.onmessage = onMessage;
|
||||||
|
});
|
||||||
|
|
||||||
|
var onMessage = (event) => {
|
||||||
|
var packet = event.data;
|
||||||
|
var code = JSON.stringify(packet, 2, 2);
|
||||||
|
|
||||||
|
var input = editor.getWrapperElement().parentNode;
|
||||||
|
var response = document.querySelector(".task .response.pending")
|
||||||
|
|
||||||
|
if (!response) {
|
||||||
|
message = document.querySelector("views .task").cloneNode(true)
|
||||||
|
response = message.querySelector(".response")
|
||||||
|
response.classList.add("message")
|
||||||
|
|
||||||
|
input.parentNode.insertBefore(message, input);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (packet.error)
|
||||||
|
response.classList.add("error");
|
||||||
|
|
||||||
|
|
||||||
|
CodeMirror.runMode(code, "application/json", response);
|
||||||
|
response.classList.remove("pending");
|
||||||
|
|
||||||
|
document.activeElement.scrollIntoView()
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
</html>
|
117
addon-sdk/source/examples/actor-repl/data/main.css
Normal file
117
addon-sdk/source/examples/actor-repl/data/main.css
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
body
|
||||||
|
{
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
background: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pre
|
||||||
|
{
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
section
|
||||||
|
{
|
||||||
|
border-top: 1px solid rgba(150, 150, 150, 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
.CodeMirror {
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
.CodeMirror-scroll {
|
||||||
|
overflow-y: hidden;
|
||||||
|
overflow-x: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.request,
|
||||||
|
.response,
|
||||||
|
.input
|
||||||
|
{
|
||||||
|
border-left: 5px solid;
|
||||||
|
padding-left: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.request:not(:empty),
|
||||||
|
.response.pending
|
||||||
|
{
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input
|
||||||
|
{
|
||||||
|
padding-left: 6px;
|
||||||
|
border-color: lightgreen;
|
||||||
|
}
|
||||||
|
.input.invalid
|
||||||
|
{
|
||||||
|
border-color: orange;
|
||||||
|
}
|
||||||
|
|
||||||
|
.request
|
||||||
|
{
|
||||||
|
border-color: lightgrey;
|
||||||
|
}
|
||||||
|
|
||||||
|
.response
|
||||||
|
{
|
||||||
|
border-color: grey;
|
||||||
|
}
|
||||||
|
.response.error
|
||||||
|
{
|
||||||
|
border-color: red;
|
||||||
|
}
|
||||||
|
|
||||||
|
.response.message
|
||||||
|
{
|
||||||
|
border-color: lightblue;
|
||||||
|
}
|
||||||
|
|
||||||
|
.response .one,
|
||||||
|
.response .two,
|
||||||
|
.response .three
|
||||||
|
{
|
||||||
|
width: 0;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.response.pending .one,
|
||||||
|
.response.pending .two,
|
||||||
|
.response.pending .three
|
||||||
|
{
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
background-color: rgba(150, 150, 150, 0.5);
|
||||||
|
|
||||||
|
border-radius: 100%;
|
||||||
|
display: inline-block;
|
||||||
|
animation: bouncedelay 1.4s infinite ease-in-out;
|
||||||
|
/* Prevent first frame from flickering when animation starts */
|
||||||
|
animation-fill-mode: both;
|
||||||
|
}
|
||||||
|
|
||||||
|
.response.pending .one
|
||||||
|
{
|
||||||
|
animation-delay: -0.32s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.response.pending .two
|
||||||
|
{
|
||||||
|
animation-delay: -0.16s;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes bouncedelay {
|
||||||
|
0%, 80%, 100% {
|
||||||
|
transform: scale(0.0);
|
||||||
|
} 40% {
|
||||||
|
transform: scale(1.0);
|
||||||
|
}
|
||||||
|
}
|
BIN
addon-sdk/source/examples/actor-repl/data/robot.png
Normal file
BIN
addon-sdk/source/examples/actor-repl/data/robot.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.1 KiB |
37
addon-sdk/source/examples/actor-repl/index.js
Normal file
37
addon-sdk/source/examples/actor-repl/index.js
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
/* 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/. */
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
const { Panel } = require("dev/panel");
|
||||||
|
const { Tool } = require("dev/toolbox");
|
||||||
|
const { Class } = require("sdk/core/heritage");
|
||||||
|
|
||||||
|
|
||||||
|
const REPLPanel = Class({
|
||||||
|
extends: Panel,
|
||||||
|
label: "Actor REPL",
|
||||||
|
tooltip: "Firefox debugging protocol REPL",
|
||||||
|
icon: "./robot.png",
|
||||||
|
url: "./index.html",
|
||||||
|
setup: function({debuggee}) {
|
||||||
|
this.debuggee = debuggee;
|
||||||
|
},
|
||||||
|
dispose: function() {
|
||||||
|
this.debuggee = null;
|
||||||
|
},
|
||||||
|
onReady: function() {
|
||||||
|
console.log("repl panel document is interactive");
|
||||||
|
this.debuggee.start();
|
||||||
|
this.postMessage("RDP", [this.debuggee]);
|
||||||
|
},
|
||||||
|
onLoad: function() {
|
||||||
|
console.log("repl panel document is fully loaded");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
exports.REPLPanel = REPLPanel;
|
||||||
|
|
||||||
|
|
||||||
|
const replTool = new Tool({
|
||||||
|
panels: { repl: REPLPanel }
|
||||||
|
});
|
10
addon-sdk/source/examples/actor-repl/package.json
Normal file
10
addon-sdk/source/examples/actor-repl/package.json
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"name": "actor-repl",
|
||||||
|
"id": "@actor-repl",
|
||||||
|
"title": "Actor REPL",
|
||||||
|
"description": "Actor REPL",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"author": "Irakli Gozalishvili",
|
||||||
|
"main": "./index.js",
|
||||||
|
"license": "MPL 2.0"
|
||||||
|
}
|
816
addon-sdk/source/examples/debug-client/data/client.js
Normal file
816
addon-sdk/source/examples/debug-client/data/client.js
Normal file
@ -0,0 +1,816 @@
|
|||||||
|
/* 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/. */
|
||||||
|
(function(exports) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
|
||||||
|
var describe = Object.getOwnPropertyDescriptor;
|
||||||
|
var Class = fields => {
|
||||||
|
var constructor = fields.constructor || function() {};
|
||||||
|
var ancestor = fields.extends || Object;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
var descriptor = {};
|
||||||
|
for (var key of Object.keys(fields))
|
||||||
|
descriptor[key] = describe(fields, key);
|
||||||
|
|
||||||
|
var prototype = Object.create(ancestor.prototype, descriptor);
|
||||||
|
|
||||||
|
constructor.prototype = prototype;
|
||||||
|
prototype.constructor = constructor;
|
||||||
|
|
||||||
|
return constructor;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
var bus = function Bus() {
|
||||||
|
var parser = new DOMParser();
|
||||||
|
return parser.parseFromString("<EventTarget/>", "application/xml").documentElement;
|
||||||
|
}();
|
||||||
|
|
||||||
|
var GUID = new WeakMap();
|
||||||
|
GUID.id = 0;
|
||||||
|
var guid = x => GUID.get(x);
|
||||||
|
var setGUID = x => {
|
||||||
|
GUID.set(x, ++ GUID.id);
|
||||||
|
};
|
||||||
|
|
||||||
|
var Emitter = Class({
|
||||||
|
extends: EventTarget,
|
||||||
|
constructor: function() {
|
||||||
|
this.setupEmitter();
|
||||||
|
},
|
||||||
|
setupEmitter: function() {
|
||||||
|
setGUID(this);
|
||||||
|
},
|
||||||
|
addEventListener: function(type, listener, capture) {
|
||||||
|
bus.addEventListener(type + "@" + guid(this),
|
||||||
|
listener, capture);
|
||||||
|
},
|
||||||
|
removeEventListener: function(type, listener, capture) {
|
||||||
|
bus.removeEventListener(type + "@" + guid(this),
|
||||||
|
listener, capture);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function dispatch(target, type, data) {
|
||||||
|
var event = new MessageEvent(type + "@" + guid(target), {
|
||||||
|
bubbles: true,
|
||||||
|
cancelable: false,
|
||||||
|
data: data
|
||||||
|
});
|
||||||
|
bus.dispatchEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
var supervisedWorkers = new WeakMap();
|
||||||
|
var supervised = supervisor => {
|
||||||
|
if (!supervisedWorkers.has(supervisor)) {
|
||||||
|
supervisedWorkers.set(supervisor, new Map());
|
||||||
|
supervisor.connection.addActorPool(supervisor);
|
||||||
|
}
|
||||||
|
return supervisedWorkers.get(supervisor);
|
||||||
|
};
|
||||||
|
|
||||||
|
var Supervisor = Class({
|
||||||
|
extends: Emitter,
|
||||||
|
constructor: function(...params) {
|
||||||
|
this.setupEmitter(...params);
|
||||||
|
this.setupSupervisor(...params);
|
||||||
|
},
|
||||||
|
Supervisor: function(connection) {
|
||||||
|
this.connection = connection;
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* Return the parent pool for this client.
|
||||||
|
*/
|
||||||
|
supervisor: function() {
|
||||||
|
return this.connection.poolFor(this.actorID);
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* Override this if you want actors returned by this actor
|
||||||
|
* to belong to a different actor by default.
|
||||||
|
*/
|
||||||
|
marshallPool: function() { return this; },
|
||||||
|
/**
|
||||||
|
* Add an actor as a child of this pool.
|
||||||
|
*/
|
||||||
|
supervise: function(actor) {
|
||||||
|
if (!actor.actorID)
|
||||||
|
actor.actorID = this.connection.allocID(actor.actorPrefix ||
|
||||||
|
actor.typeName);
|
||||||
|
|
||||||
|
supervised(this).set(actor.actorID, actor);
|
||||||
|
return actor;
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* Remove an actor as a child of this pool.
|
||||||
|
*/
|
||||||
|
abandon: function(actor) {
|
||||||
|
supervised(this).delete(actor.actorID);
|
||||||
|
},
|
||||||
|
// true if the given actor ID exists in the pool.
|
||||||
|
has: function(actorID) {
|
||||||
|
return supervised(this).has(actorID);
|
||||||
|
},
|
||||||
|
// Same as actor, should update debugger connection to use 'actor'
|
||||||
|
// and then remove this.
|
||||||
|
get: function(actorID) {
|
||||||
|
return supervised(this).get(actorID);
|
||||||
|
},
|
||||||
|
actor: function(actorID) {
|
||||||
|
return supervised(this).get(actorID);
|
||||||
|
},
|
||||||
|
isEmpty: function() {
|
||||||
|
return supervised(this).size === 0;
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* For getting along with the debugger server pools, should be removable
|
||||||
|
* eventually.
|
||||||
|
*/
|
||||||
|
cleanup: function() {
|
||||||
|
this.destroy();
|
||||||
|
},
|
||||||
|
destroy: function() {
|
||||||
|
var supervisor = this.supervisor();
|
||||||
|
if (supervisor)
|
||||||
|
supervisor.abandon(this);
|
||||||
|
|
||||||
|
for (var actor of supervised(this).values()) {
|
||||||
|
if (actor !== this) {
|
||||||
|
var destroy = actor.destroy;
|
||||||
|
// Disconnect destroy while we're destroying in case of (misbehaving)
|
||||||
|
// circular ownership.
|
||||||
|
if (destroy) {
|
||||||
|
actor.destroy = null;
|
||||||
|
destroy.call(actor);
|
||||||
|
actor.destroy = destroy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.connection.removeActorPool(this);
|
||||||
|
supervised(this).clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
var mailbox = new WeakMap();
|
||||||
|
var clientRequests = new WeakMap();
|
||||||
|
|
||||||
|
var inbox = client => mailbox.get(client).inbox;
|
||||||
|
var outbox = client => mailbox.get(client).outbox;
|
||||||
|
var requests = client => clientRequests.get(client);
|
||||||
|
|
||||||
|
|
||||||
|
var Receiver = Class({
|
||||||
|
receive: function(packet) {
|
||||||
|
if (packet.error)
|
||||||
|
this.reject(packet.error);
|
||||||
|
else
|
||||||
|
this.resolve(this.read(packet));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var Connection = Class({
|
||||||
|
constructor: function() {
|
||||||
|
// Queue of the outgoing messages.
|
||||||
|
this.outbox = [];
|
||||||
|
// Map of pending requests.
|
||||||
|
this.pending = new Map();
|
||||||
|
this.pools = new Set();
|
||||||
|
},
|
||||||
|
isConnected: function() {
|
||||||
|
return !!this.port
|
||||||
|
},
|
||||||
|
connect: function(port) {
|
||||||
|
this.port = port;
|
||||||
|
port.addEventListener("message", this);
|
||||||
|
port.start();
|
||||||
|
|
||||||
|
this.flush();
|
||||||
|
},
|
||||||
|
addPool: function(pool) {
|
||||||
|
this.pools.add(pool);
|
||||||
|
},
|
||||||
|
removePool: function(pool) {
|
||||||
|
this.pools.delete(pool);
|
||||||
|
},
|
||||||
|
poolFor: function(id) {
|
||||||
|
for (let pool of this.pools.values()) {
|
||||||
|
if pool.has(id)
|
||||||
|
return pool;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
get: function(id) {
|
||||||
|
var pool = this.poolFor(id);
|
||||||
|
return pool && pool.get(id);
|
||||||
|
},
|
||||||
|
disconnect: function() {
|
||||||
|
this.port.stop();
|
||||||
|
this.port = null;
|
||||||
|
for (var request of this.pending.values()) {
|
||||||
|
request.catch(new Error("Connection closed"));
|
||||||
|
}
|
||||||
|
this.pending.clear();
|
||||||
|
|
||||||
|
var requests = this.outbox.splice(0);
|
||||||
|
for (var request of request) {
|
||||||
|
requests.catch(new Error("Connection closed"));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
handleEvent: function(event) {
|
||||||
|
this.receive(event.data);
|
||||||
|
},
|
||||||
|
flush: function() {
|
||||||
|
if (this.isConnected()) {
|
||||||
|
for (var request of this.outbox) {
|
||||||
|
if (!this.pending.has(request.to)) {
|
||||||
|
this.outbox.splice(this.outbox.indexOf(request), 1);
|
||||||
|
this.pending.set(request.to, request);
|
||||||
|
this.send(request.packet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
send: function(packet) {
|
||||||
|
this.port.postMessage(packet);
|
||||||
|
},
|
||||||
|
request: function(packet) {
|
||||||
|
return new Promise(function(resolve, reject) {
|
||||||
|
this.outbox.push({
|
||||||
|
to: packet.to,
|
||||||
|
packet: packet,
|
||||||
|
receive: resolve,
|
||||||
|
catch: reject
|
||||||
|
});
|
||||||
|
this.flush();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
receive: function(packet) {
|
||||||
|
var { from, type, why } = packet;
|
||||||
|
var receiver = this.pending.get(from);
|
||||||
|
if (!receiver) {
|
||||||
|
console.warn("Unable to handle received packet", data);
|
||||||
|
} else {
|
||||||
|
this.pending.delete(from);
|
||||||
|
if (packet.error)
|
||||||
|
receiver.catch(packet.error);
|
||||||
|
else
|
||||||
|
receiver.receive(packet);
|
||||||
|
}
|
||||||
|
this.flush();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base class for client-side actor fronts.
|
||||||
|
*/
|
||||||
|
var Client = Class({
|
||||||
|
extends: Supervisor,
|
||||||
|
constructor: function(from=null, detail=null, connection=null) {
|
||||||
|
this.Client(from, detail, connection);
|
||||||
|
},
|
||||||
|
Client: function(form, detail, connection) {
|
||||||
|
this.Supervisor(connection);
|
||||||
|
|
||||||
|
if (form) {
|
||||||
|
this.actorID = form.actor;
|
||||||
|
this.from(form, detail);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
connect: function(port) {
|
||||||
|
this.connection = new Connection(port);
|
||||||
|
},
|
||||||
|
actorID: null,
|
||||||
|
actor: function() {
|
||||||
|
return this.actorID;
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* Update the actor from its representation.
|
||||||
|
* Subclasses should override this.
|
||||||
|
*/
|
||||||
|
form: function(form) {
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* Method is invokeid when packet received constitutes an
|
||||||
|
* event. By default such packets are demarshalled and
|
||||||
|
* dispatched on the client instance.
|
||||||
|
*/
|
||||||
|
dispatch: function(packet) {
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* Method is invoked when packet is returned in response to
|
||||||
|
* a request. By default respond delivers response to a first
|
||||||
|
* request in a queue.
|
||||||
|
*/
|
||||||
|
read: function(input) {
|
||||||
|
throw new TypeError("Subclass must implement read method");
|
||||||
|
},
|
||||||
|
write: function(input) {
|
||||||
|
throw new TypeError("Subclass must implement write method");
|
||||||
|
},
|
||||||
|
respond: function(packet) {
|
||||||
|
var [resolve, reject] = requests(this).shift();
|
||||||
|
if (packet.error)
|
||||||
|
reject(packet.error);
|
||||||
|
else
|
||||||
|
resolve(this.read(packet));
|
||||||
|
},
|
||||||
|
receive: function(packet) {
|
||||||
|
if (this.isEventPacket(packet)) {
|
||||||
|
this.dispatch(packet);
|
||||||
|
}
|
||||||
|
else if (requests(this).length) {
|
||||||
|
this.respond(packet);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.catch(packet);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
send: function(packet) {
|
||||||
|
Promise.cast(packet.to || this.actor()).then(id => {
|
||||||
|
packet.to = id;
|
||||||
|
this.connection.send(packet);
|
||||||
|
})
|
||||||
|
},
|
||||||
|
request: function(packet) {
|
||||||
|
return this.connection.request(packet);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
var Destructor = method => {
|
||||||
|
return function(...args) {
|
||||||
|
return method.apply(this, args).then(result => {
|
||||||
|
this.destroy();
|
||||||
|
return result;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
var Profiled = (method, id) => {
|
||||||
|
return function(...args) {
|
||||||
|
var start = new Date();
|
||||||
|
return method.apply(this, args).then(result => {
|
||||||
|
var end = new Date();
|
||||||
|
this.telemetry.add(id, +end - start);
|
||||||
|
return result;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
var Method = (request, response) => {
|
||||||
|
return response ? new BidirectionalMethod(request, response) :
|
||||||
|
new UnidirecationalMethod(request);
|
||||||
|
};
|
||||||
|
|
||||||
|
var UnidirecationalMethod = request => {
|
||||||
|
return function(...args) {
|
||||||
|
var packet = request.write(args, this);
|
||||||
|
this.connection.send(packet);
|
||||||
|
return Promise.resolve(void(0));
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
var BidirectionalMethod = (request, response) => {
|
||||||
|
return function(...args) {
|
||||||
|
var packet = request.write(args, this);
|
||||||
|
return this.connection.request(packet).then(packet => {
|
||||||
|
return response.read(packet, this);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Client.from = ({category, typeName, methods, events}) => {
|
||||||
|
var proto = {
|
||||||
|
constructor: function(...args) {
|
||||||
|
this.Client(...args);
|
||||||
|
},
|
||||||
|
extends: Client,
|
||||||
|
name: typeName
|
||||||
|
};
|
||||||
|
|
||||||
|
methods.forEach(({telemetry, request, response, name, oneway, release}) => {
|
||||||
|
var [reader, writer] = oneway ? [, new Request(request)] :
|
||||||
|
[new Request(request), new Response(response)];
|
||||||
|
var method = new Method(request, response);
|
||||||
|
var profiler = telemetry ? new Profiler(method) : method;
|
||||||
|
var destructor = release ? new Destructor(profiler) : profiler;
|
||||||
|
proto[name] = destructor;
|
||||||
|
});
|
||||||
|
|
||||||
|
return Class(proto);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
var defineType = (client, descriptor) => {
|
||||||
|
var type = void(0)
|
||||||
|
if (typeof(descriptor) === "string") {
|
||||||
|
if (name.indexOf(":") > 0)
|
||||||
|
type = makeCompoundType(descriptor);
|
||||||
|
else if (name.indexOf("#") > 0)
|
||||||
|
type = new ActorDetail(descriptor);
|
||||||
|
else if (client.specification[descriptor])
|
||||||
|
type = makeCategoryType(client.specification[descriptor]);
|
||||||
|
} else {
|
||||||
|
type = makeCategoryType(descriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type)
|
||||||
|
client.types.set(type.name, type);
|
||||||
|
else
|
||||||
|
throw TypeError("Invalid type: " + descriptor);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
var makeCompoundType = name => {
|
||||||
|
var index = name.indexOf(":");
|
||||||
|
var [baseType, subType] = [name.slice(0, index), parts.slice(1)];
|
||||||
|
return baseType === "array" ? new ArrayOf(subType) :
|
||||||
|
baseType === "nullable" ? new Maybe(subType) :
|
||||||
|
null;
|
||||||
|
};
|
||||||
|
|
||||||
|
var makeCategoryType = (descriptor) => {
|
||||||
|
var { category } = descriptor;
|
||||||
|
return category === "dict" ? new Dictionary(descriptor) :
|
||||||
|
category === "actor" ? new Actor(descriptor) :
|
||||||
|
null;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
var typeFor = (client, type="primitive") => {
|
||||||
|
if (!client.types.has(type))
|
||||||
|
defineType(client, type);
|
||||||
|
|
||||||
|
return client.types.get(type);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
var Client = Class({
|
||||||
|
constructor: function() {
|
||||||
|
},
|
||||||
|
setupTypes: function(specification) {
|
||||||
|
this.specification = specification;
|
||||||
|
this.types = new Map();
|
||||||
|
},
|
||||||
|
read: function(input, type) {
|
||||||
|
return typeFor(this, type).read(input, this);
|
||||||
|
},
|
||||||
|
write: function(input, type) {
|
||||||
|
return typeFor(this, type).write(input, this);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
var Type = Class({
|
||||||
|
get name() {
|
||||||
|
return this.category ? this.category + ":" + this.type :
|
||||||
|
this.type;
|
||||||
|
},
|
||||||
|
read: function(input, client) {
|
||||||
|
throw new TypeError("`Type` subclass must implement `read`");
|
||||||
|
},
|
||||||
|
write: function(input, client) {
|
||||||
|
throw new TypeError("`Type` subclass must implement `write`");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
var Primitve = Class({
|
||||||
|
extends: Type,
|
||||||
|
constuctor: function(type) {
|
||||||
|
this.type = type;
|
||||||
|
},
|
||||||
|
read: function(input, client) {
|
||||||
|
return input;
|
||||||
|
},
|
||||||
|
write: function(input, client) {
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var Maybe = Class({
|
||||||
|
extends: Type,
|
||||||
|
category: "nullable",
|
||||||
|
constructor: function(type) {
|
||||||
|
this.type = type;
|
||||||
|
},
|
||||||
|
read: function(input, client) {
|
||||||
|
return input === null ? null :
|
||||||
|
input === void(0) ? void(0) :
|
||||||
|
client.read(input, this.type);
|
||||||
|
},
|
||||||
|
write: function(input, client) {
|
||||||
|
return input === null ? null :
|
||||||
|
input === void(0) ? void(0) :
|
||||||
|
client.write(input, this.type);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var ArrayOf = Class({
|
||||||
|
extends: Type,
|
||||||
|
category: "array",
|
||||||
|
constructor: function(type) {
|
||||||
|
this.type = type;
|
||||||
|
},
|
||||||
|
read: function(input, client) {
|
||||||
|
return input.map($ => client.read($, this.type));
|
||||||
|
},
|
||||||
|
write: function(input, client) {
|
||||||
|
return input.map($ => client.write($, this.type));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var Dictionary = Class({
|
||||||
|
exteds: Type,
|
||||||
|
category: "dict",
|
||||||
|
get name() { return this.type; },
|
||||||
|
constructor: function({typeName, specializations}) {
|
||||||
|
this.type = typeName;
|
||||||
|
this.types = specifications;
|
||||||
|
},
|
||||||
|
read: function(input, client) {
|
||||||
|
var output = {};
|
||||||
|
for (var key in input) {
|
||||||
|
output[key] = client.read(input[key], this.types[key]);
|
||||||
|
}
|
||||||
|
return output;
|
||||||
|
},
|
||||||
|
write: function(input, client) {
|
||||||
|
var output = {};
|
||||||
|
for (var key in input) {
|
||||||
|
output[key] = client.write(value, this.types[key]);
|
||||||
|
}
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var Actor = Class({
|
||||||
|
exteds: Type,
|
||||||
|
category: "actor",
|
||||||
|
get name() { return this.type; },
|
||||||
|
constructor: function({typeName}) {
|
||||||
|
this.type = typeName;
|
||||||
|
},
|
||||||
|
read: function(input, client, detail) {
|
||||||
|
var id = value.actor;
|
||||||
|
var actor = void(0);
|
||||||
|
if (client.connection.has(id)) {
|
||||||
|
return client.connection.get(id).form(input, detail, client);
|
||||||
|
} else {
|
||||||
|
actor = Client.from(detail, client);
|
||||||
|
actor.actorID = id;
|
||||||
|
client.supervise(actor);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
write: function(input, client, detail) {
|
||||||
|
if (input instanceof Actor) {
|
||||||
|
if (!input.actorID) {
|
||||||
|
client.supervise(input);
|
||||||
|
}
|
||||||
|
return input.from(detail);
|
||||||
|
}
|
||||||
|
return input.actorID;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var Root = Client.from({
|
||||||
|
"category": "actor",
|
||||||
|
"typeName": "root",
|
||||||
|
"methods": [
|
||||||
|
{"name": "listTabs",
|
||||||
|
"request": {},
|
||||||
|
"response": {
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{"name": "listAddons"
|
||||||
|
},
|
||||||
|
{"name": "echo",
|
||||||
|
|
||||||
|
},
|
||||||
|
{"name": "protocolDescription",
|
||||||
|
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
var ActorDetail = Class({
|
||||||
|
extends: Actor,
|
||||||
|
constructor: function(name, actor, detail) {
|
||||||
|
this.detail = detail;
|
||||||
|
this.actor = actor;
|
||||||
|
},
|
||||||
|
read: function(input, client) {
|
||||||
|
this.actor.read(input, client, this.detail);
|
||||||
|
},
|
||||||
|
write: function(input, client) {
|
||||||
|
this.actor.write(input, client, this.detail);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var registeredLifetimes = new Map();
|
||||||
|
var LifeTime = Class({
|
||||||
|
extends: Type,
|
||||||
|
category: "lifetime",
|
||||||
|
constructor: function(lifetime, type) {
|
||||||
|
this.name = lifetime + ":" + type.name;
|
||||||
|
this.field = registeredLifetimes.get(lifetime);
|
||||||
|
},
|
||||||
|
read: function(input, client) {
|
||||||
|
return this.type.read(input, client[this.field]);
|
||||||
|
},
|
||||||
|
write: function(input, client) {
|
||||||
|
return this.type.write(input, client[this.field]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var primitive = new Primitve("primitive");
|
||||||
|
var string = new Primitve("string");
|
||||||
|
var number = new Primitve("number");
|
||||||
|
var boolean = new Primitve("boolean");
|
||||||
|
var json = new Primitve("json");
|
||||||
|
var array = new Primitve("array");
|
||||||
|
|
||||||
|
|
||||||
|
var TypedValue = Class({
|
||||||
|
extends: Type,
|
||||||
|
constructor: function(name, type) {
|
||||||
|
this.TypedValue(name, type);
|
||||||
|
},
|
||||||
|
TypedValue: function(name, type) {
|
||||||
|
this.name = name;
|
||||||
|
this.type = type;
|
||||||
|
},
|
||||||
|
read: function(input, client) {
|
||||||
|
return this.client.read(input, this.type);
|
||||||
|
},
|
||||||
|
write: function(input, client) {
|
||||||
|
return this.client.write(input, this.type);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var Return = Class({
|
||||||
|
extends: TypedValue,
|
||||||
|
constructor: function(type) {
|
||||||
|
this.type = type
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var Argument = Class({
|
||||||
|
extends: TypedValue,
|
||||||
|
constructor: function(...args) {
|
||||||
|
this.Argument(...args);
|
||||||
|
},
|
||||||
|
Argument: function(index, type) {
|
||||||
|
this.index = index;
|
||||||
|
this.TypedValue("argument[" + index + "]", type);
|
||||||
|
},
|
||||||
|
read: function(input, client, target) {
|
||||||
|
return target[this.index] = client.read(input, this.type);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var Option = Class({
|
||||||
|
extends: Argument,
|
||||||
|
constructor: function(...args) {
|
||||||
|
return this.Argument(...args);
|
||||||
|
},
|
||||||
|
read: function(input, client, target, name) {
|
||||||
|
var param = target[this.index] || (target[this.index] = {});
|
||||||
|
param[name] = input === void(0) ? input : client.read(input, this.type);
|
||||||
|
},
|
||||||
|
write: function(input, client, name) {
|
||||||
|
var value = input && input[name];
|
||||||
|
return value === void(0) ? value : client.write(value, this.type);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var Request = Class({
|
||||||
|
extends: Type,
|
||||||
|
constructor: function(template={}) {
|
||||||
|
this.type = template.type;
|
||||||
|
this.template = template;
|
||||||
|
this.params = findPlaceholders(template, Argument);
|
||||||
|
},
|
||||||
|
read: function(packet, client) {
|
||||||
|
var args = [];
|
||||||
|
for (var param of this.params) {
|
||||||
|
var {placeholder, path} = param;
|
||||||
|
var name = path[path.length - 1];
|
||||||
|
placeholder.read(getPath(packet, path), client, args, name);
|
||||||
|
// TODO:
|
||||||
|
// args[placeholder.index] = placeholder.read(query(packet, path), client);
|
||||||
|
}
|
||||||
|
return args;
|
||||||
|
},
|
||||||
|
write: function(input, client) {
|
||||||
|
return JSON.parse(JSON.stringify(this.template, (key, value) => {
|
||||||
|
return value instanceof Argument ? value.write(input[value.index],
|
||||||
|
client, key) :
|
||||||
|
value;
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var Response = Class({
|
||||||
|
extends: Type,
|
||||||
|
constructor: function(template={}) {
|
||||||
|
this.template = template;
|
||||||
|
var [x] = findPlaceholders(template, Return);
|
||||||
|
var {placeholder, path} = x;
|
||||||
|
this.return = placeholder;
|
||||||
|
this.path = path;
|
||||||
|
},
|
||||||
|
read: function(packet, client) {
|
||||||
|
var value = query(packet, this.path);
|
||||||
|
return this.return.read(value, client);
|
||||||
|
},
|
||||||
|
write: function(input, client) {
|
||||||
|
return JSON.parse(JSON.stringify(this.template, (key, value) => {
|
||||||
|
return value instanceof Return ? value.write(input) :
|
||||||
|
input
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Returns array of values for the given object.
|
||||||
|
var values = object => Object.keys(object).map(key => object[key]);
|
||||||
|
// Returns [key, value] pairs for the given object.
|
||||||
|
var pairs = object => Object.keys(object).map(key => [key, object[key]]);
|
||||||
|
// Queries an object for the field nested with in it.
|
||||||
|
var query = (object, path) => path.reduce((object, entry) => object && object[entry],
|
||||||
|
object);
|
||||||
|
|
||||||
|
|
||||||
|
var Root = Client.from({
|
||||||
|
"category": "actor",
|
||||||
|
"typeName": "root",
|
||||||
|
"methods": [
|
||||||
|
{
|
||||||
|
"name": "echo",
|
||||||
|
"request": {
|
||||||
|
"string": { "_arg": 0, "type": "string" }
|
||||||
|
},
|
||||||
|
"response": {
|
||||||
|
"string": { "_retval": "string" }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "listTabs",
|
||||||
|
"request": {},
|
||||||
|
"response": { "_retval": "tablist" }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "actorDescriptions",
|
||||||
|
"request": {},
|
||||||
|
"response": { "_retval": "json" }
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"events": {
|
||||||
|
"tabListChanged": {}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var Tab = Client.from({
|
||||||
|
"category": "dict",
|
||||||
|
"typeName": "tab",
|
||||||
|
"specifications": {
|
||||||
|
"title": "string",
|
||||||
|
"url": "string",
|
||||||
|
"outerWindowID": "number",
|
||||||
|
"console": "console",
|
||||||
|
"inspectorActor": "inspector",
|
||||||
|
"callWatcherActor": "call-watcher",
|
||||||
|
"canvasActor": "canvas",
|
||||||
|
"webglActor": "webgl",
|
||||||
|
"webaudioActor": "webaudio",
|
||||||
|
"styleSheetsActor": "stylesheets",
|
||||||
|
"styleEditorActor": "styleeditor",
|
||||||
|
"storageActor": "storage",
|
||||||
|
"gcliActor": "gcli",
|
||||||
|
"memoryActor": "memory",
|
||||||
|
"eventLoopLag": "eventLoopLag"
|
||||||
|
|
||||||
|
"trace": "trace", // missing
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var tablist = Client.from({
|
||||||
|
"category": "dict",
|
||||||
|
"typeName": "tablist",
|
||||||
|
"specializations": {
|
||||||
|
"selected": "number",
|
||||||
|
"tabs": "array:tab"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
})(this);
|
||||||
|
|
50
addon-sdk/source/examples/debug-client/data/index.html
Normal file
50
addon-sdk/source/examples/debug-client/data/index.html
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
<!-- 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/. -->
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<script src="resource://sdk/dev/volcan.js"></script>
|
||||||
|
<script src="./task.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
</body>
|
||||||
|
<script>
|
||||||
|
const wait = (target, type, capture) => new Promise((resolve, reject) => {
|
||||||
|
const listener = event => {
|
||||||
|
target.removeEventListener(type, listener, capture);
|
||||||
|
resolve(event);
|
||||||
|
};
|
||||||
|
target.addEventListener(type, listener, capture);
|
||||||
|
});
|
||||||
|
|
||||||
|
const display = message =>
|
||||||
|
document.body.innerHTML += message + "<br/>";
|
||||||
|
|
||||||
|
Task.spawn(function*() {
|
||||||
|
var event = yield wait(window, "message");
|
||||||
|
var port = event.ports[0];
|
||||||
|
|
||||||
|
display("Port received");
|
||||||
|
var root = yield volcan.connect(port);
|
||||||
|
|
||||||
|
display("Connected to a debugger");
|
||||||
|
|
||||||
|
var message = yield root.echo("hello")
|
||||||
|
|
||||||
|
display("Received echo for: " + message);
|
||||||
|
|
||||||
|
var list = yield root.listTabs();
|
||||||
|
|
||||||
|
display("You have " + list.tabs.length + " open tabs");
|
||||||
|
|
||||||
|
var activeTab = list.tabs[list.selected];
|
||||||
|
|
||||||
|
display("Your active tab url is: " + activeTab.url);
|
||||||
|
|
||||||
|
var sheets = yield activeTab.styleSheetsActor.getStyleSheets();
|
||||||
|
|
||||||
|
display("Page in active tab has " + sheets.length + " stylesheets");
|
||||||
|
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</html>
|
BIN
addon-sdk/source/examples/debug-client/data/plugin.png
Normal file
BIN
addon-sdk/source/examples/debug-client/data/plugin.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.7 KiB |
28
addon-sdk/source/examples/debug-client/data/task.js
Normal file
28
addon-sdk/source/examples/debug-client/data/task.js
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
(function(exports) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
const spawn = (task, ...args) => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
try {
|
||||||
|
const routine = task(...args);
|
||||||
|
const raise = error => routine.throw(error);
|
||||||
|
const step = data => {
|
||||||
|
const { done, value } = routine.next(data);
|
||||||
|
if (done)
|
||||||
|
resolve(value);
|
||||||
|
else
|
||||||
|
Promise.resolve(value).then(step, raise);
|
||||||
|
}
|
||||||
|
step();
|
||||||
|
} catch(error) {
|
||||||
|
reject(error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
exports.spawn = spawn;
|
||||||
|
|
||||||
|
})(Task = {});
|
33
addon-sdk/source/examples/debug-client/index.js
Normal file
33
addon-sdk/source/examples/debug-client/index.js
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
/* 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/. */
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
const { Panel } = require("dev/panel");
|
||||||
|
const { Tool } = require("dev/toolbox");
|
||||||
|
const { Class } = require("sdk/core/heritage");
|
||||||
|
|
||||||
|
|
||||||
|
const LadybugPanel = Class({
|
||||||
|
extends: Panel,
|
||||||
|
label: "Ladybug",
|
||||||
|
tooltip: "Debug client example",
|
||||||
|
icon: "./plugin.png",
|
||||||
|
url: "./index.html",
|
||||||
|
setup: function({debuggee}) {
|
||||||
|
this.debuggee = debuggee;
|
||||||
|
},
|
||||||
|
dispose: function() {
|
||||||
|
delete this.debuggee;
|
||||||
|
},
|
||||||
|
onReady: function() {
|
||||||
|
this.debuggee.start();
|
||||||
|
this.postMessage("RDP", [this.debuggee]);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
exports.LadybugPanel = LadybugPanel;
|
||||||
|
|
||||||
|
|
||||||
|
const ladybug = new Tool({
|
||||||
|
panels: { ladybug: LadybugPanel }
|
||||||
|
});
|
10
addon-sdk/source/examples/debug-client/package.json
Normal file
10
addon-sdk/source/examples/debug-client/package.json
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"name": "debug-client",
|
||||||
|
"id": "@debug-client",
|
||||||
|
"title": "Debug client",
|
||||||
|
"description": "Example debug client",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"author": "Irakli Gozalishvili",
|
||||||
|
"main": "./index.js",
|
||||||
|
"license": "MPL 2.0"
|
||||||
|
}
|
95
addon-sdk/source/lib/dev/debuggee.js
Normal file
95
addon-sdk/source/lib/dev/debuggee.js
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
module.metadata = {
|
||||||
|
"stability": "experimental"
|
||||||
|
};
|
||||||
|
|
||||||
|
const { Cu } = require("chrome");
|
||||||
|
const { Class } = require("../sdk/core/heritage");
|
||||||
|
const { MessagePort, MessageChannel } = require("../sdk/messaging");
|
||||||
|
const { DebuggerServer } = Cu.import("resource://gre/modules/devtools/dbg-server.jsm", {});
|
||||||
|
|
||||||
|
const outputs = new WeakMap();
|
||||||
|
const inputs = new WeakMap();
|
||||||
|
const targets = new WeakMap();
|
||||||
|
const transports = new WeakMap();
|
||||||
|
|
||||||
|
const inputFor = port => inputs.get(port);
|
||||||
|
const outputFor = port => outputs.get(port);
|
||||||
|
const transportFor = port => transports.get(port);
|
||||||
|
|
||||||
|
|
||||||
|
const fromTarget = target => {
|
||||||
|
const debuggee = new Debuggee();
|
||||||
|
const { port1, port2 } = new MessageChannel();
|
||||||
|
inputs.set(debuggee, port1);
|
||||||
|
outputs.set(debuggee, port2);
|
||||||
|
targets.set(debuggee, target);
|
||||||
|
|
||||||
|
return debuggee;
|
||||||
|
};
|
||||||
|
exports.fromTarget = fromTarget;
|
||||||
|
|
||||||
|
const Debuggee = Class({
|
||||||
|
extends: MessagePort.prototype,
|
||||||
|
close: function() {
|
||||||
|
const server = transportFor(this);
|
||||||
|
if (server) {
|
||||||
|
transports.delete(this);
|
||||||
|
server.close();
|
||||||
|
}
|
||||||
|
outputFor(this).close();
|
||||||
|
},
|
||||||
|
start: function() {
|
||||||
|
const target = targets.get(this);
|
||||||
|
if (target.isLocalTab) {
|
||||||
|
// Since a remote protocol connection will be made, let's start the
|
||||||
|
// DebuggerServer here, once and for all tools.
|
||||||
|
if (!DebuggerServer.initialized) {
|
||||||
|
DebuggerServer.init();
|
||||||
|
DebuggerServer.addBrowserActors();
|
||||||
|
}
|
||||||
|
|
||||||
|
transports.set(this, DebuggerServer.connectPipe());
|
||||||
|
}
|
||||||
|
// TODO: Implement support for remote connections (See Bug 980421)
|
||||||
|
else {
|
||||||
|
throw Error("Remote targets are not yet supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
// pipe messages send to the debuggee to an actual
|
||||||
|
// server via remote debugging protocol transport.
|
||||||
|
inputFor(this).addEventListener("message", ({data}) =>
|
||||||
|
transportFor(this).send(data));
|
||||||
|
|
||||||
|
// pipe messages received from the remote debugging
|
||||||
|
// server transport onto the this debuggee.
|
||||||
|
transportFor(this).hooks = {
|
||||||
|
onPacket: packet => inputFor(this).postMessage(packet),
|
||||||
|
onClosed: () => inputFor(this).close()
|
||||||
|
};
|
||||||
|
|
||||||
|
inputFor(this).start();
|
||||||
|
outputFor(this).start();
|
||||||
|
},
|
||||||
|
postMessage: function(data) {
|
||||||
|
return outputFor(this).postMessage(data);
|
||||||
|
},
|
||||||
|
get onmessage() {
|
||||||
|
return outputFor(this).onmessage;
|
||||||
|
},
|
||||||
|
set onmessage(onmessage) {
|
||||||
|
outputFor(this).onmessage = onmessage;
|
||||||
|
},
|
||||||
|
addEventListener: function(...args) {
|
||||||
|
return outputFor(this).addEventListener(...args);
|
||||||
|
},
|
||||||
|
removeEventListener: function(...args) {
|
||||||
|
return outputFor(this).removeEventListener(...args);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
exports.Debuggee = Debuggee;
|
115
addon-sdk/source/lib/dev/frame-script.js
Normal file
115
addon-sdk/source/lib/dev/frame-script.js
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
(function({content, sendSyncMessage, addMessageListener, sendAsyncMessage}) {
|
||||||
|
|
||||||
|
const Cc = Components.classes;
|
||||||
|
const Ci = Components.interfaces;
|
||||||
|
const observerService = Cc["@mozilla.org/observer-service;1"]
|
||||||
|
.getService(Ci.nsIObserverService);
|
||||||
|
|
||||||
|
const channels = new Map();
|
||||||
|
const handles = new WeakMap();
|
||||||
|
|
||||||
|
// Takes remote port handle and creates a local one.
|
||||||
|
// also set's up a messaging channel between them.
|
||||||
|
// This is temporary workaround until Bug 914974 is fixed
|
||||||
|
// and port can be transfered through message manager.
|
||||||
|
const demarshal = (handle) => {
|
||||||
|
if (handle.type === "MessagePort") {
|
||||||
|
if (!channels.has(handle.id)) {
|
||||||
|
const channel = new content.MessageChannel();
|
||||||
|
channels.set(handle.id, channel);
|
||||||
|
handles.set(channel.port1, handle);
|
||||||
|
channel.port1.onmessage = onOutPort;
|
||||||
|
}
|
||||||
|
return channels.get(handle.id).port2;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const onOutPort = event => {
|
||||||
|
const handle = handles.get(event.target);
|
||||||
|
sendAsyncMessage("sdk/port/message", {
|
||||||
|
port: handle,
|
||||||
|
message: event.data
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const onInPort = ({data}) => {
|
||||||
|
const channel = channels.get(data.port.id);
|
||||||
|
if (channel)
|
||||||
|
channel.port1.postMessage(data.message);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onOutEvent = event =>
|
||||||
|
sendSyncMessage("sdk/event/" + event.type,
|
||||||
|
{ type: event.type,
|
||||||
|
data: event.data });
|
||||||
|
|
||||||
|
const onInMessage = (message) => {
|
||||||
|
const {type, data, origin, bubbles, cancelable, ports} = message.data;
|
||||||
|
|
||||||
|
const event = new content.MessageEvent(type, {
|
||||||
|
bubbles: bubbles,
|
||||||
|
cancelable: cancelable,
|
||||||
|
data: data,
|
||||||
|
origin: origin,
|
||||||
|
target: content,
|
||||||
|
source: content,
|
||||||
|
ports: ports.map(demarshal)
|
||||||
|
});
|
||||||
|
content.dispatchEvent(event);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onReady = event => {
|
||||||
|
channels.clear();
|
||||||
|
};
|
||||||
|
|
||||||
|
addMessageListener("sdk/event/message", onInMessage);
|
||||||
|
addMessageListener("sdk/port/message", onInPort);
|
||||||
|
|
||||||
|
const observer = {
|
||||||
|
observe: (document, topic, data) => {
|
||||||
|
// When frame associated with message manager is removed from document `docShell`
|
||||||
|
// is set to `null` but observer is still kept alive. At this point accesing
|
||||||
|
// `content.document` throws "can't access dead object" exceptions. In order to
|
||||||
|
// avoid leaking observer and logged errors observer is going to be removed when
|
||||||
|
// `docShell` is set to `null`.
|
||||||
|
if (!docShell) {
|
||||||
|
observerService.removeObserver(observer, topic);
|
||||||
|
}
|
||||||
|
else if (document === content.document) {
|
||||||
|
if (topic === "content-document-interactive") {
|
||||||
|
sendAsyncMessage("sdk/event/ready", {
|
||||||
|
type: "ready",
|
||||||
|
readyState: document.readyState,
|
||||||
|
uri: document.documentURI
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (topic === "content-document-loaded") {
|
||||||
|
sendAsyncMessage("sdk/event/load", {
|
||||||
|
type: "load",
|
||||||
|
readyState: document.readyState,
|
||||||
|
uri: document.documentURI
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (topic === "content-page-hidden") {
|
||||||
|
channels.clear();
|
||||||
|
sendAsyncMessage("sdk/event/unload", {
|
||||||
|
type: "unload",
|
||||||
|
readyState: "uninitialized",
|
||||||
|
uri: document.documentURI
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
observerService.addObserver(observer, "content-document-interactive", false);
|
||||||
|
observerService.addObserver(observer, "content-document-loaded", false);
|
||||||
|
observerService.addObserver(observer, "content-page-hidden", false);
|
||||||
|
|
||||||
|
})(this);
|
223
addon-sdk/source/lib/dev/panel.js
Normal file
223
addon-sdk/source/lib/dev/panel.js
Normal file
@ -0,0 +1,223 @@
|
|||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
module.metadata = {
|
||||||
|
"stability": "experimental"
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const { Cu } = require("chrome");
|
||||||
|
const { Class } = require("../sdk/core/heritage");
|
||||||
|
const { curry } = require("../sdk/lang/functional");
|
||||||
|
const { EventTarget } = require("../sdk/event/target");
|
||||||
|
const { Disposable, setup, dispose } = require("../sdk/core/disposable");
|
||||||
|
const { emit, off, setListeners } = require("../sdk/event/core");
|
||||||
|
const { when } = require("../sdk/event/utils");
|
||||||
|
const { getFrameElement } = require("../sdk/window/utils");
|
||||||
|
const { contract, validate } = require("../sdk/util/contract");
|
||||||
|
const { data: { url: resolve }} = require("../sdk/self");
|
||||||
|
const { identify } = require("../sdk/ui/id");
|
||||||
|
const { isLocalURL, URL } = require("../sdk/url");
|
||||||
|
const { defer } = require("../sdk/core/promise");
|
||||||
|
const { encode } = require("../sdk/base64");
|
||||||
|
const { marshal, demarshal } = require("./ports");
|
||||||
|
const { fromTarget } = require("./debuggee");
|
||||||
|
const { removed } = require("../sdk/dom/events");
|
||||||
|
const { id: addonID } = require("../sdk/self");
|
||||||
|
|
||||||
|
const OUTER_FRAME_URI = module.uri.replace(/\.js$/, ".html");
|
||||||
|
const FRAME_SCRIPT = module.uri.replace("/panel.js", "/frame-script.js");
|
||||||
|
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
||||||
|
const HTML_NS = "http://www.w3.org/1999/xhtml";
|
||||||
|
|
||||||
|
const makeID = name =>
|
||||||
|
("dev-panel-" + addonID + "-" + name).
|
||||||
|
split("/").join("-").
|
||||||
|
split(".").join("-").
|
||||||
|
split(" ").join("-").
|
||||||
|
replace(/[^A-Za-z0-9_\-]/g, "");
|
||||||
|
|
||||||
|
|
||||||
|
// Weak mapping between `Panel` instances and their frame's
|
||||||
|
// `nsIMessageManager`.
|
||||||
|
const managers = new WeakMap();
|
||||||
|
// Return `nsIMessageManager` for the given `Panel` instance.
|
||||||
|
const managerFor = x => managers.get(x);
|
||||||
|
|
||||||
|
// Weak mappinging between iframe's and their owner
|
||||||
|
// `Panel` instances.
|
||||||
|
const panels = new WeakMap();
|
||||||
|
const panelFor = frame => panels.get(frame);
|
||||||
|
|
||||||
|
// Weak mapping between panels and debugees they're targeting.
|
||||||
|
const debuggees = new WeakMap();
|
||||||
|
const debuggeeFor = panel => debuggees.get(panel);
|
||||||
|
|
||||||
|
const setAttributes = (node, attributes) => {
|
||||||
|
for (var key in attributes)
|
||||||
|
node.setAttribute(key, attributes[key]);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onStateChange = ({target, data}) => {
|
||||||
|
const panel = panelFor(target);
|
||||||
|
panel.readyState = data.readyState;
|
||||||
|
emit(panel, data.type, { target: panel, type: data.type });
|
||||||
|
};
|
||||||
|
|
||||||
|
// port event listener on the message manager that demarshalls
|
||||||
|
// and forwards to the actual receiver. This is a workaround
|
||||||
|
// until Bug 914974 is fixed.
|
||||||
|
const onPortMessage = ({data, target}) => {
|
||||||
|
const port = demarshal(target, data.port);
|
||||||
|
if (port)
|
||||||
|
port.postMessage(data.message);
|
||||||
|
};
|
||||||
|
|
||||||
|
// When frame is removed from the toolbox destroy panel
|
||||||
|
// associated with it to release all the resources.
|
||||||
|
const onFrameRemove = frame => {
|
||||||
|
panelFor(frame).destroy();
|
||||||
|
};
|
||||||
|
|
||||||
|
const onFrameInited = frame => {
|
||||||
|
frame.style.visibility = "visible";
|
||||||
|
}
|
||||||
|
|
||||||
|
const inited = frame => new Promise(resolve => {
|
||||||
|
const { messageManager } = frame.frameLoader;
|
||||||
|
const listener = message => {
|
||||||
|
messageManager.removeMessageListener("sdk/event/ready", listener);
|
||||||
|
resolve(frame);
|
||||||
|
};
|
||||||
|
messageManager.addMessageListener("sdk/event/ready", listener);
|
||||||
|
});
|
||||||
|
|
||||||
|
const getTarget = ({target}) => target;
|
||||||
|
|
||||||
|
const Panel = Class({
|
||||||
|
extends: Disposable,
|
||||||
|
implements: [EventTarget],
|
||||||
|
get id() {
|
||||||
|
return makeID(this.name || this.label);
|
||||||
|
},
|
||||||
|
readyState: "uninitialized",
|
||||||
|
ready: function() {
|
||||||
|
const { readyState } = this;
|
||||||
|
const isReady = readyState === "complete" ||
|
||||||
|
readyState === "interactive";
|
||||||
|
return isReady ? Promise.resolve(this) :
|
||||||
|
when(this, "ready").then(getTarget);
|
||||||
|
},
|
||||||
|
loaded: function() {
|
||||||
|
const { readyState } = this;
|
||||||
|
const isLoaded = readyState === "complete";
|
||||||
|
return isLoaded ? Promise.resolve(this) :
|
||||||
|
when(this, "load").then(getTarget);
|
||||||
|
},
|
||||||
|
unloaded: function() {
|
||||||
|
const { readyState } = this;
|
||||||
|
const isUninitialized = readyState === "uninitialized";
|
||||||
|
return isUninitialized ? Promise.resolve(this) :
|
||||||
|
when(this, "unload").then(getTarget);
|
||||||
|
},
|
||||||
|
postMessage: function(data, ports) {
|
||||||
|
const manager = managerFor(this);
|
||||||
|
manager.sendAsyncMessage("sdk/event/message", {
|
||||||
|
type: "message",
|
||||||
|
bubbles: false,
|
||||||
|
cancelable: false,
|
||||||
|
data: data,
|
||||||
|
origin: this.url,
|
||||||
|
ports: ports.map(marshal(manager))
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
exports.Panel = Panel;
|
||||||
|
|
||||||
|
validate.define(Panel, contract({
|
||||||
|
label: {
|
||||||
|
is: ["string"],
|
||||||
|
msg: "The `option.label` must be a provided"
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
is: ["string", "undefined"],
|
||||||
|
msg: "The `option.tooltip` must be a string"
|
||||||
|
},
|
||||||
|
icon: {
|
||||||
|
is: ["string"],
|
||||||
|
map: x => x && resolve(x),
|
||||||
|
ok: x => isLocalURL(x),
|
||||||
|
msg: "The `options.icon` must be a valid local URI."
|
||||||
|
},
|
||||||
|
url: {
|
||||||
|
map: x => resolve(x.toString()),
|
||||||
|
is: ["string"],
|
||||||
|
ok: x => isLocalURL(x),
|
||||||
|
msg: "The `options.url` must be a valid local URI."
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
setup.define(Panel, (panel, {window, toolbox, url}) => {
|
||||||
|
// Hack: Given that iframe created by devtools API is no good for us,
|
||||||
|
// we obtain original iframe and replace it with the one that has
|
||||||
|
// desired configuration.
|
||||||
|
const original = getFrameElement(window);
|
||||||
|
const frame = original.cloneNode(true);
|
||||||
|
|
||||||
|
setAttributes(frame, {
|
||||||
|
"src": url,
|
||||||
|
"sandbox": "allow-scripts",
|
||||||
|
// It would be great if we could allow remote iframes for sandboxing
|
||||||
|
// panel documents in a content process, but for now platform implementation
|
||||||
|
// is buggy on linux so this is disabled.
|
||||||
|
// "remote": true,
|
||||||
|
"type": "content",
|
||||||
|
"transparent": true,
|
||||||
|
"seamless": "seamless"
|
||||||
|
});
|
||||||
|
|
||||||
|
original.parentNode.replaceChild(frame, original);
|
||||||
|
frame.style.visibility = "hidden";
|
||||||
|
|
||||||
|
// associate panel model with a frame view.
|
||||||
|
panels.set(frame, panel);
|
||||||
|
|
||||||
|
const debuggee = fromTarget(toolbox.target);
|
||||||
|
// associate debuggee with a panel.
|
||||||
|
debuggees.set(panel, debuggee);
|
||||||
|
|
||||||
|
|
||||||
|
// Setup listeners for the frame message manager.
|
||||||
|
const { messageManager } = frame.frameLoader;
|
||||||
|
messageManager.addMessageListener("sdk/event/ready", onStateChange);
|
||||||
|
messageManager.addMessageListener("sdk/event/load", onStateChange);
|
||||||
|
messageManager.addMessageListener("sdk/event/unload", onStateChange);
|
||||||
|
messageManager.addMessageListener("sdk/port/message", onPortMessage);
|
||||||
|
messageManager.loadFrameScript(FRAME_SCRIPT, false);
|
||||||
|
|
||||||
|
managers.set(panel, messageManager);
|
||||||
|
|
||||||
|
// destroy panel if frame is removed.
|
||||||
|
removed(frame).then(onFrameRemove);
|
||||||
|
// show frame when it is initialized.
|
||||||
|
inited(frame).then(onFrameInited);
|
||||||
|
|
||||||
|
|
||||||
|
// set listeners if there are ones defined on the prototype.
|
||||||
|
setListeners(panel, Object.getPrototypeOf(panel));
|
||||||
|
|
||||||
|
|
||||||
|
panel.setup({ debuggee: debuggee });
|
||||||
|
});
|
||||||
|
|
||||||
|
dispose.define(Panel, function(panel) {
|
||||||
|
debuggeeFor(panel).close();
|
||||||
|
|
||||||
|
debuggees.delete(panel);
|
||||||
|
managers.delete(panel);
|
||||||
|
panel.readyState = "destroyed";
|
||||||
|
panel.dispose();
|
||||||
|
});
|
64
addon-sdk/source/lib/dev/ports.js
Normal file
64
addon-sdk/source/lib/dev/ports.js
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
module.metadata = {
|
||||||
|
"stability": "experimental"
|
||||||
|
};
|
||||||
|
|
||||||
|
// This module provides `marshal` and `demarshal` functions
|
||||||
|
// that can be used to send MessagePort's over `nsIFrameMessageManager`
|
||||||
|
// until Bug 914974 is fixed.
|
||||||
|
|
||||||
|
const { add, iterator } = require("../sdk/lang/weak-set");
|
||||||
|
const { curry } = require("../sdk/lang/functional");
|
||||||
|
|
||||||
|
let id = 0;
|
||||||
|
const ports = new WeakMap();
|
||||||
|
|
||||||
|
// Takes `nsIFrameMessageManager` and `MessagePort` instances
|
||||||
|
// and returns a handle representing given `port`. Messages
|
||||||
|
// received on given `port` will be forwarded to a message
|
||||||
|
// manager under `sdk/port/message` and messages like:
|
||||||
|
// { port: { type: "MessagePort", id: 2}, data: data }
|
||||||
|
// Where id is an identifier associated with a given `port`
|
||||||
|
// and `data` is an `event.data` received on port.
|
||||||
|
const marshal = curry((manager, port) => {
|
||||||
|
if (!ports.has(port)) {
|
||||||
|
id = id + 1;
|
||||||
|
const handle = {type: "MessagePort", id: id};
|
||||||
|
// Bind id to the given port
|
||||||
|
ports.set(port, handle);
|
||||||
|
|
||||||
|
// Obtain a weak reference to a port.
|
||||||
|
add(exports, port);
|
||||||
|
|
||||||
|
port.onmessage = event => {
|
||||||
|
manager.sendAsyncMessage("sdk/port/message", {
|
||||||
|
port: handle,
|
||||||
|
message: event.data
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
return ports.get(port);
|
||||||
|
});
|
||||||
|
exports.marshal = marshal;
|
||||||
|
|
||||||
|
// Takes `nsIFrameMessageManager` instance and a handle returned
|
||||||
|
// `marshal(manager, port)` returning a `port` that was passed
|
||||||
|
// to it. Note that `port` may be GC-ed in which case returned
|
||||||
|
// value will be `null`.
|
||||||
|
const demarshal = curry((manager, {type, id}) => {
|
||||||
|
if (type === "MessagePort") {
|
||||||
|
for (let port of iterator(exports)) {
|
||||||
|
if (id === ports.get(port).id)
|
||||||
|
return port;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
exports.demarshal = demarshal;
|
75
addon-sdk/source/lib/dev/toolbox.js
Normal file
75
addon-sdk/source/lib/dev/toolbox.js
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
module.metadata = {
|
||||||
|
"stability": "experimental"
|
||||||
|
};
|
||||||
|
|
||||||
|
const { Cu, Cc, Ci } = require("chrome");
|
||||||
|
const { Class } = require("../sdk/core/heritage");
|
||||||
|
const { Disposable, setup } = require("../sdk/core/disposable");
|
||||||
|
const { contract, validate } = require("../sdk/util/contract");
|
||||||
|
const { each, pairs, values } = require("../sdk/util/sequence");
|
||||||
|
|
||||||
|
const { gDevTools } = Cu.import("resource:///modules/devtools/gDevTools.jsm", {});
|
||||||
|
|
||||||
|
// This is temporary workaround to allow loading of the developer tools client - volcan
|
||||||
|
// into a toolbox panel, this hack won't be necessary as soon as devtools patch will be
|
||||||
|
// shipped in nightly, after which it can be removed. Bug 1038517
|
||||||
|
const registerSDKURI = () => {
|
||||||
|
const ioService = Cc['@mozilla.org/network/io-service;1']
|
||||||
|
.getService(Ci.nsIIOService);
|
||||||
|
const resourceHandler = ioService.getProtocolHandler("resource")
|
||||||
|
.QueryInterface(Ci.nsIResProtocolHandler);
|
||||||
|
|
||||||
|
const uri = module.uri.replace("dev/toolbox.js", "");
|
||||||
|
resourceHandler.setSubstitution("sdk", ioService.newURI(uri, null, null));
|
||||||
|
};
|
||||||
|
|
||||||
|
registerSDKURI();
|
||||||
|
|
||||||
|
|
||||||
|
const Tool = Class({
|
||||||
|
extends: Disposable,
|
||||||
|
setup: function(params={}) {
|
||||||
|
const { panels } = validate(this, params);
|
||||||
|
|
||||||
|
this.panels = panels;
|
||||||
|
|
||||||
|
each(([key, Panel]) => {
|
||||||
|
const { url, label, tooltip, icon } = validate(Panel.prototype);
|
||||||
|
const { id } = Panel.prototype;
|
||||||
|
|
||||||
|
gDevTools.registerTool({
|
||||||
|
id: id,
|
||||||
|
url: "about:blank",
|
||||||
|
label: label,
|
||||||
|
tooltip: tooltip,
|
||||||
|
icon: icon,
|
||||||
|
isTargetSupported: target => target.isLocalTab,
|
||||||
|
build: (window, toolbox) => {
|
||||||
|
const panel = new Panel();
|
||||||
|
setup(panel, { window: window,
|
||||||
|
toolbox: toolbox,
|
||||||
|
url: url });
|
||||||
|
|
||||||
|
return panel.ready();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, pairs(panels));
|
||||||
|
},
|
||||||
|
dispose: function() {
|
||||||
|
each(Panel => gDevTools.unregisterTool(Panel.prototype.id),
|
||||||
|
values(this.panels));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
validate.define(Tool, contract({
|
||||||
|
panels: {
|
||||||
|
is: ["object", "undefined"]
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
exports.Tool = Tool;
|
38
addon-sdk/source/lib/dev/utils.js
Normal file
38
addon-sdk/source/lib/dev/utils.js
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
const { Cu } = require("chrome");
|
||||||
|
const { gDevTools } = Cu.import("resource:///modules/devtools/gDevTools.jsm", {});
|
||||||
|
const { devtools } = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
|
||||||
|
|
||||||
|
const { getActiveTab } = require("../sdk/tabs/utils");
|
||||||
|
const { getMostRecentBrowserWindow } = require("../sdk/window/utils");
|
||||||
|
|
||||||
|
const targetFor = target => {
|
||||||
|
target = target || getActiveTab(getMostRecentBrowserWindow());
|
||||||
|
return devtools.TargetFactory.forTab(target);
|
||||||
|
};
|
||||||
|
|
||||||
|
const getCurrentPanel = toolbox => toolbox.getCurrentPanel();
|
||||||
|
exports.getCurrentPanel = getCurrentPanel;
|
||||||
|
|
||||||
|
const openToolbox = (id, tab) => {
|
||||||
|
id = id.prototype.id || id.id || id;
|
||||||
|
return gDevTools.showToolbox(targetFor(tab), id);
|
||||||
|
};
|
||||||
|
exports.openToolbox = openToolbox;
|
||||||
|
|
||||||
|
const closeToolbox = tab => gDevTools.closeToolbox(targetFor(tab));
|
||||||
|
exports.closeToolbox = closeToolbox;
|
||||||
|
|
||||||
|
const getToolbox = tab => gDevTools.getToolbox(targetFor(tab));
|
||||||
|
exports.getToolbox = getToolbox;
|
||||||
|
|
||||||
|
const openToolboxPanel = (id, tab) => {
|
||||||
|
id = id.prototype.id || id.id || id;
|
||||||
|
return gDevTools.showToolbox(targetFor(tab), id).then(getCurrentPanel);
|
||||||
|
};
|
||||||
|
exports.openToolboxPanel = openToolboxPanel;
|
3760
addon-sdk/source/lib/dev/volcan.js
Normal file
3760
addon-sdk/source/lib/dev/volcan.js
Normal file
File diff suppressed because one or more lines are too long
@ -7,6 +7,7 @@ module.metadata = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const { Cc, Ci } = require('chrome');
|
const { Cc, Ci } = require('chrome');
|
||||||
|
const { isNative } = require('@loader/options');
|
||||||
const { descriptor, Sandbox, evaluate, main, resolveURI } = require('toolkit/loader');
|
const { descriptor, Sandbox, evaluate, main, resolveURI } = require('toolkit/loader');
|
||||||
const { once } = require('../system/events');
|
const { once } = require('../system/events');
|
||||||
const { exit, env, staticArgs } = require('../system');
|
const { exit, env, staticArgs } = require('../system');
|
||||||
@ -104,7 +105,8 @@ function startup(reason, options) {
|
|||||||
require('../l10n/loader').
|
require('../l10n/loader').
|
||||||
load(rootURI).
|
load(rootURI).
|
||||||
then(null, function failure(error) {
|
then(null, function failure(error) {
|
||||||
console.info("Error while loading localization: " + error.message);
|
if (!isNative)
|
||||||
|
console.info("Error while loading localization: " + error.message);
|
||||||
}).
|
}).
|
||||||
then(function onLocalizationReady(data) {
|
then(function onLocalizationReady(data) {
|
||||||
// Exports data to a pseudo module so that api-utils/l10n/core
|
// Exports data to a pseudo module so that api-utils/l10n/core
|
||||||
|
@ -9,81 +9,50 @@ module.metadata = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const { EventEmitter } = require('../deprecated/events');
|
const { EventEmitter } = require('../deprecated/events');
|
||||||
const { validateOptions } = require('../deprecated/api-utils');
|
const { isValidURI, isLocalURL, URL } = require('../url');
|
||||||
const { isValidURI, URL } = require('../url');
|
|
||||||
const file = require('../io/file');
|
const file = require('../io/file');
|
||||||
const { contract } = require('../util/contract');
|
const { contract } = require('../util/contract');
|
||||||
const { isString, instanceOf } = require('../lang/type');
|
const { isString, isNil, instanceOf } = require('../lang/type');
|
||||||
|
const { validateOptions,
|
||||||
|
string, array, object, either, required } = require('../deprecated/api-utils');
|
||||||
|
|
||||||
const LOCAL_URI_SCHEMES = ['resource', 'data'];
|
const isJSONable = (value) => {
|
||||||
|
try {
|
||||||
|
JSON.parse(JSON.stringify(value));
|
||||||
|
} catch (e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
// Returns `null` if `value` is `null` or `undefined`, otherwise `value`.
|
const isValidScriptFile = (value) =>
|
||||||
function ensureNull(value) value == null ? null : value
|
(isString(value) || instanceOf(value, URL)) && isLocalURL(value);
|
||||||
|
|
||||||
// map of property validations
|
// map of property validations
|
||||||
const valid = {
|
const valid = {
|
||||||
contentURL: {
|
contentURL: {
|
||||||
map: function(url) !url ? ensureNull(url) : url.toString(),
|
is: either(string, object),
|
||||||
is: ['undefined', 'null', 'string'],
|
ok: url => isNil(url) || isLocalURL(url) || isValidURI(url),
|
||||||
ok: function (url) {
|
|
||||||
if (url === null)
|
|
||||||
return true;
|
|
||||||
return isValidURI(url);
|
|
||||||
},
|
|
||||||
msg: 'The `contentURL` option must be a valid URL.'
|
msg: 'The `contentURL` option must be a valid URL.'
|
||||||
},
|
},
|
||||||
contentScriptFile: {
|
contentScriptFile: {
|
||||||
is: ['undefined', 'null', 'string', 'array', 'object'],
|
is: either(string, object, array),
|
||||||
map: ensureNull,
|
ok: value => isNil(value) || [].concat(value).every(isValidScriptFile),
|
||||||
ok: function(value) {
|
|
||||||
if (value === null)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
value = [].concat(value);
|
|
||||||
|
|
||||||
// Make sure every item is a string or an
|
|
||||||
// URL instance, and also a local file URL.
|
|
||||||
return value.every(function (item) {
|
|
||||||
|
|
||||||
if (!isString(item) && !(item instanceof URL))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
try {
|
|
||||||
return ~LOCAL_URI_SCHEMES.indexOf(URL(item).scheme);
|
|
||||||
}
|
|
||||||
catch(e) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
},
|
|
||||||
msg: 'The `contentScriptFile` option must be a local URL or an array of URLs.'
|
msg: 'The `contentScriptFile` option must be a local URL or an array of URLs.'
|
||||||
},
|
},
|
||||||
contentScript: {
|
contentScript: {
|
||||||
is: ['undefined', 'null', 'string', 'array'],
|
is: either(string, array),
|
||||||
map: ensureNull,
|
ok: value => isNil(value) || [].concat(value).every(isString),
|
||||||
ok: function(value) {
|
|
||||||
return !Array.isArray(value) || value.every(
|
|
||||||
function(item) { return typeof item === 'string' }
|
|
||||||
);
|
|
||||||
},
|
|
||||||
msg: 'The `contentScript` option must be a string or an array of strings.'
|
msg: 'The `contentScript` option must be a string or an array of strings.'
|
||||||
},
|
},
|
||||||
contentScriptWhen: {
|
contentScriptWhen: {
|
||||||
is: ['string'],
|
is: required(string),
|
||||||
ok: function(value) { return ~['start', 'ready', 'end'].indexOf(value) },
|
map: value => value || 'end',
|
||||||
map: function(value) {
|
ok: value => ~['start', 'ready', 'end'].indexOf(value),
|
||||||
return value || 'end';
|
|
||||||
},
|
|
||||||
msg: 'The `contentScriptWhen` option must be either "start", "ready" or "end".'
|
msg: 'The `contentScriptWhen` option must be either "start", "ready" or "end".'
|
||||||
},
|
},
|
||||||
contentScriptOptions: {
|
contentScriptOptions: {
|
||||||
ok: function(value) {
|
ok: value => isNil(value) || isJSONable(value),
|
||||||
if ( value === undefined ) { return true; }
|
|
||||||
try { JSON.parse( JSON.stringify( value ) ); } catch(e) { return false; }
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
map: function(value) 'undefined' === getTypeOf(value) ? null : value,
|
|
||||||
msg: 'The contentScriptOptions should be a jsonable value.'
|
msg: 'The contentScriptOptions should be a jsonable value.'
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -20,7 +20,7 @@ const { merge } = require('../util/object');
|
|||||||
const { getTabForContentWindow } = require('../tabs/utils');
|
const { getTabForContentWindow } = require('../tabs/utils');
|
||||||
const { getInnerId } = require('../window/utils');
|
const { getInnerId } = require('../window/utils');
|
||||||
const { PlainTextConsole } = require('../console/plain-text');
|
const { PlainTextConsole } = require('../console/plain-text');
|
||||||
|
const { data } = require('../self');
|
||||||
// WeakMap of sandboxes so we can access private values
|
// WeakMap of sandboxes so we can access private values
|
||||||
const sandboxes = new WeakMap();
|
const sandboxes = new WeakMap();
|
||||||
|
|
||||||
@ -247,9 +247,12 @@ const WorkerSandbox = Class({
|
|||||||
// The order of `contentScriptFile` and `contentScript` evaluation is
|
// The order of `contentScriptFile` and `contentScript` evaluation is
|
||||||
// intentional, so programs can load libraries like jQuery from script URLs
|
// intentional, so programs can load libraries like jQuery from script URLs
|
||||||
// and use them in scripts.
|
// and use them in scripts.
|
||||||
let contentScriptFile = ('contentScriptFile' in worker) ? worker.contentScriptFile
|
let contentScriptFile = ('contentScriptFile' in worker)
|
||||||
|
? worker.contentScriptFile
|
||||||
: null,
|
: null,
|
||||||
contentScript = ('contentScript' in worker) ? worker.contentScript : null;
|
contentScript = ('contentScript' in worker)
|
||||||
|
? worker.contentScript
|
||||||
|
: null;
|
||||||
|
|
||||||
if (contentScriptFile)
|
if (contentScriptFile)
|
||||||
importScripts.apply(null, [this].concat(contentScriptFile));
|
importScripts.apply(null, [this].concat(contentScriptFile));
|
||||||
@ -285,7 +288,8 @@ exports.WorkerSandbox = WorkerSandbox;
|
|||||||
function importScripts (workerSandbox, ...urls) {
|
function importScripts (workerSandbox, ...urls) {
|
||||||
let { worker, sandbox } = modelFor(workerSandbox);
|
let { worker, sandbox } = modelFor(workerSandbox);
|
||||||
for (let i in urls) {
|
for (let i in urls) {
|
||||||
let contentScriptFile = urls[i];
|
let contentScriptFile = data.url(urls[i]);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
let uri = URL(contentScriptFile);
|
let uri = URL(contentScriptFile);
|
||||||
if (uri.scheme === 'resource')
|
if (uri.scheme === 'resource')
|
||||||
|
@ -8,13 +8,14 @@ module.metadata = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let { merge } = require('../util/object');
|
let { merge } = require('../util/object');
|
||||||
let assetsURI = require('../self').data.url();
|
let { data } = require('../self');
|
||||||
|
let assetsURI = data.url();
|
||||||
let isArray = Array.isArray;
|
let isArray = Array.isArray;
|
||||||
let method = require('../../method/core');
|
let method = require('../../method/core');
|
||||||
|
|
||||||
function isAddonContent({ contentURL }) {
|
const isAddonContent = ({ contentURL }) =>
|
||||||
return typeof(contentURL) === 'string' && contentURL.indexOf(assetsURI) === 0;
|
contentURL && data.url(contentURL).startsWith(assetsURI);
|
||||||
}
|
|
||||||
exports.isAddonContent = isAddonContent;
|
exports.isAddonContent = isAddonContent;
|
||||||
|
|
||||||
function hasContentScript({ contentScript, contentScriptFile }) {
|
function hasContentScript({ contentScript, contentScriptFile }) {
|
||||||
|
@ -25,6 +25,7 @@ const { EventTarget } = require("./event/target");
|
|||||||
const { emit } = require('./event/core');
|
const { emit } = require('./event/core');
|
||||||
const { when } = require('./system/unload');
|
const { when } = require('./system/unload');
|
||||||
const selection = require('./selection');
|
const selection = require('./selection');
|
||||||
|
const { contract: loaderContract } = require('./content/loader');
|
||||||
|
|
||||||
// All user items we add have this class.
|
// All user items we add have this class.
|
||||||
const ITEM_CLASS = "addon-context-menu-item";
|
const ITEM_CLASS = "addon-context-menu-item";
|
||||||
@ -257,7 +258,7 @@ function populateCallbackNodeData(node) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
data.selectionText = selection.text;
|
data.selectionText = selection.text;
|
||||||
|
|
||||||
data.srcURL = node.src || null;
|
data.srcURL = node.src || null;
|
||||||
data.value = node.value || null;
|
data.value = node.value || null;
|
||||||
|
|
||||||
@ -265,7 +266,7 @@ function populateCallbackNodeData(node) {
|
|||||||
data.linkURL = node.href || null;
|
data.linkURL = node.href || null;
|
||||||
node = node.parentNode;
|
node = node.parentNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -298,30 +299,11 @@ let baseItemRules = {
|
|||||||
msg: "The 'context' option must be a Context object or an array of " +
|
msg: "The 'context' option must be a Context object or an array of " +
|
||||||
"Context objects."
|
"Context objects."
|
||||||
},
|
},
|
||||||
contentScript: {
|
|
||||||
is: ["string", "array", "undefined"],
|
|
||||||
ok: function (v) {
|
|
||||||
return !Array.isArray(v) ||
|
|
||||||
v.every(function (s) typeof(s) === "string");
|
|
||||||
}
|
|
||||||
},
|
|
||||||
contentScriptFile: {
|
|
||||||
is: ["string", "array", "undefined"],
|
|
||||||
ok: function (v) {
|
|
||||||
if (!v)
|
|
||||||
return true;
|
|
||||||
let arr = Array.isArray(v) ? v : [v];
|
|
||||||
return arr.every(function (s) {
|
|
||||||
return getTypeOf(s) === "string" &&
|
|
||||||
getScheme(s) === 'resource';
|
|
||||||
});
|
|
||||||
},
|
|
||||||
msg: "The 'contentScriptFile' option must be a local file URL or " +
|
|
||||||
"an array of local file URLs."
|
|
||||||
},
|
|
||||||
onMessage: {
|
onMessage: {
|
||||||
is: ["function", "undefined"]
|
is: ["function", "undefined"]
|
||||||
}
|
},
|
||||||
|
contentScript: loaderContract.rules.contentScript,
|
||||||
|
contentScriptFile: loaderContract.rules.contentScriptFile
|
||||||
};
|
};
|
||||||
|
|
||||||
let labelledItemRules = mix(baseItemRules, {
|
let labelledItemRules = mix(baseItemRules, {
|
||||||
|
@ -172,6 +172,9 @@ exports.boolean = boolean;
|
|||||||
let object = { is: ['object', 'undefined', 'null'] };
|
let object = { is: ['object', 'undefined', 'null'] };
|
||||||
exports.object = object;
|
exports.object = object;
|
||||||
|
|
||||||
|
let array = { is: ['array', 'undefined', 'null'] };
|
||||||
|
exports.array = array;
|
||||||
|
|
||||||
let isTruthyType = type => !(type === 'undefined' || type === 'null');
|
let isTruthyType = type => !(type === 'undefined' || type === 'null');
|
||||||
let findTypes = v => { while (!isArray(v) && v.is) v = v.is; return v };
|
let findTypes = v => { while (!isArray(v) && v.is) v = v.is; return v };
|
||||||
|
|
||||||
|
@ -143,11 +143,17 @@ TestFinder.prototype = {
|
|||||||
suiteModule = cuddlefish.main(loader, suite);
|
suiteModule = cuddlefish.main(loader, suite);
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
// If `Unsupported Application` error thrown during test,
|
if (/Unsupported Application/i.test(e.message)) {
|
||||||
// skip the test suite
|
// If `Unsupported Application` error thrown during test,
|
||||||
suiteModule = {
|
// skip the test suite
|
||||||
'test suite skipped': assert => assert.pass(e.message)
|
suiteModule = {
|
||||||
};
|
'test suite skipped': assert => assert.pass(e.message)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.exception(e);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.testInProcess) {
|
if (this.testInProcess) {
|
||||||
|
@ -33,7 +33,7 @@ function getInitializerName(category) {
|
|||||||
* [event type](https://developer.mozilla.org/en/DOM/event.type) to
|
* [event type](https://developer.mozilla.org/en/DOM/event.type) to
|
||||||
* listen for.
|
* listen for.
|
||||||
* @param {Function} listener
|
* @param {Function} listener
|
||||||
* Function that is called whenever an event of the specified `type`
|
* Function that is called whenever an event of the specified `type`
|
||||||
* occurs.
|
* occurs.
|
||||||
* @param {Boolean} capture
|
* @param {Boolean} capture
|
||||||
* If true, indicates that the user wishes to initiate capture. After
|
* If true, indicates that the user wishes to initiate capture. After
|
||||||
@ -62,7 +62,7 @@ exports.on = on;
|
|||||||
* [event type](https://developer.mozilla.org/en/DOM/event.type) to
|
* [event type](https://developer.mozilla.org/en/DOM/event.type) to
|
||||||
* listen for.
|
* listen for.
|
||||||
* @param {Function} listener
|
* @param {Function} listener
|
||||||
* Function that is called whenever an event of the specified `type`
|
* Function that is called whenever an event of the specified `type`
|
||||||
* occurs.
|
* occurs.
|
||||||
* @param {Boolean} capture
|
* @param {Boolean} capture
|
||||||
* If true, indicates that the user wishes to initiate capture. After
|
* If true, indicates that the user wishes to initiate capture. After
|
||||||
@ -92,7 +92,7 @@ exports.once = once;
|
|||||||
* [event type](https://developer.mozilla.org/en/DOM/event.type) to
|
* [event type](https://developer.mozilla.org/en/DOM/event.type) to
|
||||||
* listen for.
|
* listen for.
|
||||||
* @param {Function} listener
|
* @param {Function} listener
|
||||||
* Function that is called whenever an event of the specified `type`
|
* Function that is called whenever an event of the specified `type`
|
||||||
* occurs.
|
* occurs.
|
||||||
* @param {Boolean} capture
|
* @param {Boolean} capture
|
||||||
* If true, indicates that the user wishes to initiate capture. After
|
* If true, indicates that the user wishes to initiate capture. After
|
||||||
@ -137,3 +137,33 @@ function emit(element, type, { category, initializer, settings }) {
|
|||||||
element.dispatchEvent(event);
|
element.dispatchEvent(event);
|
||||||
};
|
};
|
||||||
exports.emit = emit;
|
exports.emit = emit;
|
||||||
|
|
||||||
|
// Takes DOM `element` and returns promise which is resolved
|
||||||
|
// when given element is removed from it's parent node.
|
||||||
|
const removed = element => {
|
||||||
|
return new Promise(resolve => {
|
||||||
|
const { MutationObserver } = element.ownerDocument.defaultView;
|
||||||
|
const observer = new MutationObserver(mutations => {
|
||||||
|
for (let mutation of mutations) {
|
||||||
|
for (let node of mutation.removedNodes || []) {
|
||||||
|
if (node === element) {
|
||||||
|
observer.disconnect();
|
||||||
|
resolve(element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
observer.observe(element.parentNode, {childList: true});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
exports.removed = removed;
|
||||||
|
|
||||||
|
const when = (element, eventName, capture=false) => new Promise(resolve => {
|
||||||
|
const listener = event => {
|
||||||
|
element.removeEventListener(eventName, listener, capture);
|
||||||
|
resolve(event);
|
||||||
|
};
|
||||||
|
|
||||||
|
element.addEventListener(eventName, listener, capture);
|
||||||
|
});
|
||||||
|
exports.when = when;
|
||||||
|
@ -260,7 +260,7 @@ exports.Reactor = Reactor;
|
|||||||
* Takes an object used as options with potential keys like 'onMessage',
|
* Takes an object used as options with potential keys like 'onMessage',
|
||||||
* used to be called `require('sdk/event/core').setListeners` on.
|
* used to be called `require('sdk/event/core').setListeners` on.
|
||||||
* This strips all keys that would trigger a listener to be set.
|
* This strips all keys that would trigger a listener to be set.
|
||||||
*
|
*
|
||||||
* @params {Object} object
|
* @params {Object} object
|
||||||
* @return {Object}
|
* @return {Object}
|
||||||
*/
|
*/
|
||||||
@ -273,3 +273,8 @@ function stripListeners (object) {
|
|||||||
}, {});
|
}, {});
|
||||||
}
|
}
|
||||||
exports.stripListeners = stripListeners;
|
exports.stripListeners = stripListeners;
|
||||||
|
|
||||||
|
const when = (target, type) => new Promise(resolve => {
|
||||||
|
once(target, type, resolve);
|
||||||
|
});
|
||||||
|
exports.when = when;
|
||||||
|
@ -34,7 +34,8 @@ exports.get = function get(k) {
|
|||||||
if (arguments.length <= 1)
|
if (arguments.length <= 1)
|
||||||
return localized;
|
return localized;
|
||||||
|
|
||||||
let args = arguments;
|
let args = Array.slice(arguments);
|
||||||
|
let placeholders = [null, ...args.slice(typeof(n) === "number" ? 2 : 1)];
|
||||||
|
|
||||||
if (typeof localized == "object" && "other" in localized) {
|
if (typeof localized == "object" && "other" in localized) {
|
||||||
// # Plural form:
|
// # Plural form:
|
||||||
@ -76,11 +77,15 @@ exports.get = function get(k) {
|
|||||||
// in translation.
|
// in translation.
|
||||||
// * In case of plural form, we has `%d` instead of `%s`.
|
// * In case of plural form, we has `%d` instead of `%s`.
|
||||||
let offset = 1;
|
let offset = 1;
|
||||||
localized = localized.replace(/%(\d*)(s|d)/g, function (v, n) {
|
if (placeholders.length > 1) {
|
||||||
let rv = args[n != "" ? n : offset];
|
args = placeholders;
|
||||||
offset++;
|
}
|
||||||
return rv;
|
|
||||||
});
|
localized = localized.replace(/%(\d*)[sd]/g, (v, n) => {
|
||||||
|
let rv = args[n != "" ? n : offset];
|
||||||
|
offset++;
|
||||||
|
return rv;
|
||||||
|
});
|
||||||
|
|
||||||
return localized;
|
return localized;
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,7 @@ exports.get = function get(k) {
|
|||||||
exports.locale = function locale() {
|
exports.locale = function locale() {
|
||||||
return bestMatchingLocale;
|
return bestMatchingLocale;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the short locale code: ja, en, fr
|
// Returns the short locale code: ja, en, fr
|
||||||
exports.language = function language() {
|
exports.language = function language() {
|
||||||
return bestMatchingLocale ? bestMatchingLocale.split("-")[0].toLowerCase()
|
return bestMatchingLocale ? bestMatchingLocale.split("-")[0].toLowerCase()
|
||||||
|
@ -66,6 +66,10 @@ function get(key, n, locales) {
|
|||||||
localized = getKey(locale, key);
|
localized = getKey(locale, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!localized) {
|
||||||
|
localized = getKey(locale, key + '[other]');
|
||||||
|
}
|
||||||
|
|
||||||
if (localized) {
|
if (localized) {
|
||||||
return localized;
|
return localized;
|
||||||
}
|
}
|
||||||
|
12
addon-sdk/source/lib/sdk/messaging.js
Normal file
12
addon-sdk/source/lib/sdk/messaging.js
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
/* 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/. */
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
module.metadata = {
|
||||||
|
"stability": "unstable"
|
||||||
|
};
|
||||||
|
|
||||||
|
const { window } = require("sdk/addon/window");
|
||||||
|
exports.MessageChannel = window.MessageChannel;
|
||||||
|
exports.MessagePort = window.MessagePort;
|
@ -12,7 +12,8 @@ const { Cc, Ci, Cr } = require("chrome");
|
|||||||
const apiUtils = require("./deprecated/api-utils");
|
const apiUtils = require("./deprecated/api-utils");
|
||||||
const errors = require("./deprecated/errors");
|
const errors = require("./deprecated/errors");
|
||||||
const { isString, isUndefined, instanceOf } = require('./lang/type');
|
const { isString, isUndefined, instanceOf } = require('./lang/type');
|
||||||
const { URL } = require('./url');
|
const { URL, isLocalURL } = require('./url');
|
||||||
|
const { data } = require('./self');
|
||||||
|
|
||||||
const NOTIFICATION_DIRECTIONS = ["auto", "ltr", "rtl"];
|
const NOTIFICATION_DIRECTIONS = ["auto", "ltr", "rtl"];
|
||||||
|
|
||||||
@ -39,7 +40,10 @@ exports.notify = function notifications_notify(options) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
function notifyWithOpts(notifyFn) {
|
function notifyWithOpts(notifyFn) {
|
||||||
notifyFn(valOpts.iconURL, valOpts.title, valOpts.text, !!clickObserver,
|
let { iconURL } = valOpts;
|
||||||
|
iconURL = iconURL && isLocalURL(iconURL) ? data.url(iconURL) : iconURL;
|
||||||
|
|
||||||
|
notifyFn(iconURL, valOpts.title, valOpts.text, !!clickObserver,
|
||||||
valOpts.data, clickObserver, valOpts.tag, valOpts.dir, valOpts.lang);
|
valOpts.data, clickObserver, valOpts.tag, valOpts.dir, valOpts.lang);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
@ -47,7 +51,7 @@ exports.notify = function notifications_notify(options) {
|
|||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
if (err instanceof Ci.nsIException && err.result == Cr.NS_ERROR_FILE_NOT_FOUND) {
|
if (err instanceof Ci.nsIException && err.result == Cr.NS_ERROR_FILE_NOT_FOUND) {
|
||||||
console.warn("The notification icon named by " + valOpts.iconURL +
|
console.warn("The notification icon named by " + iconURL +
|
||||||
" does not exist. A default icon will be used instead.");
|
" does not exist. A default icon will be used instead.");
|
||||||
delete valOpts.iconURL;
|
delete valOpts.iconURL;
|
||||||
notifyWithOpts(notify);
|
notifyWithOpts(notify);
|
||||||
|
@ -26,6 +26,7 @@ const { contract: loaderContract } = require('./content/loader');
|
|||||||
const { has } = require('./util/array');
|
const { has } = require('./util/array');
|
||||||
const { Rules } = require('./util/rules');
|
const { Rules } = require('./util/rules');
|
||||||
const { merge } = require('./util/object');
|
const { merge } = require('./util/object');
|
||||||
|
const { data } = require('./self');
|
||||||
|
|
||||||
const views = WeakMap();
|
const views = WeakMap();
|
||||||
const workers = WeakMap();
|
const workers = WeakMap();
|
||||||
@ -92,10 +93,13 @@ const Page = Class({
|
|||||||
setup: function Page(options) {
|
setup: function Page(options) {
|
||||||
let page = this;
|
let page = this;
|
||||||
options = pageContract(options);
|
options = pageContract(options);
|
||||||
|
|
||||||
|
let uri = options.contentURL;
|
||||||
|
|
||||||
let view = makeFrame(window.document, {
|
let view = makeFrame(window.document, {
|
||||||
nodeName: 'iframe',
|
nodeName: 'iframe',
|
||||||
type: 'content',
|
type: 'content',
|
||||||
uri: options.contentURL,
|
uri: uri ? data.url(uri) : '',
|
||||||
allowJavascript: options.allow.script,
|
allowJavascript: options.allow.script,
|
||||||
allowPlugins: true,
|
allowPlugins: true,
|
||||||
allowAuth: true
|
allowAuth: true
|
||||||
@ -124,12 +128,19 @@ const Page = Class({
|
|||||||
let allowJavascript = pageContract({ allow: value }).allow.script;
|
let allowJavascript = pageContract({ allow: value }).allow.script;
|
||||||
return allowJavascript ? enableScript(this) : disableScript(this);
|
return allowJavascript ? enableScript(this) : disableScript(this);
|
||||||
},
|
},
|
||||||
get contentURL() { return viewFor(this).getAttribute('src'); },
|
get contentURL() { return viewFor(this).getAttribute("data-src") },
|
||||||
set contentURL(value) {
|
set contentURL(value) {
|
||||||
if (!isValidURL(this, value)) return;
|
if (!isValidURL(this, value)) return;
|
||||||
let view = viewFor(this);
|
let view = viewFor(this);
|
||||||
let contentURL = pageContract({ contentURL: value }).contentURL;
|
let contentURL = pageContract({ contentURL: value }).contentURL;
|
||||||
view.setAttribute('src', contentURL);
|
|
||||||
|
// page-worker doesn't have a model like other APIs, so to be consitent
|
||||||
|
// with the behavior "what you set is what you get", we need to store
|
||||||
|
// the original `contentURL` given.
|
||||||
|
// Even if XUL elements doesn't support `dataset`, properties, to
|
||||||
|
// indicate that is a custom attribute the syntax "data-*" is used.
|
||||||
|
view.setAttribute('data-src', contentURL);
|
||||||
|
view.setAttribute('src', data.url(contentURL));
|
||||||
},
|
},
|
||||||
dispose: function () {
|
dispose: function () {
|
||||||
if (isDisposed(this)) return;
|
if (isDisposed(this)) return;
|
||||||
|
@ -307,13 +307,13 @@ on(hides, "data", ({target}) => emit(panelFor(target), "hide"));
|
|||||||
on(ready, "data", ({target}) => {
|
on(ready, "data", ({target}) => {
|
||||||
let panel = panelFor(target);
|
let panel = panelFor(target);
|
||||||
let window = domPanel.getContentDocument(target).defaultView;
|
let window = domPanel.getContentDocument(target).defaultView;
|
||||||
|
|
||||||
workerFor(panel).attach(window);
|
workerFor(panel).attach(window);
|
||||||
});
|
});
|
||||||
|
|
||||||
on(start, "data", ({target}) => {
|
on(start, "data", ({target}) => {
|
||||||
let panel = panelFor(target);
|
let panel = panelFor(target);
|
||||||
let window = domPanel.getContentDocument(target).defaultView;
|
let window = domPanel.getContentDocument(target).defaultView;
|
||||||
|
|
||||||
attach(styleFor(panel), window);
|
attach(styleFor(panel), window);
|
||||||
});
|
});
|
||||||
|
@ -17,6 +17,8 @@ const { getMostRecentBrowserWindow, getOwnerBrowserWindow,
|
|||||||
const { create: createFrame, swapFrameLoaders } = require("../frame/utils");
|
const { create: createFrame, swapFrameLoaders } = require("../frame/utils");
|
||||||
const { window: addonWindow } = require("../addon/window");
|
const { window: addonWindow } = require("../addon/window");
|
||||||
const { isNil } = require("../lang/type");
|
const { isNil } = require("../lang/type");
|
||||||
|
const { data } = require('../self');
|
||||||
|
|
||||||
const events = require("../system/events");
|
const events = require("../system/events");
|
||||||
|
|
||||||
|
|
||||||
@ -402,7 +404,10 @@ exports.getContentFrame = getContentFrame;
|
|||||||
function getContentDocument(panel) getContentFrame(panel).contentDocument
|
function getContentDocument(panel) getContentFrame(panel).contentDocument
|
||||||
exports.getContentDocument = getContentDocument;
|
exports.getContentDocument = getContentDocument;
|
||||||
|
|
||||||
function setURL(panel, url) getContentFrame(panel).setAttribute("src", url)
|
function setURL(panel, url) {
|
||||||
|
getContentFrame(panel).setAttribute("src", url ? data.url(url) : url);
|
||||||
|
}
|
||||||
|
|
||||||
exports.setURL = setURL;
|
exports.setURL = setURL;
|
||||||
|
|
||||||
function allowContextMenu(panel, allow) {
|
function allowContextMenu(panel, allow) {
|
||||||
|
@ -28,7 +28,7 @@ const permissions = metadata.permissions || {};
|
|||||||
const isPacked = rootURI && rootURI.indexOf("jar:") === 0;
|
const isPacked = rootURI && rootURI.indexOf("jar:") === 0;
|
||||||
|
|
||||||
const uri = (path="") =>
|
const uri = (path="") =>
|
||||||
path.contains(":") ? path : addonDataURI + path;
|
path.contains(":") ? path : addonDataURI + path.replace(/^\.\//, "");
|
||||||
|
|
||||||
|
|
||||||
// Some XPCOM APIs require valid URIs as an argument for certain operations
|
// Some XPCOM APIs require valid URIs as an argument for certain operations
|
||||||
|
@ -9,24 +9,14 @@ module.metadata = {
|
|||||||
|
|
||||||
const { Cc, Ci } = require("chrome");
|
const { Cc, Ci } = require("chrome");
|
||||||
const { Class } = require("../core/heritage");
|
const { Class } = require("../core/heritage");
|
||||||
const { ns } = require("../core/namespace");
|
const { URL, isLocalURL } = require('../url');
|
||||||
const { URL } = require('../url');
|
|
||||||
const events = require("../system/events");
|
const events = require("../system/events");
|
||||||
const { loadSheet, removeSheet, isTypeValid } = require("./utils");
|
const { loadSheet, removeSheet, isTypeValid } = require("./utils");
|
||||||
const { isString } = require("../lang/type");
|
const { isString } = require("../lang/type");
|
||||||
const { attachTo, detachFrom, getTargetWindow } = require("../content/mod");
|
const { attachTo, detachFrom, getTargetWindow } = require("../content/mod");
|
||||||
|
const { data } = require('../self');
|
||||||
|
|
||||||
const { freeze, create } = Object;
|
const { freeze, create } = Object;
|
||||||
const LOCAL_URI_SCHEMES = ['resource', 'data'];
|
|
||||||
|
|
||||||
function isLocalURL(item) {
|
|
||||||
try {
|
|
||||||
return LOCAL_URI_SCHEMES.indexOf(URL(item).scheme) > -1;
|
|
||||||
}
|
|
||||||
catch(e) {}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function Style({ source, uri, type }) {
|
function Style({ source, uri, type }) {
|
||||||
source = source == null ? null : freeze([].concat(source));
|
source = source == null ? null : freeze([].concat(source));
|
||||||
@ -54,7 +44,7 @@ exports.Style = Style;
|
|||||||
attachTo.define(Style, function (style, window) {
|
attachTo.define(Style, function (style, window) {
|
||||||
if (style.uri) {
|
if (style.uri) {
|
||||||
for (let uri of style.uri)
|
for (let uri of style.uri)
|
||||||
loadSheet(window, uri, style.type);
|
loadSheet(window, data.url(uri), style.type);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (style.source) {
|
if (style.source) {
|
||||||
@ -69,7 +59,7 @@ attachTo.define(Style, function (style, window) {
|
|||||||
detachFrom.define(Style, function (style, window) {
|
detachFrom.define(Style, function (style, window) {
|
||||||
if (style.uri)
|
if (style.uri)
|
||||||
for (let uri of style.uri)
|
for (let uri of style.uri)
|
||||||
removeSheet(window, uri);
|
removeSheet(window, data.url(uri));
|
||||||
|
|
||||||
if (style.source) {
|
if (style.source) {
|
||||||
let uri = "data:text/css;charset=utf-8,";
|
let uri = "data:text/css;charset=utf-8,";
|
||||||
|
@ -3,16 +3,20 @@
|
|||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const { validateOptions } = require('../deprecated/api-utils');
|
const { validateOptions } = require("../deprecated/api-utils");
|
||||||
|
const { data } = require("../self");
|
||||||
|
|
||||||
function Options(options) {
|
function Options(options) {
|
||||||
if ('string' === typeof options)
|
if ('string' === typeof options)
|
||||||
options = { url: options };
|
options = { url: options };
|
||||||
|
|
||||||
return validateOptions(options, {
|
return validateOptions(options, {
|
||||||
url: { is: ["string"] },
|
url: {
|
||||||
|
is: ["string"],
|
||||||
|
map: (v) => v ? data.url(v) : v
|
||||||
|
},
|
||||||
inBackground: {
|
inBackground: {
|
||||||
map: function(v) !!v,
|
map: Boolean,
|
||||||
is: ["undefined", "boolean"]
|
is: ["undefined", "boolean"]
|
||||||
},
|
},
|
||||||
isPinned: { is: ["undefined", "boolean"] },
|
isPinned: { is: ["undefined", "boolean"] },
|
||||||
|
@ -17,7 +17,7 @@ const { off, emit, setListeners } = require('../event/core');
|
|||||||
const { EventTarget } = require('../event/target');
|
const { EventTarget } = require('../event/target');
|
||||||
const { URL } = require('../url');
|
const { URL } = require('../url');
|
||||||
const { add, remove, has, clear, iterator } = require('../lang/weak-set');
|
const { add, remove, has, clear, iterator } = require('../lang/weak-set');
|
||||||
const { id: addonID } = require('../self');
|
const { id: addonID, data } = require('../self');
|
||||||
const { WindowTracker } = require('../deprecated/window-utils');
|
const { WindowTracker } = require('../deprecated/window-utils');
|
||||||
const { isShowing } = require('./sidebar/utils');
|
const { isShowing } = require('./sidebar/utils');
|
||||||
const { isBrowser, getMostRecentBrowserWindow, windows, isWindowPrivate } = require('../window/utils');
|
const { isBrowser, getMostRecentBrowserWindow, windows, isWindowPrivate } = require('../window/utils');
|
||||||
@ -35,6 +35,8 @@ const { identify } = require('./id');
|
|||||||
const { uuid } = require('../util/uuid');
|
const { uuid } = require('../util/uuid');
|
||||||
const { viewFor } = require('../view/core');
|
const { viewFor } = require('../view/core');
|
||||||
|
|
||||||
|
const resolveURL = (url) => url ? data.url(url) : url;
|
||||||
|
|
||||||
const sidebarNS = ns();
|
const sidebarNS = ns();
|
||||||
|
|
||||||
const WEB_PANEL_BROWSER_ID = 'web-panels-browser';
|
const WEB_PANEL_BROWSER_ID = 'web-panels-browser';
|
||||||
@ -107,7 +109,7 @@ const Sidebar = Class({
|
|||||||
|
|
||||||
let sbTitle = window.document.getElementById('sidebar-title');
|
let sbTitle = window.document.getElementById('sidebar-title');
|
||||||
function onWebPanelSidebarCreated() {
|
function onWebPanelSidebarCreated() {
|
||||||
if (panelBrowser.contentWindow.location != model.url ||
|
if (panelBrowser.contentWindow.location != resolveURL(model.url) ||
|
||||||
sbTitle.value != model.title) {
|
sbTitle.value != model.title) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -264,6 +266,8 @@ const Sidebar = Class({
|
|||||||
exports.Sidebar = Sidebar;
|
exports.Sidebar = Sidebar;
|
||||||
|
|
||||||
function validateTitleAndURLCombo(sidebar, title, url) {
|
function validateTitleAndURLCombo(sidebar, title, url) {
|
||||||
|
url = resolveURL(url);
|
||||||
|
|
||||||
if (sidebar.title == title && sidebar.url == url) {
|
if (sidebar.title == title && sidebar.url == url) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -14,11 +14,13 @@ const { models, buttons, views, viewsFor, modelFor } = require('./namespace');
|
|||||||
const { isBrowser, getMostRecentBrowserWindow, windows, isWindowPrivate } = require('../../window/utils');
|
const { isBrowser, getMostRecentBrowserWindow, windows, isWindowPrivate } = require('../../window/utils');
|
||||||
const { setStateFor } = require('../state');
|
const { setStateFor } = require('../state');
|
||||||
const { defer } = require('../../core/promise');
|
const { defer } = require('../../core/promise');
|
||||||
const { isPrivateBrowsingSupported } = require('../../self');
|
const { isPrivateBrowsingSupported, data } = require('../../self');
|
||||||
|
|
||||||
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
||||||
const WEB_PANEL_BROWSER_ID = 'web-panels-browser';
|
const WEB_PANEL_BROWSER_ID = 'web-panels-browser';
|
||||||
|
|
||||||
|
const resolveURL = (url) => url ? data.url(url) : url;
|
||||||
|
|
||||||
function create(window, details) {
|
function create(window, details) {
|
||||||
let id = makeID(details.id);
|
let id = makeID(details.id);
|
||||||
let { document } = window;
|
let { document } = window;
|
||||||
@ -29,7 +31,7 @@ function create(window, details) {
|
|||||||
let menuitem = document.createElementNS(XUL_NS, 'menuitem');
|
let menuitem = document.createElementNS(XUL_NS, 'menuitem');
|
||||||
menuitem.setAttribute('id', id);
|
menuitem.setAttribute('id', id);
|
||||||
menuitem.setAttribute('label', details.title);
|
menuitem.setAttribute('label', details.title);
|
||||||
menuitem.setAttribute('sidebarurl', details.sidebarurl);
|
menuitem.setAttribute('sidebarurl', resolveURL(details.sidebarurl));
|
||||||
menuitem.setAttribute('checked', 'false');
|
menuitem.setAttribute('checked', 'false');
|
||||||
menuitem.setAttribute('type', 'checkbox');
|
menuitem.setAttribute('type', 'checkbox');
|
||||||
menuitem.setAttribute('group', 'sidebar');
|
menuitem.setAttribute('group', 'sidebar');
|
||||||
@ -74,6 +76,8 @@ exports.updateTitle = updateTitle;
|
|||||||
function updateURL(sidebar, url) {
|
function updateURL(sidebar, url) {
|
||||||
let eleID = makeID(sidebar.id);
|
let eleID = makeID(sidebar.id);
|
||||||
|
|
||||||
|
url = resolveURL(url);
|
||||||
|
|
||||||
for (let window of windows(null, { includePrivate: true })) {
|
for (let window of windows(null, { includePrivate: true })) {
|
||||||
// update the menuitem
|
// update the menuitem
|
||||||
let mi = window.document.getElementById(eleID);
|
let mi = window.document.getElementById(eleID);
|
||||||
@ -111,8 +115,10 @@ function isSidebarShowing(window, sidebar) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (sidebarTitle.value == modelFor(sidebar).title) {
|
if (sidebarTitle.value == modelFor(sidebar).title) {
|
||||||
|
let url = resolveURL(modelFor(sidebar).url);
|
||||||
|
|
||||||
// checks if the sidebar is loading
|
// checks if the sidebar is loading
|
||||||
if (win.gWebPanelURI == modelFor(sidebar).url) {
|
if (win.gWebPanelURI == url) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -122,11 +128,11 @@ function isSidebarShowing(window, sidebar) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ele.getAttribute('cachedurl') == modelFor(sidebar).url) {
|
if (ele.getAttribute('cachedurl') == url) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ele && ele.contentWindow && ele.contentWindow.location == modelFor(sidebar).url) {
|
if (ele && ele.contentWindow && ele.contentWindow.location == url) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -154,7 +160,7 @@ function showSidebar(window, sidebar, newURL) {
|
|||||||
let menuitem = window.document.getElementById(makeID(model.id));
|
let menuitem = window.document.getElementById(makeID(model.id));
|
||||||
menuitem.setAttribute('checked', true);
|
menuitem.setAttribute('checked', true);
|
||||||
|
|
||||||
window.openWebPanel(model.title, newURL || model.url);
|
window.openWebPanel(model.title, resolveURL(newURL || model.url));
|
||||||
}
|
}
|
||||||
|
|
||||||
return promise;
|
return promise;
|
||||||
|
@ -9,6 +9,7 @@ module.metadata = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const { validateOptions: valid } = require("../deprecated/api-utils");
|
const { validateOptions: valid } = require("../deprecated/api-utils");
|
||||||
|
const method = require("method/core");
|
||||||
|
|
||||||
// Function takes property validation rules and returns function that given
|
// Function takes property validation rules and returns function that given
|
||||||
// an `options` object will return validated / normalized options back. If
|
// an `options` object will return validated / normalized options back. If
|
||||||
@ -18,9 +19,9 @@ const { validateOptions: valid } = require("../deprecated/api-utils");
|
|||||||
// property getter and setters can be mixed into prototype. For more details
|
// property getter and setters can be mixed into prototype. For more details
|
||||||
// see `properties` function below.
|
// see `properties` function below.
|
||||||
function contract(rules) {
|
function contract(rules) {
|
||||||
function validator(options) {
|
const validator = (instance, options) => {
|
||||||
return valid(options || {}, rules);
|
return valid(options || instance || {}, rules);
|
||||||
}
|
};
|
||||||
validator.rules = rules
|
validator.rules = rules
|
||||||
validator.properties = function(modelFor) {
|
validator.properties = function(modelFor) {
|
||||||
return properties(modelFor, rules);
|
return properties(modelFor, rules);
|
||||||
@ -48,4 +49,7 @@ function properties(modelFor, rules) {
|
|||||||
}, {});
|
}, {});
|
||||||
return Object.create(Object.prototype, descriptor);
|
return Object.create(Object.prototype, descriptor);
|
||||||
}
|
}
|
||||||
exports.properties = properties
|
exports.properties = properties;
|
||||||
|
|
||||||
|
const validate = method("contract/validate");
|
||||||
|
exports.validate = validate;
|
||||||
|
@ -19,7 +19,7 @@ const { EventTarget } = require('../event/target');
|
|||||||
const { when: unload } = require('../system/unload');
|
const { when: unload } = require('../system/unload');
|
||||||
const { windowIterator } = require('../deprecated/window-utils');
|
const { windowIterator } = require('../deprecated/window-utils');
|
||||||
const { List, addListItem, removeListItem } = require('../util/list');
|
const { List, addListItem, removeListItem } = require('../util/list');
|
||||||
const { isPrivateBrowsingSupported } = require('../self');
|
const { isPrivateBrowsingSupported, data } = require('../self');
|
||||||
const { isTabPBSupported, ignoreWindow } = require('../private-browsing/utils');
|
const { isTabPBSupported, ignoreWindow } = require('../private-browsing/utils');
|
||||||
|
|
||||||
const mainWindow = windowNS(browserWindows.activeWindow).window;
|
const mainWindow = windowNS(browserWindows.activeWindow).window;
|
||||||
@ -55,7 +55,8 @@ const Tabs = Class({
|
|||||||
console.error(ERR_FENNEC_MSG); // TODO
|
console.error(ERR_FENNEC_MSG); // TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
let rawTab = openTab(windowNS(activeWin).window, options.url, {
|
let url = options.url ? data.url(options.url) : options.url;
|
||||||
|
let rawTab = openTab(windowNS(activeWin).window, url, {
|
||||||
inBackground: options.inBackground,
|
inBackground: options.inBackground,
|
||||||
isPrivate: supportPrivateTabs && options.isPrivate
|
isPrivate: supportPrivateTabs && options.isPrivate
|
||||||
});
|
});
|
||||||
|
@ -17,7 +17,7 @@ const { getOwnerWindow, getActiveTab, getTabs,
|
|||||||
const { Options } = require("../tabs/common");
|
const { Options } = require("../tabs/common");
|
||||||
const { observer: tabsObserver } = require("../tabs/observer");
|
const { observer: tabsObserver } = require("../tabs/observer");
|
||||||
const { ignoreWindow } = require("../private-browsing/utils");
|
const { ignoreWindow } = require("../private-browsing/utils");
|
||||||
const { when: unload } = require('../system/unload');
|
const { when: unload } = require("../system/unload");
|
||||||
|
|
||||||
const TAB_BROWSER = "tabbrowser";
|
const TAB_BROWSER = "tabbrowser";
|
||||||
|
|
||||||
|
@ -27,6 +27,9 @@ skip = [
|
|||||||
"packages/api-utils/tests/test-querystring.js", # MIT
|
"packages/api-utils/tests/test-querystring.js", # MIT
|
||||||
"packages/api-utils/lib/promise.js", # MIT
|
"packages/api-utils/lib/promise.js", # MIT
|
||||||
"packages/api-utils/tests/test-promise.js", # MIT
|
"packages/api-utils/tests/test-promise.js", # MIT
|
||||||
|
"examples/actor-repl/README.md", # It's damn readme file
|
||||||
|
"examples/actor-repl/data/codemirror-compressed.js", # MIT
|
||||||
|
"examples/actor-repl/data/codemirror.css", # MIT
|
||||||
]
|
]
|
||||||
absskip = [from_sdk_top(os.path.join(*fn.split("/"))) for fn in skip]
|
absskip = [from_sdk_top(os.path.join(*fn.split("/"))) for fn in skip]
|
||||||
|
|
||||||
|
@ -20,3 +20,9 @@ explicitPlural[other]=other
|
|||||||
# file parser)
|
# file parser)
|
||||||
unicodeEscape = \u0020\u0040\u0020
|
unicodeEscape = \u0020\u0040\u0020
|
||||||
# this string equals to " @ "
|
# this string equals to " @ "
|
||||||
|
|
||||||
|
# bug 1033309 plurals with multiple placeholders
|
||||||
|
first_identifier[one]=first entry is %s and the second one is %s.
|
||||||
|
first_identifier=the entries are %s and %s.
|
||||||
|
second_identifier[other]=first entry is %s and the second one is %s.
|
||||||
|
third_identifier=first entry is %s and the second one is %s.
|
||||||
|
@ -163,6 +163,20 @@ exports.testEnUsLocaleName = createTest("en-GB", function(assert, loader, done)
|
|||||||
"other",
|
"other",
|
||||||
"PluralForm form can be omitting generic key [i.e. without ...[other] at end of key)");
|
"PluralForm form can be omitting generic key [i.e. without ...[other] at end of key)");
|
||||||
|
|
||||||
|
assert.equal(_("first_identifier", "ONE", "TWO"), "the entries are ONE and TWO.", "first_identifier no count");
|
||||||
|
assert.equal(_("first_identifier", 0, "ONE", "TWO"), "the entries are ONE and TWO.", "first_identifier with count = 0");
|
||||||
|
assert.equal(_("first_identifier", 1, "ONE", "TWO"), "first entry is ONE and the second one is TWO.", "first_identifier with count = 1");
|
||||||
|
assert.equal(_("first_identifier", 2, "ONE", "TWO"), "the entries are ONE and TWO.", "first_identifier with count = 2");
|
||||||
|
|
||||||
|
assert.equal(_("second_identifier", "ONE", "TWO"), "first entry is ONE and the second one is TWO.", "second_identifier with no count");
|
||||||
|
assert.equal(_("second_identifier", 0, "ONE", "TWO"), "first entry is ONE and the second one is TWO.", "second_identifier with count = 0");
|
||||||
|
assert.equal(_("second_identifier", 1, "ONE", "TWO"), "first entry is ONE and the second one is TWO.", "second_identifier with count = 1");
|
||||||
|
assert.equal(_("second_identifier", 2, "ONE", "TWO"), "first entry is ONE and the second one is TWO.", "second_identifier with count = 2");
|
||||||
|
|
||||||
|
assert.equal(_("third_identifier", "ONE", "TWO"), "first entry is ONE and the second one is TWO.", "third_identifier with no count");
|
||||||
|
assert.equal(_("third_identifier", 0, "ONE", "TWO"), "first entry is ONE and the second one is TWO.", "third_identifier with count = 0");
|
||||||
|
assert.equal(_("third_identifier", 2, "ONE", "TWO"), "first entry is ONE and the second one is TWO.", "third_identifier with count = 2");
|
||||||
|
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -20,3 +20,9 @@ explicitPlural[other]=other
|
|||||||
# file parser)
|
# file parser)
|
||||||
unicodeEscape = \u0020\u0040\u0020
|
unicodeEscape = \u0020\u0040\u0020
|
||||||
# this string equals to " @ "
|
# this string equals to " @ "
|
||||||
|
|
||||||
|
# bug 1033309 plurals with multiple placeholders
|
||||||
|
first_identifier[one]=first entry is %s and the second one is %s.
|
||||||
|
first_identifier=the entries are %s and %s.
|
||||||
|
second_identifier[other]=first entry is %s and the second one is %s.
|
||||||
|
third_identifier=first entry is %s and the second one is %s.
|
||||||
|
@ -87,7 +87,6 @@ exports.testExactMatching = createTest("fr-FR", function(assert, loader, done) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
exports.testHtmlLocalization = createTest("en-GB", function(assert, loader, done) {
|
exports.testHtmlLocalization = createTest("en-GB", function(assert, loader, done) {
|
||||||
|
|
||||||
// Ensure initing html component that watch document creations
|
// Ensure initing html component that watch document creations
|
||||||
// Note that this module is automatically initialized in
|
// Note that this module is automatically initialized in
|
||||||
// cuddlefish.js:Loader.main in regular addons. But it isn't for unit tests.
|
// cuddlefish.js:Loader.main in regular addons. But it isn't for unit tests.
|
||||||
@ -165,6 +164,20 @@ exports.testEnUsLocaleName = createTest("en-US", function(assert, loader, done)
|
|||||||
"other",
|
"other",
|
||||||
"PluralForm form can be omitting generic key [i.e. without ...[other] at end of key)");
|
"PluralForm form can be omitting generic key [i.e. without ...[other] at end of key)");
|
||||||
|
|
||||||
|
assert.equal(_("first_identifier", "ONE", "TWO"), "the entries are ONE and TWO.", "first_identifier no count");
|
||||||
|
assert.equal(_("first_identifier", 0, "ONE", "TWO"), "the entries are ONE and TWO.", "first_identifier with count = 0");
|
||||||
|
assert.equal(_("first_identifier", 1, "ONE", "TWO"), "first entry is ONE and the second one is TWO.", "first_identifier with count = 1");
|
||||||
|
assert.equal(_("first_identifier", 2, "ONE", "TWO"), "the entries are ONE and TWO.", "first_identifier with count = 2");
|
||||||
|
|
||||||
|
assert.equal(_("second_identifier", "ONE", "TWO"), "first entry is ONE and the second one is TWO.", "second_identifier with no count");
|
||||||
|
assert.equal(_("second_identifier", 0, "ONE", "TWO"), "first entry is ONE and the second one is TWO.", "second_identifier with count = 0");
|
||||||
|
assert.equal(_("second_identifier", 1, "ONE", "TWO"), "first entry is ONE and the second one is TWO.", "second_identifier with count = 1");
|
||||||
|
assert.equal(_("second_identifier", 2, "ONE", "TWO"), "first entry is ONE and the second one is TWO.", "second_identifier with count = 2");
|
||||||
|
|
||||||
|
assert.equal(_("third_identifier", "ONE", "TWO"), "first entry is ONE and the second one is TWO.", "third_identifier with no count");
|
||||||
|
assert.equal(_("third_identifier", 0, "ONE", "TWO"), "first entry is ONE and the second one is TWO.", "third_identifier with count = 0");
|
||||||
|
assert.equal(_("third_identifier", 2, "ONE", "TWO"), "first entry is ONE and the second one is TWO.", "third_identifier with count = 2");
|
||||||
|
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1,3 +0,0 @@
|
|||||||
<script>
|
|
||||||
addon.postMessage("hello addon")
|
|
||||||
</script>
|
|
@ -1,34 +0,0 @@
|
|||||||
/* 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/. */
|
|
||||||
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
const app = require("sdk/system/xul-app");
|
|
||||||
|
|
||||||
exports["test addon globa"] = app.is("Firefox") ? testAddonGlobal : unsupported;
|
|
||||||
|
|
||||||
function testAddonGlobal (assert, done) {
|
|
||||||
const { Panel } = require("sdk/panel")
|
|
||||||
const { data } = require("sdk/self")
|
|
||||||
|
|
||||||
let panel = Panel({
|
|
||||||
contentURL: //"data:text/html,now?",
|
|
||||||
data.url("./index.html"),
|
|
||||||
onMessage: function(message) {
|
|
||||||
assert.pass("got message from panel script");
|
|
||||||
panel.destroy();
|
|
||||||
done();
|
|
||||||
},
|
|
||||||
onError: function(error) {
|
|
||||||
assert.fail(Error("failed to recieve message"));
|
|
||||||
done();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
function unsupported (assert) {
|
|
||||||
assert.pass("privileged-panel unsupported on platform");
|
|
||||||
}
|
|
||||||
|
|
||||||
require("sdk/test/runner").runTestsFromModule(module);
|
|
@ -1,3 +0,0 @@
|
|||||||
{
|
|
||||||
"id": "test-privileged-addon"
|
|
||||||
}
|
|
@ -2,5 +2,9 @@
|
|||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
exports.url = path =>
|
const { uri } = module;
|
||||||
module.uri.substr(0, module.uri.lastIndexOf("/") + 1) + "fixtures/" + path
|
const prefix = uri.substr(0, uri.lastIndexOf("/") + 1) + "fixtures/";
|
||||||
|
|
||||||
|
exports.url = (path="") => path && path.contains(":")
|
||||||
|
? path
|
||||||
|
: prefix + path.replace(/^\.\//, "");
|
||||||
|
1
addon-sdk/source/test/fixtures/border-style.css
vendored
Normal file
1
addon-sdk/source/test/fixtures/border-style.css
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
div { border-style: dashed; }
|
@ -1,10 +1,12 @@
|
|||||||
<script>
|
<script>
|
||||||
addon.port.on('X', function(msg) {
|
if ("addon" in window) {
|
||||||
// last message
|
addon.port.on('X', function(msg) {
|
||||||
addon.port.emit('X', msg + '3');
|
// last message
|
||||||
});
|
addon.port.emit('X', msg + '3');
|
||||||
|
});
|
||||||
|
|
||||||
// start messaging chain
|
// start messaging chain
|
||||||
addon.port.emit('Y', '1');
|
addon.port.emit('Y', '1');
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
SIDEBAR TEST
|
SIDEBAR TEST
|
||||||
|
@ -9,6 +9,8 @@ const timer = require("sdk/timers");
|
|||||||
const xulApp = require("sdk/system/xul-app");
|
const xulApp = require("sdk/system/xul-app");
|
||||||
const { Loader } = require("sdk/test/loader");
|
const { Loader } = require("sdk/test/loader");
|
||||||
const { openTab, getBrowserForTab, closeTab } = require("sdk/tabs/utils");
|
const { openTab, getBrowserForTab, closeTab } = require("sdk/tabs/utils");
|
||||||
|
const self = require("sdk/self");
|
||||||
|
const { merge } = require("sdk/util/object");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A helper function that creates a PageMod, then opens the specified URL
|
* A helper function that creates a PageMod, then opens the specified URL
|
||||||
@ -31,7 +33,13 @@ exports.testPageMod = function testPageMod(assert, done, testURL, pageModOptions
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
let loader = Loader(module);
|
let loader = Loader(module, null, null, {
|
||||||
|
modules: {
|
||||||
|
"sdk/self": merge({}, self, {
|
||||||
|
data: merge({}, self.data, require("./fixtures"))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
});
|
||||||
let pageMod = loader.require("sdk/page-mod");
|
let pageMod = loader.require("sdk/page-mod");
|
||||||
|
|
||||||
var pageMods = [new pageMod.PageMod(opts) for each(opts in pageModOptions)];
|
var pageMods = [new pageMod.PageMod(opts) for each(opts in pageModOptions)];
|
||||||
|
@ -12,13 +12,13 @@ exports['test:contentURL'] = function(assert) {
|
|||||||
let loader = Loader(),
|
let loader = Loader(),
|
||||||
value, emitted = 0, changes = 0;
|
value, emitted = 0, changes = 0;
|
||||||
|
|
||||||
assert.throws(
|
assert.throws(() =>
|
||||||
function() loader.contentURL = 4,
|
loader.contentURL = 4,
|
||||||
/The `contentURL` option must be a valid URL./,
|
/The `contentURL` option must be a valid URL./,
|
||||||
'Must throw an exception if `contentURL` is not URL.'
|
'Must throw an exception if `contentURL` is not URL.'
|
||||||
);
|
);
|
||||||
assert.throws(
|
assert.throws(() =>
|
||||||
function() loader.contentURL = { toString: function() 'Oops' },
|
loader.contentURL = { toString: function() 'Oops' },
|
||||||
/The `contentURL` option must be a valid URL./,
|
/The `contentURL` option must be a valid URL./,
|
||||||
'Must throw an exception if `contentURL` is not URL.'
|
'Must throw an exception if `contentURL` is not URL.'
|
||||||
);
|
);
|
||||||
@ -78,6 +78,24 @@ exports['test:contentURL'] = function(assert) {
|
|||||||
'must not emit `propertyChange` if same value is set'
|
'must not emit `propertyChange` if same value is set'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
loader.contentURL = value = './index.html';
|
||||||
|
assert.equal(
|
||||||
|
value,
|
||||||
|
'' + loader.contentURL,
|
||||||
|
'value must be set'
|
||||||
|
);
|
||||||
|
assert.equal(
|
||||||
|
++ changes,
|
||||||
|
emitted,
|
||||||
|
'had to emit `propertyChange`'
|
||||||
|
);
|
||||||
|
loader.contentURL = value;
|
||||||
|
assert.equal(
|
||||||
|
changes,
|
||||||
|
emitted,
|
||||||
|
'must not emit `propertyChange` if same value is set'
|
||||||
|
);
|
||||||
|
|
||||||
loader.removeListener('propertyChange', listener);
|
loader.removeListener('propertyChange', listener);
|
||||||
loader.contentURL = value = 'about:blank';
|
loader.contentURL = value = 'about:blank';
|
||||||
assert.equal(
|
assert.equal(
|
||||||
@ -133,39 +151,37 @@ exports['test:contentScriptWhen'] = function(assert) {
|
|||||||
|
|
||||||
exports['test:contentScript'] = function(assert) {
|
exports['test:contentScript'] = function(assert) {
|
||||||
let loader = Loader(), value;
|
let loader = Loader(), value;
|
||||||
|
|
||||||
assert.equal(
|
assert.equal(
|
||||||
null,
|
null,
|
||||||
loader.contentScript,
|
loader.contentScript,
|
||||||
'`contentScript` defaults to `null`'
|
'`contentScript` defaults to `null`'
|
||||||
);
|
);
|
||||||
|
|
||||||
loader.contentScript = value = 'let test = {};';
|
loader.contentScript = value = 'let test = {};';
|
||||||
assert.equal(
|
assert.equal(
|
||||||
value,
|
value,
|
||||||
loader.contentScript
|
loader.contentScript
|
||||||
);
|
);
|
||||||
try {
|
|
||||||
loader.contentScript = { 1: value }
|
assert.throws(() =>
|
||||||
test.fail('must throw when wrong value is set');
|
loader.contentScript = { 1: value },
|
||||||
} catch(e) {
|
/The `contentScript` option must be a string or an array of strings/,
|
||||||
assert.equal(
|
'must throw when wrong value is set'
|
||||||
'The `contentScript` option must be a string or an array of strings.',
|
);
|
||||||
e.message
|
|
||||||
);
|
assert.throws(() =>
|
||||||
}
|
loader.contentScript = ['oue', 2],
|
||||||
try {
|
/The `contentScript` option must be a string or an array of strings/,
|
||||||
loader.contentScript = ['oue', 2]
|
'must throw when wrong value is set'
|
||||||
test.fail('must throw when wrong value is set');
|
);
|
||||||
} catch(e) {
|
|
||||||
assert.equal(
|
|
||||||
'The `contentScript` option must be a string or an array of strings.',
|
|
||||||
e.message
|
|
||||||
);
|
|
||||||
}
|
|
||||||
loader.contentScript = undefined;
|
loader.contentScript = undefined;
|
||||||
assert.equal(
|
assert.equal(
|
||||||
null,
|
null,
|
||||||
loader.contentScript
|
loader.contentScript
|
||||||
);
|
);
|
||||||
|
|
||||||
loader.contentScript = value = ["1;", "2;"];
|
loader.contentScript = value = ["1;", "2;"];
|
||||||
assert.equal(
|
assert.equal(
|
||||||
value,
|
value,
|
||||||
@ -185,36 +201,25 @@ exports['test:contentScriptFile'] = function(assert) {
|
|||||||
value,
|
value,
|
||||||
loader.contentScriptFile
|
loader.contentScriptFile
|
||||||
);
|
);
|
||||||
try {
|
|
||||||
loader.contentScriptFile = { 1: uri }
|
|
||||||
test.fail('must throw when wrong value is set');
|
|
||||||
} catch(e) {
|
|
||||||
assert.equal(
|
|
||||||
'The `contentScriptFile` option must be a local URL or an array of URLs.',
|
|
||||||
e.message
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
assert.throws(() =>
|
||||||
loader.contentScriptFile = [ 'oue', uri ]
|
loader.contentScriptFile = { 1: uri },
|
||||||
test.fail('must throw when wrong value is set');
|
/The `contentScriptFile` option must be a local URL or an array of URLs/,
|
||||||
} catch(e) {
|
'must throw when wrong value is set'
|
||||||
assert.equal(
|
);
|
||||||
'The `contentScriptFile` option must be a local URL or an array of URLs.',
|
|
||||||
e.message
|
assert.throws(() =>
|
||||||
);
|
loader.contentScriptFile = [ 'oue', uri ],
|
||||||
}
|
/The `contentScriptFile` option must be a local URL or an array of URLs/,
|
||||||
|
'must throw when wrong value is set'
|
||||||
|
);
|
||||||
|
|
||||||
let data = 'data:text/html,test';
|
let data = 'data:text/html,test';
|
||||||
try {
|
assert.throws(() =>
|
||||||
loader.contentScriptFile = [ { toString: () => data } ];
|
loader.contentScriptFile = [ { toString: () => data } ],
|
||||||
test.fail('must throw when non-URL object is set');
|
/The `contentScriptFile` option must be a local URL or an array of URLs/,
|
||||||
} catch(e) {
|
'must throw when wrong value is set'
|
||||||
assert.equal(
|
);
|
||||||
'The `contentScriptFile` option must be a local URL or an array of URLs.',
|
|
||||||
e.message
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
loader.contentScriptFile = new URL(data);
|
loader.contentScriptFile = new URL(data);
|
||||||
assert.ok(
|
assert.ok(
|
||||||
@ -222,11 +227,18 @@ exports['test:contentScriptFile'] = function(assert) {
|
|||||||
'must be able to set `contentScriptFile` to an instance of URL'
|
'must be able to set `contentScriptFile` to an instance of URL'
|
||||||
);
|
);
|
||||||
assert.equal(
|
assert.equal(
|
||||||
data,
|
data,
|
||||||
loader.contentScriptFile.toString(),
|
loader.contentScriptFile.toString(),
|
||||||
'setting `contentScriptFile` to an instance of URL should preserve the url'
|
'setting `contentScriptFile` to an instance of URL should preserve the url'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
loader.contentScriptFile = './index.html';
|
||||||
|
assert.equal(
|
||||||
|
'./index.html',
|
||||||
|
loader.contentScriptFile,
|
||||||
|
'setting `contentScriptFile` to relative path is allowed'
|
||||||
|
);
|
||||||
|
|
||||||
loader.contentScriptFile = undefined;
|
loader.contentScriptFile = undefined;
|
||||||
assert.equal(
|
assert.equal(
|
||||||
null,
|
null,
|
||||||
|
@ -879,6 +879,10 @@ exports.testContentContextMatchString = function (assert, done) {
|
|||||||
exports.testContentScriptFile = function (assert, done) {
|
exports.testContentScriptFile = function (assert, done) {
|
||||||
let test = new TestHelper(assert, done);
|
let test = new TestHelper(assert, done);
|
||||||
let loader = test.newLoader();
|
let loader = test.newLoader();
|
||||||
|
let { defer, all } = require("sdk/core/promise");
|
||||||
|
let itemScript = [defer(), defer()];
|
||||||
|
let menuShown = defer();
|
||||||
|
let menuPromises = itemScript.concat(menuShown).map(({promise}) => promise);
|
||||||
|
|
||||||
// Reject remote files
|
// Reject remote files
|
||||||
assert.throws(function() {
|
assert.throws(function() {
|
||||||
@ -887,20 +891,37 @@ exports.testContentScriptFile = function (assert, done) {
|
|||||||
contentScriptFile: "http://mozilla.com/context-menu.js"
|
contentScriptFile: "http://mozilla.com/context-menu.js"
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
new RegExp("The 'contentScriptFile' option must be a local file URL " +
|
/The `contentScriptFile` option must be a local URL or an array of URLs/,
|
||||||
"or an array of local file URLs."),
|
|
||||||
"Item throws when contentScriptFile is a remote URL");
|
"Item throws when contentScriptFile is a remote URL");
|
||||||
|
|
||||||
// But accept files from data folder
|
// But accept files from data folder
|
||||||
let item = new loader.cm.Item({
|
let item = new loader.cm.Item({
|
||||||
label: "item",
|
label: "item",
|
||||||
contentScriptFile: data.url("test-context-menu.js")
|
contentScriptFile: data.url("test-contentScriptFile.js"),
|
||||||
|
onMessage: (message) => {
|
||||||
|
assert.equal(message, "msg from contentScriptFile",
|
||||||
|
"contentScriptFile loaded with absolute url");
|
||||||
|
itemScript[0].resolve();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
test.showMenu(null, function (popup) {
|
let item2 = new loader.cm.Item({
|
||||||
test.checkMenu([item], [], []);
|
label: "item2",
|
||||||
test.done();
|
contentScriptFile: "./test-contentScriptFile.js",
|
||||||
|
onMessage: (message) => {
|
||||||
|
assert.equal(message, "msg from contentScriptFile",
|
||||||
|
"contentScriptFile loaded with relative url");
|
||||||
|
itemScript[1].resolve();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
console.log(item.contentScriptFile, item2.contentScriptFile);
|
||||||
|
|
||||||
|
test.showMenu(null, function (popup) {
|
||||||
|
test.checkMenu([item, item2], [], []);
|
||||||
|
menuShown.resolve();
|
||||||
|
});
|
||||||
|
|
||||||
|
all(menuPromises).then(() => test.done());
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -3944,7 +3965,15 @@ TestHelper.prototype = {
|
|||||||
// function that unloads the loader and associated resources.
|
// function that unloads the loader and associated resources.
|
||||||
newLoader: function () {
|
newLoader: function () {
|
||||||
const self = this;
|
const self = this;
|
||||||
let loader = Loader(module);
|
const selfModule = require('sdk/self');
|
||||||
|
let loader = Loader(module, null, null, {
|
||||||
|
modules: {
|
||||||
|
"sdk/self": merge({}, selfModule, {
|
||||||
|
data: merge({}, selfModule.data, require("./fixtures"))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
let wrapper = {
|
let wrapper = {
|
||||||
loader: loader,
|
loader: loader,
|
||||||
cm: loader.require("sdk/context-menu"),
|
cm: loader.require("sdk/context-menu"),
|
||||||
|
236
addon-sdk/source/test/test-dev-panel.js
Normal file
236
addon-sdk/source/test/test-dev-panel.js
Normal file
File diff suppressed because one or more lines are too long
@ -1,6 +1,7 @@
|
|||||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
/* 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
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
"use strict";
|
||||||
|
|
||||||
const { getRulesForLocale } = require("sdk/l10n/plural-rules");
|
const { getRulesForLocale } = require("sdk/l10n/plural-rules");
|
||||||
|
|
||||||
|
@ -1028,20 +1028,20 @@ exports.testPageModCss = function(assert, done) {
|
|||||||
'data:text/html;charset=utf-8,<div style="background: silver">css test</div>', [{
|
'data:text/html;charset=utf-8,<div style="background: silver">css test</div>', [{
|
||||||
include: ["*", "data:*"],
|
include: ["*", "data:*"],
|
||||||
contentStyle: "div { height: 100px; }",
|
contentStyle: "div { height: 100px; }",
|
||||||
contentStyleFile: data.url("css-include-file.css")
|
contentStyleFile: [data.url("include-file.css"), "./border-style.css"]
|
||||||
}],
|
}],
|
||||||
function(win, done) {
|
function(win, done) {
|
||||||
let div = win.document.querySelector("div");
|
let div = win.document.querySelector("div");
|
||||||
assert.equal(
|
|
||||||
div.clientHeight,
|
assert.equal(div.clientHeight, 100,
|
||||||
100,
|
"PageMod contentStyle worked");
|
||||||
"PageMod contentStyle worked"
|
|
||||||
);
|
assert.equal(div.offsetHeight, 120,
|
||||||
assert.equal(
|
"PageMod contentStyleFile worked");
|
||||||
div.offsetHeight,
|
|
||||||
120,
|
assert.equal(win.getComputedStyle(div).borderTopStyle, "dashed",
|
||||||
"PageMod contentStyleFile worked"
|
"PageMod contentStyleFile with relative path worked");
|
||||||
);
|
|
||||||
done();
|
done();
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@ -1165,6 +1165,21 @@ exports.testPageModCssAutomaticDestroy = function(assert, done) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
exports.testPageModContentScriptFile = function(assert, done) {
|
||||||
|
|
||||||
|
testPageMod(assert, done, "about:license", [{
|
||||||
|
include: "about:*",
|
||||||
|
contentScriptWhen: "start",
|
||||||
|
contentScriptFile: "./test-contentScriptFile.js",
|
||||||
|
onMessage: message => {
|
||||||
|
assert.equal(message, "msg from contentScriptFile",
|
||||||
|
"PageMod contentScriptFile with relative path worked");
|
||||||
|
}
|
||||||
|
}],
|
||||||
|
(win, done) => done()
|
||||||
|
);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
exports.testPageModTimeout = function(assert, done) {
|
exports.testPageModTimeout = function(assert, done) {
|
||||||
let tab = null
|
let tab = null
|
||||||
|
@ -268,6 +268,33 @@ exports.testLoadContentPage = function(assert, done) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exports.testLoadContentPageRelativePath = function(assert, done) {
|
||||||
|
const self = require("sdk/self");
|
||||||
|
const { merge } = require("sdk/util/object");
|
||||||
|
|
||||||
|
let loader = Loader(module, null, null, {
|
||||||
|
modules: {
|
||||||
|
"sdk/self": merge({}, self, {
|
||||||
|
data: merge({}, self.data, fixtures)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let page = loader.require("sdk/page-worker").Page({
|
||||||
|
onMessage: function(message) {
|
||||||
|
// The message is an array whose first item is the test method to call
|
||||||
|
// and the rest of whose items are arguments to pass it.
|
||||||
|
let msg = message.shift();
|
||||||
|
if (msg == "done")
|
||||||
|
return done();
|
||||||
|
assert[msg].apply(assert, message);
|
||||||
|
},
|
||||||
|
contentURL: "./test-page-worker.html",
|
||||||
|
contentScriptFile: "./test-page-worker.js",
|
||||||
|
contentScriptWhen: "ready"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
exports.testAllowScriptDefault = function(assert, done) {
|
exports.testAllowScriptDefault = function(assert, done) {
|
||||||
let page = Page({
|
let page = Page({
|
||||||
onMessage: function(message) {
|
onMessage: function(message) {
|
||||||
|
@ -27,7 +27,6 @@ const { wait } = require('./event/helpers');
|
|||||||
const fixtures = require('./fixtures')
|
const fixtures = require('./fixtures')
|
||||||
|
|
||||||
const SVG_URL = fixtures.url('mofo_logo.SVG');
|
const SVG_URL = fixtures.url('mofo_logo.SVG');
|
||||||
const CSS_URL = fixtures.url('css-include-file.css');
|
|
||||||
|
|
||||||
const Isolate = fn => '(' + fn + ')()';
|
const Isolate = fn => '(' + fn + ')()';
|
||||||
|
|
||||||
@ -979,7 +978,16 @@ exports['test panel can be constructed without any arguments'] = function (asser
|
|||||||
};
|
};
|
||||||
|
|
||||||
exports['test panel CSS'] = function(assert, done) {
|
exports['test panel CSS'] = function(assert, done) {
|
||||||
const loader = Loader(module);
|
const { merge } = require("sdk/util/object");
|
||||||
|
|
||||||
|
let loader = Loader(module, null, null, {
|
||||||
|
modules: {
|
||||||
|
"sdk/self": merge({}, self, {
|
||||||
|
data: merge({}, self.data, fixtures)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
const { Panel } = loader.require('sdk/panel');
|
const { Panel } = loader.require('sdk/panel');
|
||||||
|
|
||||||
const { getActiveView } = loader.require('sdk/view/core');
|
const { getActiveView } = loader.require('sdk/view/core');
|
||||||
@ -991,13 +999,19 @@ exports['test panel CSS'] = function(assert, done) {
|
|||||||
contentURL: 'data:text/html;charset=utf-8,' +
|
contentURL: 'data:text/html;charset=utf-8,' +
|
||||||
'<div style="background: silver">css test</div>',
|
'<div style="background: silver">css test</div>',
|
||||||
contentStyle: 'div { height: 100px; }',
|
contentStyle: 'div { height: 100px; }',
|
||||||
contentStyleFile: CSS_URL,
|
contentStyleFile: [fixtures.url("include-file.css"), "./border-style.css"],
|
||||||
onShow: () => {
|
onShow: () => {
|
||||||
ready(getContentWindow(panel)).then(({ document }) => {
|
ready(getContentWindow(panel)).then(({ window, document }) => {
|
||||||
let div = document.querySelector('div');
|
let div = document.querySelector('div');
|
||||||
|
|
||||||
assert.equal(div.clientHeight, 100, 'Panel contentStyle worked');
|
assert.equal(div.clientHeight, 100,
|
||||||
assert.equal(div.offsetHeight, 120, 'Panel contentStyleFile worked');
|
"Panel contentStyle worked");
|
||||||
|
|
||||||
|
assert.equal(div.offsetHeight, 120,
|
||||||
|
"Panel contentStyleFile worked");
|
||||||
|
|
||||||
|
assert.equal(window.getComputedStyle(div).borderTopStyle, "dashed",
|
||||||
|
"Panel contentStyleFile with relative path worked");
|
||||||
|
|
||||||
loader.unload();
|
loader.unload();
|
||||||
done();
|
done();
|
||||||
@ -1008,6 +1022,53 @@ exports['test panel CSS'] = function(assert, done) {
|
|||||||
panel.show();
|
panel.show();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
exports['test panel contentScriptFile'] = function(assert, done) {
|
||||||
|
const { merge } = require("sdk/util/object");
|
||||||
|
|
||||||
|
let loader = Loader(module, null, null, {
|
||||||
|
modules: {
|
||||||
|
"sdk/self": merge({}, self, {
|
||||||
|
data: merge({}, self.data, {url: fixtures.url})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const { Panel } = loader.require('sdk/panel');
|
||||||
|
const { getActiveView } = loader.require('sdk/view/core');
|
||||||
|
|
||||||
|
const getContentWindow = panel =>
|
||||||
|
getActiveView(panel).querySelector('iframe').contentWindow;
|
||||||
|
|
||||||
|
let whenMessage = defer();
|
||||||
|
let whenShown = defer();
|
||||||
|
|
||||||
|
let panel = Panel({
|
||||||
|
contentURL: './test.html',
|
||||||
|
contentScriptFile: "./test-contentScriptFile.js",
|
||||||
|
onMessage: (message) => {
|
||||||
|
assert.equal(message, "msg from contentScriptFile",
|
||||||
|
"Panel contentScriptFile with relative path worked");
|
||||||
|
|
||||||
|
whenMessage.resolve();
|
||||||
|
},
|
||||||
|
onShow: () => {
|
||||||
|
ready(getContentWindow(panel)).then(({ document }) => {
|
||||||
|
assert.equal(document.title, 'foo',
|
||||||
|
"Panel contentURL with relative path worked");
|
||||||
|
|
||||||
|
whenShown.resolve();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
all([whenMessage.promise, whenShown.promise]).
|
||||||
|
then(loader.unload).
|
||||||
|
then(done, assert.fail);
|
||||||
|
|
||||||
|
panel.show();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
exports['test panel CSS list'] = function(assert, done) {
|
exports['test panel CSS list'] = function(assert, done) {
|
||||||
const loader = Loader(module);
|
const loader = Loader(module);
|
||||||
const { Panel } = loader.require('sdk/panel');
|
const { Panel } = loader.require('sdk/panel');
|
||||||
@ -1186,6 +1247,36 @@ exports['test panel contextmenu disabled'] = function*(assert) {
|
|||||||
assert.equal(contextmenu.state, 'closed',
|
assert.equal(contextmenu.state, 'closed',
|
||||||
'contextmenu was never open');
|
'contextmenu was never open');
|
||||||
|
|
||||||
|
loader.unload();
|
||||||
|
}
|
||||||
|
|
||||||
|
exports["test panel addon global object"] = function*(assert) {
|
||||||
|
const { merge } = require("sdk/util/object");
|
||||||
|
|
||||||
|
let loader = Loader(module, null, null, {
|
||||||
|
modules: {
|
||||||
|
"sdk/self": merge({}, self, {
|
||||||
|
data: merge({}, self.data, {url: fixtures.url})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const { Panel } = loader.require('sdk/panel');
|
||||||
|
|
||||||
|
let panel = Panel({
|
||||||
|
contentURL: "./test-trusted-document.html"
|
||||||
|
});
|
||||||
|
|
||||||
|
panel.show();
|
||||||
|
|
||||||
|
yield wait(panel, "show");
|
||||||
|
|
||||||
|
panel.port.emit('addon-to-document', 'ok');
|
||||||
|
|
||||||
|
yield wait(panel.port, "document-to-addon");
|
||||||
|
|
||||||
|
assert.pass("Received an event from the document");
|
||||||
|
|
||||||
loader.unload();
|
loader.unload();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,6 +40,38 @@ exports.testTabCounts = function(assert, done) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
exports.testTabRelativePath = function(assert, done) {
|
||||||
|
const { merge } = require("sdk/util/object");
|
||||||
|
const self = require("sdk/self");
|
||||||
|
|
||||||
|
let loader = Loader(module, null, null, {
|
||||||
|
modules: {
|
||||||
|
"sdk/self": merge({}, self, {
|
||||||
|
data: merge({}, self.data, require("./fixtures"))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let tabs = loader.require("sdk/tabs");
|
||||||
|
|
||||||
|
tabs.open({
|
||||||
|
url: "./test.html",
|
||||||
|
onReady: (tab) => {
|
||||||
|
assert.equal(tab.title, "foo",
|
||||||
|
"tab opened a document with relative path");
|
||||||
|
|
||||||
|
tab.attach({
|
||||||
|
contentScriptFile: "./test-contentScriptFile.js",
|
||||||
|
onMessage: (message) => {
|
||||||
|
assert.equal(message, "msg from contentScriptFile",
|
||||||
|
"Tab attach a contentScriptFile with relative path worked");
|
||||||
|
|
||||||
|
tab.close(done);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
// TEST: tabs.activeTab getter
|
// TEST: tabs.activeTab getter
|
||||||
exports.testActiveTab_getter = function(assert, done) {
|
exports.testActiveTab_getter = function(assert, done) {
|
||||||
|
@ -370,6 +370,48 @@ exports.testSidebarUnload = function(assert, done) {
|
|||||||
assert.pass('showing the sidebar');
|
assert.pass('showing the sidebar');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exports.testRelativeURL = function(assert, done) {
|
||||||
|
const { merge } = require('sdk/util/object');
|
||||||
|
const self = require('sdk/self');
|
||||||
|
|
||||||
|
let loader = Loader(module, null, null, {
|
||||||
|
modules: {
|
||||||
|
'sdk/self': merge({}, self, {
|
||||||
|
data: merge({}, self.data, require('./fixtures'))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const { Sidebar } = loader.require('sdk/ui/sidebar');
|
||||||
|
|
||||||
|
let testName = 'testRelativeURL';
|
||||||
|
let sidebar = Sidebar({
|
||||||
|
id: testName,
|
||||||
|
title: testName,
|
||||||
|
url: './test-sidebar-addon-global.html'
|
||||||
|
});
|
||||||
|
|
||||||
|
sidebar.on('attach', function(worker) {
|
||||||
|
assert.pass('sidebar was attached');
|
||||||
|
assert.ok(!!worker, 'attach event has worker');
|
||||||
|
|
||||||
|
worker.port.once('Y', function(msg) {
|
||||||
|
assert.equal(msg, '1', 'got event from worker');
|
||||||
|
|
||||||
|
worker.port.on('X', function(msg) {
|
||||||
|
assert.equal(msg, '123', 'the final message is correct');
|
||||||
|
|
||||||
|
sidebar.destroy();
|
||||||
|
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
worker.port.emit('X', msg + '2');
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
sidebar.show();
|
||||||
|
}
|
||||||
|
|
||||||
exports.testRemoteContent = function(assert) {
|
exports.testRemoteContent = function(assert) {
|
||||||
const { Sidebar } = require('sdk/ui/sidebar');
|
const { Sidebar } = require('sdk/ui/sidebar');
|
||||||
let testName = 'testRemoteContent';
|
let testName = 'testRemoteContent';
|
||||||
|
@ -36,8 +36,6 @@ function openNewWindowTab(url, options) {
|
|||||||
if (options.onLoad) {
|
if (options.onLoad) {
|
||||||
options.onLoad({ target: { defaultView: window } })
|
options.onLoad({ target: { defaultView: window } })
|
||||||
}
|
}
|
||||||
|
|
||||||
return newTab;
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -538,7 +536,7 @@ exports.testConstructor = function(assert, done) {
|
|||||||
assert.equal(widgetCount2(), widgetStartCount2, "2nd window has correct number of child elements after second destroy");
|
assert.equal(widgetCount2(), widgetStartCount2, "2nd window has correct number of child elements after second destroy");
|
||||||
|
|
||||||
close(browserWindow).then(doneTest);
|
close(browserWindow).then(doneTest);
|
||||||
}});
|
}}).catch(assert.fail);
|
||||||
});
|
});
|
||||||
|
|
||||||
// test window closing
|
// test window closing
|
||||||
@ -634,7 +632,7 @@ exports.testConstructor = function(assert, done) {
|
|||||||
browserWindow.setToolbarVisibility(container(), true);
|
browserWindow.setToolbarVisibility(container(), true);
|
||||||
|
|
||||||
close(browserWindow2).then(doneTest);
|
close(browserWindow2).then(doneTest);
|
||||||
}});
|
}}).catch(assert.fail);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1179,7 +1177,7 @@ exports.testReinsertion = function(assert, done) {
|
|||||||
loader.unload();
|
loader.unload();
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
}});
|
}}).catch(assert.fail);
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.testWideWidget = function testWideWidget(assert) {
|
exports.testWideWidget = function testWideWidget(assert) {
|
||||||
|
@ -42,6 +42,33 @@ exports.testOpenAndCloseWindow = function(assert, done) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
exports.testOpenRelativePathWindow = function(assert, done) {
|
||||||
|
assert.equal(browserWindows.length, 1, "Only one window open");
|
||||||
|
|
||||||
|
const { merge } = require("sdk/util/object");
|
||||||
|
const self = require("sdk/self");
|
||||||
|
|
||||||
|
let loader = Loader(module, null, null, {
|
||||||
|
modules: {
|
||||||
|
"sdk/self": merge({}, self, {
|
||||||
|
data: merge({}, self.data, require("./../fixtures"))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
loader.require("sdk/windows").browserWindows.open({
|
||||||
|
url: "./test.html",
|
||||||
|
onOpen: (window) => {
|
||||||
|
window.tabs.activeTab.once("ready", (tab) => {
|
||||||
|
assert.equal(tab.title, "foo",
|
||||||
|
"tab opened a document with relative path");
|
||||||
|
|
||||||
|
window.close(done);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
exports.testAutomaticDestroy = function(assert, done) {
|
exports.testAutomaticDestroy = function(assert, done) {
|
||||||
let windows = browserWindows;
|
let windows = browserWindows;
|
||||||
|
|
||||||
|
@ -19,13 +19,13 @@
|
|||||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||||
</project>
|
</project>
|
||||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="1c9eb3d16167c2e5a9f7789eb46ee17830e6054e"/>
|
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="649245c238a043af32acb109b2613f578323f8e1"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7f792d756385bb894fba7645da59c67fe2c804bf"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7f792d756385bb894fba7645da59c67fe2c804bf"/>
|
||||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/>
|
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/>
|
||||||
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="227354333a185180b85471f2cc6abfb029e44718"/>
|
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="227354333a185180b85471f2cc6abfb029e44718"/>
|
||||||
<project name="moztt" path="external/moztt" remote="b2g" revision="dc5ca96695cab87b4c2fcd7c9f046ae3415a70a5"/>
|
<project name="moztt" path="external/moztt" remote="b2g" revision="dc5ca96695cab87b4c2fcd7c9f046ae3415a70a5"/>
|
||||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="8b04b5aca4b0a894de40f4d53ae9750222d349a8"/>
|
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="31215645c296ba7a62bcb3176f69e0014ab9be07"/>
|
||||||
<!-- Stock Android things -->
|
<!-- Stock Android things -->
|
||||||
<project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
|
<project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
|
||||||
<project name="platform/bionic" path="bionic" revision="c72b8f6359de7ed17c11ddc9dfdde3f615d188a9"/>
|
<project name="platform/bionic" path="bionic" revision="c72b8f6359de7ed17c11ddc9dfdde3f615d188a9"/>
|
||||||
|
@ -17,10 +17,10 @@
|
|||||||
</project>
|
</project>
|
||||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="1c9eb3d16167c2e5a9f7789eb46ee17830e6054e"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="649245c238a043af32acb109b2613f578323f8e1"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7f792d756385bb894fba7645da59c67fe2c804bf"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7f792d756385bb894fba7645da59c67fe2c804bf"/>
|
||||||
<project name="moztt" path="external/moztt" remote="b2g" revision="dc5ca96695cab87b4c2fcd7c9f046ae3415a70a5"/>
|
<project name="moztt" path="external/moztt" remote="b2g" revision="dc5ca96695cab87b4c2fcd7c9f046ae3415a70a5"/>
|
||||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="8b04b5aca4b0a894de40f4d53ae9750222d349a8"/>
|
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="31215645c296ba7a62bcb3176f69e0014ab9be07"/>
|
||||||
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
|
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
|
||||||
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
|
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
|
||||||
<!-- Stock Android things -->
|
<!-- Stock Android things -->
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
<project name="platform_build" path="build" remote="b2g" revision="276ce45e78b09c4a4ee643646f691d22804754c1">
|
<project name="platform_build" path="build" remote="b2g" revision="276ce45e78b09c4a4ee643646f691d22804754c1">
|
||||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||||
</project>
|
</project>
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="1c9eb3d16167c2e5a9f7789eb46ee17830e6054e"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="649245c238a043af32acb109b2613f578323f8e1"/>
|
||||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7f792d756385bb894fba7645da59c67fe2c804bf"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7f792d756385bb894fba7645da59c67fe2c804bf"/>
|
||||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||||
@ -23,7 +23,7 @@
|
|||||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||||
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
|
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
|
||||||
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
|
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
|
||||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="8b04b5aca4b0a894de40f4d53ae9750222d349a8"/>
|
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="31215645c296ba7a62bcb3176f69e0014ab9be07"/>
|
||||||
<!-- Stock Android things -->
|
<!-- Stock Android things -->
|
||||||
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="f92a936f2aa97526d4593386754bdbf02db07a12"/>
|
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="f92a936f2aa97526d4593386754bdbf02db07a12"/>
|
||||||
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="6e47ff2790f5656b5b074407829ceecf3e6188c4"/>
|
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="6e47ff2790f5656b5b074407829ceecf3e6188c4"/>
|
||||||
|
@ -19,13 +19,13 @@
|
|||||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||||
</project>
|
</project>
|
||||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="1c9eb3d16167c2e5a9f7789eb46ee17830e6054e"/>
|
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="649245c238a043af32acb109b2613f578323f8e1"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7f792d756385bb894fba7645da59c67fe2c804bf"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7f792d756385bb894fba7645da59c67fe2c804bf"/>
|
||||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/>
|
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/>
|
||||||
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="227354333a185180b85471f2cc6abfb029e44718"/>
|
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="227354333a185180b85471f2cc6abfb029e44718"/>
|
||||||
<project name="moztt" path="external/moztt" remote="b2g" revision="dc5ca96695cab87b4c2fcd7c9f046ae3415a70a5"/>
|
<project name="moztt" path="external/moztt" remote="b2g" revision="dc5ca96695cab87b4c2fcd7c9f046ae3415a70a5"/>
|
||||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="8b04b5aca4b0a894de40f4d53ae9750222d349a8"/>
|
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="31215645c296ba7a62bcb3176f69e0014ab9be07"/>
|
||||||
<!-- Stock Android things -->
|
<!-- Stock Android things -->
|
||||||
<project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
|
<project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
|
||||||
<project name="platform/bionic" path="bionic" revision="c72b8f6359de7ed17c11ddc9dfdde3f615d188a9"/>
|
<project name="platform/bionic" path="bionic" revision="c72b8f6359de7ed17c11ddc9dfdde3f615d188a9"/>
|
||||||
|
@ -17,10 +17,10 @@
|
|||||||
</project>
|
</project>
|
||||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="1c9eb3d16167c2e5a9f7789eb46ee17830e6054e"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="649245c238a043af32acb109b2613f578323f8e1"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7f792d756385bb894fba7645da59c67fe2c804bf"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7f792d756385bb894fba7645da59c67fe2c804bf"/>
|
||||||
<project name="moztt" path="external/moztt" remote="b2g" revision="dc5ca96695cab87b4c2fcd7c9f046ae3415a70a5"/>
|
<project name="moztt" path="external/moztt" remote="b2g" revision="dc5ca96695cab87b4c2fcd7c9f046ae3415a70a5"/>
|
||||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="8b04b5aca4b0a894de40f4d53ae9750222d349a8"/>
|
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="31215645c296ba7a62bcb3176f69e0014ab9be07"/>
|
||||||
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
|
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
|
||||||
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
|
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
|
||||||
<!-- Stock Android things -->
|
<!-- Stock Android things -->
|
||||||
|
@ -4,6 +4,6 @@
|
|||||||
"remote": "",
|
"remote": "",
|
||||||
"branch": ""
|
"branch": ""
|
||||||
},
|
},
|
||||||
"revision": "cea1598e51f188fe8c48196cbb2c73aacbf3b1dc",
|
"revision": "591c866cb04a88306e472c873429669229f28540",
|
||||||
"repo_path": "/integration/gaia-central"
|
"repo_path": "/integration/gaia-central"
|
||||||
}
|
}
|
||||||
|
@ -17,12 +17,12 @@
|
|||||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||||
</project>
|
</project>
|
||||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="1c9eb3d16167c2e5a9f7789eb46ee17830e6054e"/>
|
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="649245c238a043af32acb109b2613f578323f8e1"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7f792d756385bb894fba7645da59c67fe2c804bf"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7f792d756385bb894fba7645da59c67fe2c804bf"/>
|
||||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||||
<project name="moztt" path="external/moztt" remote="b2g" revision="dc5ca96695cab87b4c2fcd7c9f046ae3415a70a5"/>
|
<project name="moztt" path="external/moztt" remote="b2g" revision="dc5ca96695cab87b4c2fcd7c9f046ae3415a70a5"/>
|
||||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="8b04b5aca4b0a894de40f4d53ae9750222d349a8"/>
|
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="31215645c296ba7a62bcb3176f69e0014ab9be07"/>
|
||||||
<!-- Stock Android things -->
|
<!-- Stock Android things -->
|
||||||
<project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
|
<project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
|
||||||
<project name="platform/bionic" path="bionic" revision="d2eb6c7b6e1bc7643c17df2d9d9bcb1704d0b9ab"/>
|
<project name="platform/bionic" path="bionic" revision="d2eb6c7b6e1bc7643c17df2d9d9bcb1704d0b9ab"/>
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||||
</project>
|
</project>
|
||||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="1c9eb3d16167c2e5a9f7789eb46ee17830e6054e"/>
|
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="649245c238a043af32acb109b2613f578323f8e1"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7f792d756385bb894fba7645da59c67fe2c804bf"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7f792d756385bb894fba7645da59c67fe2c804bf"/>
|
||||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||||
|
@ -17,10 +17,10 @@
|
|||||||
</project>
|
</project>
|
||||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="1c9eb3d16167c2e5a9f7789eb46ee17830e6054e"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="649245c238a043af32acb109b2613f578323f8e1"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7f792d756385bb894fba7645da59c67fe2c804bf"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7f792d756385bb894fba7645da59c67fe2c804bf"/>
|
||||||
<project name="moztt" path="external/moztt" remote="b2g" revision="dc5ca96695cab87b4c2fcd7c9f046ae3415a70a5"/>
|
<project name="moztt" path="external/moztt" remote="b2g" revision="dc5ca96695cab87b4c2fcd7c9f046ae3415a70a5"/>
|
||||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="8b04b5aca4b0a894de40f4d53ae9750222d349a8"/>
|
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="31215645c296ba7a62bcb3176f69e0014ab9be07"/>
|
||||||
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
|
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
|
||||||
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
|
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
|
||||||
<!-- Stock Android things -->
|
<!-- Stock Android things -->
|
||||||
|
@ -17,12 +17,12 @@
|
|||||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||||
</project>
|
</project>
|
||||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="1c9eb3d16167c2e5a9f7789eb46ee17830e6054e"/>
|
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="649245c238a043af32acb109b2613f578323f8e1"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7f792d756385bb894fba7645da59c67fe2c804bf"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7f792d756385bb894fba7645da59c67fe2c804bf"/>
|
||||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||||
<project name="moztt" path="external/moztt" remote="b2g" revision="dc5ca96695cab87b4c2fcd7c9f046ae3415a70a5"/>
|
<project name="moztt" path="external/moztt" remote="b2g" revision="dc5ca96695cab87b4c2fcd7c9f046ae3415a70a5"/>
|
||||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="8b04b5aca4b0a894de40f4d53ae9750222d349a8"/>
|
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="31215645c296ba7a62bcb3176f69e0014ab9be07"/>
|
||||||
<project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
|
<project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
|
||||||
<!-- Stock Android things -->
|
<!-- Stock Android things -->
|
||||||
<project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
|
<project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
MOZ_APP_BASENAME=B2G
|
MOZ_APP_BASENAME=B2G
|
||||||
MOZ_APP_VENDOR=Mozilla
|
MOZ_APP_VENDOR=Mozilla
|
||||||
|
|
||||||
MOZ_APP_VERSION=33.0a1
|
MOZ_APP_VERSION=34.0a1
|
||||||
MOZ_APP_UA_NAME=Firefox
|
MOZ_APP_UA_NAME=Firefox
|
||||||
|
|
||||||
MOZ_UA_OS_AGNOSTIC=1
|
MOZ_UA_OS_AGNOSTIC=1
|
||||||
|
@ -70,7 +70,8 @@ this.Translation = {
|
|||||||
let trUI = aBrowser.translationUI;
|
let trUI = aBrowser.translationUI;
|
||||||
|
|
||||||
// Set all values before showing a new translation infobar.
|
// Set all values before showing a new translation infobar.
|
||||||
trUI._state = aData.state;
|
trUI._state = Translation.serviceUnavailable ? Translation.STATE_UNAVAILABLE
|
||||||
|
: aData.state;
|
||||||
trUI.detectedLanguage = aData.detectedLanguage;
|
trUI.detectedLanguage = aData.detectedLanguage;
|
||||||
trUI.translatedFrom = aData.translatedFrom;
|
trUI.translatedFrom = aData.translatedFrom;
|
||||||
trUI.translatedTo = aData.translatedTo;
|
trUI.translatedTo = aData.translatedTo;
|
||||||
@ -237,23 +238,6 @@ TranslationUI.prototype = {
|
|||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
|
|
||||||
showTranslationUI: function(aDetectedLanguage) {
|
|
||||||
this.detectedLanguage = aDetectedLanguage;
|
|
||||||
|
|
||||||
// Reset all values before showing a new translation infobar.
|
|
||||||
this.state = 0;
|
|
||||||
this.translatedFrom = "";
|
|
||||||
this.translatedTo = "";
|
|
||||||
this.originalShown = true;
|
|
||||||
|
|
||||||
this.showURLBarIcon();
|
|
||||||
|
|
||||||
if (!this.shouldShowInfoBar(this.browser.currentURI))
|
|
||||||
return null;
|
|
||||||
|
|
||||||
return this.showTranslationInfoBar();
|
|
||||||
},
|
|
||||||
|
|
||||||
receiveMessage: function(msg) {
|
receiveMessage: function(msg) {
|
||||||
switch (msg.name) {
|
switch (msg.name) {
|
||||||
case "Translation:Finished":
|
case "Translation:Finished":
|
||||||
|
@ -181,7 +181,7 @@
|
|||||||
if (aTranslation.translatedFrom)
|
if (aTranslation.translatedFrom)
|
||||||
fromLanguage.value = aTranslation.translatedFrom;
|
fromLanguage.value = aTranslation.translatedFrom;
|
||||||
|
|
||||||
// Fill the list of supporter target languages.
|
// Fill the list of supported target languages.
|
||||||
let toLanguage = this._getAnonElt("toLanguage");
|
let toLanguage = this._getAnonElt("toLanguage");
|
||||||
for (let code of Translation.supportedTargetLanguages)
|
for (let code of Translation.supportedTargetLanguages)
|
||||||
toLanguage.appendItem(bundle.GetStringFromName(code), code);
|
toLanguage.appendItem(bundle.GetStringFromName(code), code);
|
||||||
@ -263,8 +263,15 @@
|
|||||||
let lang;
|
let lang;
|
||||||
if (this.state == Translation.STATE_OFFER)
|
if (this.state == Translation.STATE_OFFER)
|
||||||
lang = this._getAnonElt("detectedLanguage").value;
|
lang = this._getAnonElt("detectedLanguage").value;
|
||||||
else
|
else {
|
||||||
lang = this._getAnonElt("fromLanguage").value;
|
lang = this._getAnonElt("fromLanguage").value;
|
||||||
|
|
||||||
|
// If we have never attempted to translate the page before the
|
||||||
|
// service became unavailable, "fromLanguage" isn't set.
|
||||||
|
if (!lang && this.state == Translation.STATE_UNAVAILABLE)
|
||||||
|
lang = this.translation.detectedLanguage;
|
||||||
|
}
|
||||||
|
|
||||||
let langBundle =
|
let langBundle =
|
||||||
Cc["@mozilla.org/intl/stringbundle;1"]
|
Cc["@mozilla.org/intl/stringbundle;1"]
|
||||||
.getService(Ci.nsIStringBundleService)
|
.getService(Ci.nsIStringBundleService)
|
||||||
|
@ -1 +1 @@
|
|||||||
33.0a1
|
34.0a1
|
||||||
|
@ -65,6 +65,7 @@ support-files =
|
|||||||
doc_large-array-buffer.html
|
doc_large-array-buffer.html
|
||||||
doc_minified.html
|
doc_minified.html
|
||||||
doc_minified_bogus_map.html
|
doc_minified_bogus_map.html
|
||||||
|
doc_native-event-handler.html
|
||||||
doc_no-page-sources.html
|
doc_no-page-sources.html
|
||||||
doc_pause-exceptions.html
|
doc_pause-exceptions.html
|
||||||
doc_pretty-print.html
|
doc_pretty-print.html
|
||||||
@ -155,6 +156,7 @@ skip-if = true # Bug 933950 (leaky test)
|
|||||||
[browser_dbg_editor-mode.js]
|
[browser_dbg_editor-mode.js]
|
||||||
[browser_dbg_event-listeners-01.js]
|
[browser_dbg_event-listeners-01.js]
|
||||||
[browser_dbg_event-listeners-02.js]
|
[browser_dbg_event-listeners-02.js]
|
||||||
|
[browser_dbg_event-listeners-03.js]
|
||||||
[browser_dbg_file-reload.js]
|
[browser_dbg_file-reload.js]
|
||||||
[browser_dbg_function-display-name.js]
|
[browser_dbg_function-display-name.js]
|
||||||
[browser_dbg_global-method-override.js]
|
[browser_dbg_global-method-override.js]
|
||||||
|
@ -0,0 +1,89 @@
|
|||||||
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that the eventListeners request works when there are event handlers
|
||||||
|
* that the debugger cannot unwrap.
|
||||||
|
*/
|
||||||
|
|
||||||
|
const TAB_URL = EXAMPLE_URL + "doc_native-event-handler.html";
|
||||||
|
|
||||||
|
let gClient;
|
||||||
|
|
||||||
|
function test() {
|
||||||
|
if (!DebuggerServer.initialized) {
|
||||||
|
DebuggerServer.init(() => true);
|
||||||
|
DebuggerServer.addBrowserActors();
|
||||||
|
}
|
||||||
|
|
||||||
|
let transport = DebuggerServer.connectPipe();
|
||||||
|
gClient = new DebuggerClient(transport);
|
||||||
|
gClient.connect((aType, aTraits) => {
|
||||||
|
is(aType, "browser",
|
||||||
|
"Root actor should identify itself as a browser.");
|
||||||
|
|
||||||
|
addTab(TAB_URL)
|
||||||
|
.then(() => attachThreadActorForUrl(gClient, TAB_URL))
|
||||||
|
.then(pauseDebuggee)
|
||||||
|
.then(testEventListeners)
|
||||||
|
.then(closeConnection)
|
||||||
|
.then(finish)
|
||||||
|
.then(null, aError => {
|
||||||
|
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function pauseDebuggee(aThreadClient) {
|
||||||
|
let deferred = promise.defer();
|
||||||
|
|
||||||
|
gClient.addOneTimeListener("paused", (aEvent, aPacket) => {
|
||||||
|
is(aPacket.type, "paused",
|
||||||
|
"We should now be paused.");
|
||||||
|
is(aPacket.why.type, "debuggerStatement",
|
||||||
|
"The debugger statement was hit.");
|
||||||
|
|
||||||
|
deferred.resolve(aThreadClient);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Spin the event loop before causing the debuggee to pause, to allow
|
||||||
|
// this function to return first.
|
||||||
|
executeSoon(() => {
|
||||||
|
EventUtils.sendMouseEvent({ type: "click" },
|
||||||
|
content.document.querySelector("button"),
|
||||||
|
content);
|
||||||
|
});
|
||||||
|
|
||||||
|
return deferred.promise;
|
||||||
|
}
|
||||||
|
|
||||||
|
function testEventListeners(aThreadClient) {
|
||||||
|
let deferred = promise.defer();
|
||||||
|
|
||||||
|
aThreadClient.eventListeners(aPacket => {
|
||||||
|
if (aPacket.error) {
|
||||||
|
let msg = "Error getting event listeners: " + aPacket.message;
|
||||||
|
ok(false, msg);
|
||||||
|
deferred.reject(msg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// There are 4 event listeners in the page: button.onclick, window.onload
|
||||||
|
// and two more from the video element controls.
|
||||||
|
is(aPacket.listeners.length, 4, "Found all event listeners.");
|
||||||
|
aThreadClient.resume(deferred.resolve);
|
||||||
|
});
|
||||||
|
|
||||||
|
return deferred.promise;
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeConnection() {
|
||||||
|
let deferred = promise.defer();
|
||||||
|
gClient.close(deferred.resolve);
|
||||||
|
return deferred.promise;
|
||||||
|
}
|
||||||
|
|
||||||
|
registerCleanupFunction(function() {
|
||||||
|
removeTab(gBrowser.selectedTab);
|
||||||
|
gClient = null;
|
||||||
|
});
|
22
browser/devtools/debugger/test/doc_native-event-handler.html
Normal file
22
browser/devtools/debugger/test/doc_native-event-handler.html
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
<!-- Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/ -->
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>A video element with native event handlers</title>
|
||||||
|
<script type="text/javascript">
|
||||||
|
function initialSetup(event) {
|
||||||
|
debugger;
|
||||||
|
}
|
||||||
|
|
||||||
|
window.addEventListener("load", function() {}, false);
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<button onclick="initialSetup()">Click me!</button>
|
||||||
|
<!-- the "controls" attribute ensures that there are extra event handlers in
|
||||||
|
the element. -->
|
||||||
|
<video controls></video>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -996,15 +996,25 @@ TextProperty.prototype = {
|
|||||||
dummyStyle.setProperty(this.name, this.value, this.priority);
|
dummyStyle.setProperty(this.name, this.value, this.priority);
|
||||||
|
|
||||||
this.computed = [];
|
this.computed = [];
|
||||||
for (let i = 0, n = dummyStyle.length; i < n; i++) {
|
|
||||||
let prop = dummyStyle.item(i);
|
try {
|
||||||
this.computed.push({
|
// Manually get all the properties that are set when setting a value on
|
||||||
textProp: this,
|
// this.name and check the computed style on dummyElement for each one.
|
||||||
name: prop,
|
// If we just read dummyStyle, it would skip properties when value == "".
|
||||||
value: dummyStyle.getPropertyValue(prop),
|
let subProps = domUtils.getSubpropertiesForCSSProperty(this.name);
|
||||||
priority: dummyStyle.getPropertyPriority(prop),
|
|
||||||
});
|
for (let prop of subProps) {
|
||||||
}
|
this.computed.push({
|
||||||
|
textProp: this,
|
||||||
|
name: prop,
|
||||||
|
value: dummyStyle.getPropertyValue(prop),
|
||||||
|
priority: dummyStyle.getPropertyPriority(prop),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
// This is a partial property name, probably from cutting and pasting
|
||||||
|
// text. At this point don't check for computed properties.
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -74,5 +74,6 @@ function* testCreateNew(view) {
|
|||||||
yield onModifications;
|
yield onModifications;
|
||||||
|
|
||||||
is(textProp.value, "#XYZ", "Text prop should have been changed.");
|
is(textProp.value, "#XYZ", "Text prop should have been changed.");
|
||||||
|
is(textProp.overridden, false, "Property should not be overridden");
|
||||||
is(textProp.editor.isValid(), false, "#XYZ should not be a valid entry");
|
is(textProp.editor.isValid(), false, "#XYZ should not be a valid entry");
|
||||||
}
|
}
|
||||||
|
@ -10,4 +10,4 @@
|
|||||||
# hardcoded milestones in the tree from these two files.
|
# hardcoded milestones in the tree from these two files.
|
||||||
#--------------------------------------------------------
|
#--------------------------------------------------------
|
||||||
|
|
||||||
33.0a1
|
34.0a1
|
||||||
|
@ -457,7 +457,10 @@ BluetoothAdapter::StopDiscovery(ErrorResult& aRv)
|
|||||||
aRv.Throw(NS_ERROR_FAILURE);
|
aRv.Throw(NS_ERROR_FAILURE);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
nsRefPtr<Promise> promise = new Promise(global);
|
nsRefPtr<Promise> promise = Promise::Create(global, aRv);
|
||||||
|
if (aRv.Failed()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ensure
|
* Ensure
|
||||||
@ -819,11 +822,7 @@ BluetoothAdapter::EnableDisable(bool aEnable, ErrorResult& aRv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Notify applications of adapter state change to Enabling/Disabling
|
// Notify applications of adapter state change to Enabling/Disabling
|
||||||
nsTArray<nsString> types;
|
HandleAdapterStateChanged();
|
||||||
BT_APPEND_ENUM_STRING(types,
|
|
||||||
BluetoothAdapterAttribute,
|
|
||||||
BluetoothAdapterAttribute::State);
|
|
||||||
DispatchAttributeEvent(types);
|
|
||||||
|
|
||||||
// Wrap runnable to handle result
|
// Wrap runnable to handle result
|
||||||
nsRefPtr<BluetoothReplyRunnable> result =
|
nsRefPtr<BluetoothReplyRunnable> result =
|
||||||
@ -832,8 +831,11 @@ BluetoothAdapter::EnableDisable(bool aEnable, ErrorResult& aRv)
|
|||||||
methodName);
|
methodName);
|
||||||
|
|
||||||
if(NS_FAILED(bs->EnableDisable(aEnable, result))) {
|
if(NS_FAILED(bs->EnableDisable(aEnable, result))) {
|
||||||
|
// Restore mState and notify applications of adapter state change
|
||||||
mState = aEnable ? BluetoothAdapterState::Disabled
|
mState = aEnable ? BluetoothAdapterState::Disabled
|
||||||
: BluetoothAdapterState::Enabled;
|
: BluetoothAdapterState::Enabled;
|
||||||
|
HandleAdapterStateChanged();
|
||||||
|
|
||||||
promise->MaybeReject(NS_ERROR_DOM_OPERATION_ERR);
|
promise->MaybeReject(NS_ERROR_DOM_OPERATION_ERR);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -894,6 +896,16 @@ BluetoothAdapter::IsAdapterAttributeChanged(BluetoothAdapterAttribute aType,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
BluetoothAdapter::HandleAdapterStateChanged()
|
||||||
|
{
|
||||||
|
nsTArray<nsString> types;
|
||||||
|
BT_APPEND_ENUM_STRING(types,
|
||||||
|
BluetoothAdapterAttribute,
|
||||||
|
BluetoothAdapterAttribute::State);
|
||||||
|
DispatchAttributeEvent(types);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
BluetoothAdapter::HandlePropertyChanged(const BluetoothValue& aValue)
|
BluetoothAdapter::HandlePropertyChanged(const BluetoothValue& aValue)
|
||||||
{
|
{
|
||||||
|
@ -193,6 +193,7 @@ private:
|
|||||||
|
|
||||||
bool IsAdapterAttributeChanged(BluetoothAdapterAttribute aType,
|
bool IsAdapterAttributeChanged(BluetoothAdapterAttribute aType,
|
||||||
const BluetoothValue& aValue);
|
const BluetoothValue& aValue);
|
||||||
|
void HandleAdapterStateChanged();
|
||||||
void HandlePropertyChanged(const BluetoothValue& aValue);
|
void HandlePropertyChanged(const BluetoothValue& aValue);
|
||||||
void DispatchAttributeEvent(const nsTArray<nsString>& aTypes);
|
void DispatchAttributeEvent(const nsTArray<nsString>& aTypes);
|
||||||
BluetoothAdapterAttribute
|
BluetoothAdapterAttribute
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
XPIDL_SOURCES += [
|
XPIDL_SOURCES += [
|
||||||
|
'nsICellInfo.idl',
|
||||||
'nsIMobileCellInfo.idl',
|
'nsIMobileCellInfo.idl',
|
||||||
'nsIMobileConnectionInfo.idl',
|
'nsIMobileConnectionInfo.idl',
|
||||||
'nsIMobileConnectionProvider.idl',
|
'nsIMobileConnectionProvider.idl',
|
||||||
|
256
dom/mobileconnection/interfaces/nsICellInfo.idl
Normal file
256
dom/mobileconnection/interfaces/nsICellInfo.idl
Normal file
@ -0,0 +1,256 @@
|
|||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||||
|
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#include "nsISupports.idl"
|
||||||
|
|
||||||
|
[scriptable, uuid(1aed4c36-979e-4d20-9fa0-55139da8301e)]
|
||||||
|
interface nsICellInfoListCallback : nsISupports
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* result is an array of nsICellInfo.
|
||||||
|
*/
|
||||||
|
void notifyGetCellInfoList(in jsval result);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback function with error message.
|
||||||
|
*/
|
||||||
|
void notifyGetCellInfoListFailed(in DOMString error);
|
||||||
|
};
|
||||||
|
|
||||||
|
[scriptable, uuid(86667898-c9ab-44ee-8a9a-026916b3183e)]
|
||||||
|
interface nsICellInfo : nsISupports
|
||||||
|
{
|
||||||
|
const long CELL_INFO_TYPE_GSM = 1;
|
||||||
|
const long CELL_INFO_TYPE_CDMA = 2;
|
||||||
|
const long CELL_INFO_TYPE_LTE = 3;
|
||||||
|
const long CELL_INFO_TYPE_WCDMA = 4;
|
||||||
|
|
||||||
|
const long TIMESTAMP_TYPE_UNKNOWN = 0;
|
||||||
|
const long TIMESTAMP_TYPE_ANTENNA = 1;
|
||||||
|
const long TIMESTAMP_TYPE_MODEM = 2;
|
||||||
|
const long TIMESTAMP_TYPE_OEM_RIL = 3;
|
||||||
|
const long TIMESTAMP_TYPE_JAVA_RIL = 4;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Network type. One of the CELL_INFO_TYPE_* constants.
|
||||||
|
*/
|
||||||
|
readonly attribute long type;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Registration state of this cell.
|
||||||
|
*/
|
||||||
|
readonly attribute boolean registered;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Time stamp type. One of the TIMESTAMP_TYPE_* constants.
|
||||||
|
*/
|
||||||
|
readonly attribute long timestampType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Time in nanoseconds since boot.
|
||||||
|
*/
|
||||||
|
readonly attribute long long timestamp;
|
||||||
|
};
|
||||||
|
|
||||||
|
[scriptable, uuid(6345967c-61fc-45a1-8362-39e9261df052)]
|
||||||
|
interface nsIGsmCellInfo : nsICellInfo
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 3-digit Mobile Country Code, 0..999, INT_MAX if unknown.
|
||||||
|
*/
|
||||||
|
readonly attribute long mcc;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 2 or 3-digit Mobile Network Code, 0..999, INT_MAX if unknown.
|
||||||
|
*/
|
||||||
|
readonly attribute long mnc;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 16-bit Location Area Code, 0..65535, INT_MAX if unknown.
|
||||||
|
*/
|
||||||
|
readonly attribute long lac;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 16-bit GSM Cell Identity described in TS 27.007, 0..65535, INT_MAX if unknown.
|
||||||
|
*/
|
||||||
|
readonly attribute long cid;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Valid values are 0-31 as defined in TS 27.007 8.5, 99 if unknown.
|
||||||
|
*/
|
||||||
|
readonly attribute long signalStrength;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bit error rate 0-7 as defined in TS 27.007 8.5, 99 if unknown.
|
||||||
|
*/
|
||||||
|
readonly attribute long bitErrorRate;
|
||||||
|
};
|
||||||
|
|
||||||
|
[scriptable, uuid(19693f98-943d-45e7-a3e8-25373228ce6b)]
|
||||||
|
interface nsIWcdmaCellInfo : nsICellInfo
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 2 or 3-digit Mobile Network Code, 0..999, INT_MAX if unknown.
|
||||||
|
*/
|
||||||
|
readonly attribute long mcc;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 2 or 3-digit Mobile Network Code, 0..999, INT_MAX if unknown.
|
||||||
|
*/
|
||||||
|
readonly attribute long mnc;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 16-bit Location Area Code, 0..65535, INT_MAX if unknown.
|
||||||
|
*/
|
||||||
|
readonly attribute long lac;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 28-bit UMTS Cell Identity described in TS 25.331, 0..268435455,
|
||||||
|
* INT_MAX if unknown.
|
||||||
|
*/
|
||||||
|
readonly attribute long cid;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 9-bit UMTS Primary Scrambling Code described in TS 25.331, 0..511,
|
||||||
|
* INT_MAX if unknown.
|
||||||
|
*/
|
||||||
|
readonly attribute long psc;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Valid values are 0-31 as defined in TS 27.007 8.5, 99 if unknown.
|
||||||
|
*/
|
||||||
|
readonly attribute long signalStrength;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bit error rate 0-7 as defined in TS 27.007 8.5, 99 if unknown.
|
||||||
|
*/
|
||||||
|
readonly attribute long bitErrorRate;
|
||||||
|
};
|
||||||
|
|
||||||
|
[scriptable, uuid(76b4a35d-7e45-42bc-a2e0-bc07a6434db3)]
|
||||||
|
interface nsICdmaCellInfo : nsICellInfo
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Network Id, 0..65535, INT_MAX if unknown.
|
||||||
|
*/
|
||||||
|
readonly attribute long networkId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CDMA System Id, 0..32767, INT_MAX if unknown.
|
||||||
|
*/
|
||||||
|
readonly attribute long systemId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base Station Id, 0..65535, INT_MAX if unknown.
|
||||||
|
*/
|
||||||
|
readonly attribute long baseStationId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Longitude is a decimal number as specified in 3GPP2 C.S0005-A v6.0.
|
||||||
|
* It is represented in units of 0.25 seconds and ranges from -2592000 to
|
||||||
|
* 2592000, INT_MAX if unknown.
|
||||||
|
*/
|
||||||
|
readonly attribute long longitude;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Latitude is a decimal number as specified in 3GPP2 C.S0005-A v6.0.
|
||||||
|
* It is represented in units of 0.25 seconds and ranges from -1296000 to
|
||||||
|
* 1296000, INT_MAX if unknown.
|
||||||
|
*/
|
||||||
|
readonly attribute long latitude;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Valid values are positive integers, INT_MAX if unknown. This value is the
|
||||||
|
* actual RSSI value multiplied by -1.
|
||||||
|
*/
|
||||||
|
readonly attribute long cdmaDbm;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Valid values are positive integers, INT_MAX if unknown. This value is the
|
||||||
|
* actual Ec/Io multiplied by -10. -1 if unknown.
|
||||||
|
*/
|
||||||
|
readonly attribute long cdmaEcio;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Valid values are positive integers, INT_MAX if unknown. This value is the
|
||||||
|
* actual Evdo RSSI value multiplied by -1.
|
||||||
|
*/
|
||||||
|
readonly attribute long evdoDbm;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Valid values are positive integers, INT_MAX if unknown. This value is the
|
||||||
|
* actual Evdo Ec/Io multiplied by -10.
|
||||||
|
*/
|
||||||
|
readonly attribute long evdoEcio;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Valid values are 0-8, INT_MAX if unknown. 8 is the highest signal to noise
|
||||||
|
* ratio.
|
||||||
|
*/
|
||||||
|
readonly attribute long evdoSnr;
|
||||||
|
};
|
||||||
|
|
||||||
|
[scriptable, uuid(122937d9-1ee5-45e0-a360-5959d578bc31)]
|
||||||
|
interface nsILteCellInfo : nsICellInfo
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 3-digit Mobile Country Code, 0..999, INT_MAX if unknown.
|
||||||
|
*/
|
||||||
|
readonly attribute long mcc;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 2 or 3-digit Mobile Network Code, 0..999, INT_MAX if unknown.
|
||||||
|
*/
|
||||||
|
readonly attribute long mnc;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 28-bit Cell Identity, 0..268435455, INT_MAX if unknown.
|
||||||
|
*/
|
||||||
|
readonly attribute long cid;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Physical cell id, 0..503, INT_MAX if unknown.
|
||||||
|
*/
|
||||||
|
readonly attribute long pcid;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 16-bit tracking area code, 0..65535, INT_MAX if unknown.
|
||||||
|
*/
|
||||||
|
readonly attribute long tac;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Valid values are 0-31 as defined in TS 27.007 8.5, 99 if unknown.
|
||||||
|
*/
|
||||||
|
readonly attribute long signalStrength;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The current Reference Signal Receive Power in dBm multipled by -1.
|
||||||
|
* Range: 44 to 140 dBm, INT_MAX if unknown.
|
||||||
|
*/
|
||||||
|
readonly attribute long rsrp;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The current Reference Signal Receive Quality in dB multiplied by -1.
|
||||||
|
* Range: 3 to 20 dB, INT_MAX if unknown.
|
||||||
|
*/
|
||||||
|
readonly attribute long rsrq;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The current reference signal signal-to-noise ratio in 0.1 dB units.
|
||||||
|
* Range: -200 to +300 (-200 = -20.0 dB, +300 = 30dB), INT_MAX if unknown.
|
||||||
|
*/
|
||||||
|
readonly attribute long rssnr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The current Channel Quality Indicator. Range: 0 to 15, INT_MAX if unknown.
|
||||||
|
*/
|
||||||
|
readonly attribute long cqi;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Timing advance in micro seconds for a one way trip from cell to device.
|
||||||
|
* Approximate distance can be calculated using 300m/us * timingAdvance.
|
||||||
|
* Range: 0 to 0x7FFFFFFE, INT_MAX if unknown.
|
||||||
|
*/
|
||||||
|
readonly attribute long timingAdvance;
|
||||||
|
};
|
@ -28,6 +28,7 @@
|
|||||||
namespace android {
|
namespace android {
|
||||||
class MOZ_EXPORT MtpServer;
|
class MOZ_EXPORT MtpServer;
|
||||||
class MOZ_EXPORT MtpStorage;
|
class MOZ_EXPORT MtpStorage;
|
||||||
|
class MOZ_EXPORT MtpStringBuffer;
|
||||||
class MOZ_EXPORT MtpDatabase;
|
class MOZ_EXPORT MtpDatabase;
|
||||||
class MOZ_EXPORT MtpDataPacket;
|
class MOZ_EXPORT MtpDataPacket;
|
||||||
class MOZ_EXPORT MtpProperty;
|
class MOZ_EXPORT MtpProperty;
|
||||||
@ -39,6 +40,7 @@ namespace android {
|
|||||||
#include <MtpProperty.h>
|
#include <MtpProperty.h>
|
||||||
#include <MtpServer.h>
|
#include <MtpServer.h>
|
||||||
#include <MtpStorage.h>
|
#include <MtpStorage.h>
|
||||||
|
#include <MtpStringBuffer.h>
|
||||||
#include <MtpTypes.h>
|
#include <MtpTypes.h>
|
||||||
|
|
||||||
#endif // mozilla_system_mtpcommon_h__
|
#endif // mozilla_system_mtpcommon_h__
|
||||||
|
@ -29,6 +29,7 @@ ObjectPropertyAsStr(MtpObjectProperty aProperty)
|
|||||||
{
|
{
|
||||||
switch (aProperty) {
|
switch (aProperty) {
|
||||||
case MTP_PROPERTY_STORAGE_ID: return "MTP_PROPERTY_STORAGE_ID";
|
case MTP_PROPERTY_STORAGE_ID: return "MTP_PROPERTY_STORAGE_ID";
|
||||||
|
case MTP_PROPERTY_OBJECT_FILE_NAME: return "MTP_PROPERTY_OBJECT_FILE_NAME";
|
||||||
case MTP_PROPERTY_OBJECT_FORMAT: return "MTP_PROPERTY_OBJECT_FORMAT";
|
case MTP_PROPERTY_OBJECT_FORMAT: return "MTP_PROPERTY_OBJECT_FORMAT";
|
||||||
case MTP_PROPERTY_OBJECT_SIZE: return "MTP_PROPERTY_OBJECT_SIZE";
|
case MTP_PROPERTY_OBJECT_SIZE: return "MTP_PROPERTY_OBJECT_SIZE";
|
||||||
case MTP_PROPERTY_WIDTH: return "MTP_PROPERTY_WIDTH";
|
case MTP_PROPERTY_WIDTH: return "MTP_PROPERTY_WIDTH";
|
||||||
@ -102,6 +103,22 @@ MozMtpDatabase::BaseName(const nsCString& path)
|
|||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static nsCString
|
||||||
|
GetPathWithoutFileName(const nsCString& aFullPath)
|
||||||
|
{
|
||||||
|
nsCString path;
|
||||||
|
|
||||||
|
int32_t offset = aFullPath.RFindChar('/');
|
||||||
|
if (offset != kNotFound) {
|
||||||
|
// The trailing slash will be as part of 'path'
|
||||||
|
path = StringHead(aFullPath, offset + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
MTP_LOG("returning '%s'", path.get());
|
||||||
|
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
MozMtpDatabase::ParseDirectory(const char *aDir, MtpObjectHandle aParent)
|
MozMtpDatabase::ParseDirectory(const char *aDir, MtpObjectHandle aParent)
|
||||||
{
|
{
|
||||||
@ -353,14 +370,84 @@ MozMtpDatabase::getObjectPropertyValue(MtpObjectHandle aHandle,
|
|||||||
return MTP_RESPONSE_OK;
|
return MTP_RESPONSE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
GetTypeOfObjectProp(MtpObjectProperty aProperty)
|
||||||
|
{
|
||||||
|
struct PropertyTableEntry {
|
||||||
|
MtpObjectProperty property;
|
||||||
|
int type;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const PropertyTableEntry kObjectPropertyTable[] = {
|
||||||
|
{MTP_PROPERTY_STORAGE_ID, MTP_TYPE_UINT32 },
|
||||||
|
{MTP_PROPERTY_OBJECT_FORMAT, MTP_TYPE_UINT16 },
|
||||||
|
{MTP_PROPERTY_PROTECTION_STATUS, MTP_TYPE_UINT16 },
|
||||||
|
{MTP_PROPERTY_OBJECT_SIZE, MTP_TYPE_UINT64 },
|
||||||
|
{MTP_PROPERTY_OBJECT_FILE_NAME, MTP_TYPE_STR },
|
||||||
|
{MTP_PROPERTY_DATE_MODIFIED, MTP_TYPE_STR },
|
||||||
|
{MTP_PROPERTY_PARENT_OBJECT, MTP_TYPE_UINT32 },
|
||||||
|
{MTP_PROPERTY_DISPLAY_NAME, MTP_TYPE_STR },
|
||||||
|
{MTP_PROPERTY_DATE_ADDED, MTP_TYPE_STR },
|
||||||
|
};
|
||||||
|
|
||||||
|
int count = sizeof(kObjectPropertyTable) / sizeof(kObjectPropertyTable[0]);
|
||||||
|
const PropertyTableEntry* entryProp = kObjectPropertyTable;
|
||||||
|
int type = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < count; ++i, ++entryProp) {
|
||||||
|
if (entryProp->property == aProperty) {
|
||||||
|
type = entryProp->type;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
//virtual
|
//virtual
|
||||||
MtpResponseCode
|
MtpResponseCode
|
||||||
MozMtpDatabase::setObjectPropertyValue(MtpObjectHandle aHandle,
|
MozMtpDatabase::setObjectPropertyValue(MtpObjectHandle aHandle,
|
||||||
MtpObjectProperty aProperty,
|
MtpObjectProperty aProperty,
|
||||||
MtpDataPacket& aPacket)
|
MtpDataPacket& aPacket)
|
||||||
{
|
{
|
||||||
MTP_LOG("Handle: 0x%08x (NOT SUPPORTED)", aHandle);
|
MTP_LOG("Handle: 0x%08x Property: 0x%08x", aHandle, aProperty);
|
||||||
return MTP_RESPONSE_OPERATION_NOT_SUPPORTED;
|
|
||||||
|
// Only support file name change
|
||||||
|
if (aProperty != MTP_PROPERTY_OBJECT_FILE_NAME) {
|
||||||
|
MTP_ERR("property 0x%x not supported", aProperty);
|
||||||
|
return MTP_RESPONSE_OBJECT_PROP_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GetTypeOfObjectProp(aProperty) != MTP_TYPE_STR) {
|
||||||
|
MTP_ERR("property type 0x%x not supported", GetTypeOfObjectProp(aProperty));
|
||||||
|
return MTP_RESPONSE_GENERAL_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
RefPtr<DbEntry> entry = GetEntry(aHandle);
|
||||||
|
if (!entry) {
|
||||||
|
MTP_ERR("Invalid Handle: 0x%08x", aHandle);
|
||||||
|
return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
MtpStringBuffer buf;
|
||||||
|
aPacket.getString(buf);
|
||||||
|
|
||||||
|
nsDependentCString newFileName(buf);
|
||||||
|
nsCString newFileFullPath(GetPathWithoutFileName(entry->mPath) + newFileName);
|
||||||
|
|
||||||
|
if (PR_Rename(entry->mPath.get(), newFileFullPath.get()) != PR_SUCCESS) {
|
||||||
|
MTP_ERR("Failed to rename '%s' to '%s'",
|
||||||
|
entry->mPath.get(), newFileFullPath.get());
|
||||||
|
return MTP_RESPONSE_GENERAL_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
MTP_LOG("renamed '%s' to '%s'", entry->mPath.get(), newFileFullPath.get());
|
||||||
|
|
||||||
|
entry->mPath = newFileFullPath;
|
||||||
|
entry->mObjectName = BaseName(entry->mPath);
|
||||||
|
entry->mDisplayName = entry->mObjectName;
|
||||||
|
|
||||||
|
return MTP_RESPONSE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
//virtual
|
//virtual
|
||||||
@ -635,7 +722,13 @@ MozMtpDatabase::getObjectInfo(MtpObjectHandle aHandle,
|
|||||||
aInfo.mStorageID = entry->mStorageID;
|
aInfo.mStorageID = entry->mStorageID;
|
||||||
aInfo.mFormat = entry->mObjectFormat;
|
aInfo.mFormat = entry->mObjectFormat;
|
||||||
aInfo.mProtectionStatus = 0x0;
|
aInfo.mProtectionStatus = 0x0;
|
||||||
aInfo.mCompressedSize = 0;
|
|
||||||
|
if (entry->mObjectSize > 0xFFFFFFFFuLL) {
|
||||||
|
aInfo.mCompressedSize = 0xFFFFFFFFuLL;
|
||||||
|
} else {
|
||||||
|
aInfo.mCompressedSize = entry->mObjectSize;
|
||||||
|
}
|
||||||
|
|
||||||
aInfo.mThumbFormat = entry->mObjectFormat;
|
aInfo.mThumbFormat = entry->mObjectFormat;
|
||||||
aInfo.mThumbCompressedSize = 20*20*4;
|
aInfo.mThumbCompressedSize = 20*20*4;
|
||||||
aInfo.mThumbPixWidth = 20;
|
aInfo.mThumbPixWidth = 20;
|
||||||
@ -748,18 +841,36 @@ MozMtpDatabase::getObjectPropertyDesc(MtpObjectProperty aProperty,
|
|||||||
{
|
{
|
||||||
MTP_LOG("Property: %s 0x%08x", ObjectPropertyAsStr(aProperty), aProperty);
|
MTP_LOG("Property: %s 0x%08x", ObjectPropertyAsStr(aProperty), aProperty);
|
||||||
|
|
||||||
// TODO: Perhaps Filesize should be 64-bit?
|
|
||||||
|
|
||||||
MtpProperty* result = nullptr;
|
MtpProperty* result = nullptr;
|
||||||
switch (aProperty)
|
switch (aProperty)
|
||||||
{
|
{
|
||||||
case MTP_PROPERTY_STORAGE_ID: result = new MtpProperty(aProperty, MTP_TYPE_UINT32); break;
|
case MTP_PROPERTY_PROTECTION_STATUS:
|
||||||
case MTP_PROPERTY_OBJECT_FORMAT: result = new MtpProperty(aProperty, MTP_TYPE_UINT32); break;
|
result = new MtpProperty(aProperty, MTP_TYPE_UINT16);
|
||||||
case MTP_PROPERTY_OBJECT_SIZE: result = new MtpProperty(aProperty, MTP_TYPE_UINT32); break;
|
break;
|
||||||
case MTP_PROPERTY_WIDTH: result = new MtpProperty(aProperty, MTP_TYPE_UINT32); break;
|
case MTP_PROPERTY_OBJECT_FORMAT:
|
||||||
case MTP_PROPERTY_HEIGHT: result = new MtpProperty(aProperty, MTP_TYPE_UINT32); break;
|
result = new MtpProperty(aProperty, MTP_TYPE_UINT16, false, aFormat);
|
||||||
case MTP_PROPERTY_IMAGE_BIT_DEPTH: result = new MtpProperty(aProperty, MTP_TYPE_UINT32); break;
|
break;
|
||||||
case MTP_PROPERTY_DISPLAY_NAME: result = new MtpProperty(aProperty, MTP_TYPE_STR); break;
|
case MTP_PROPERTY_STORAGE_ID:
|
||||||
|
case MTP_PROPERTY_PARENT_OBJECT:
|
||||||
|
case MTP_PROPERTY_WIDTH:
|
||||||
|
case MTP_PROPERTY_HEIGHT:
|
||||||
|
case MTP_PROPERTY_IMAGE_BIT_DEPTH:
|
||||||
|
result = new MtpProperty(aProperty, MTP_TYPE_UINT32);
|
||||||
|
break;
|
||||||
|
case MTP_PROPERTY_OBJECT_SIZE:
|
||||||
|
result = new MtpProperty(aProperty, MTP_TYPE_UINT64);
|
||||||
|
break;
|
||||||
|
case MTP_PROPERTY_DISPLAY_NAME:
|
||||||
|
result = new MtpProperty(aProperty, MTP_TYPE_STR);
|
||||||
|
break;
|
||||||
|
case MTP_PROPERTY_OBJECT_FILE_NAME:
|
||||||
|
result = new MtpProperty(aProperty, MTP_TYPE_STR, true);
|
||||||
|
break;
|
||||||
|
case MTP_PROPERTY_DATE_MODIFIED:
|
||||||
|
case MTP_PROPERTY_DATE_ADDED:
|
||||||
|
result = new MtpProperty(aProperty, MTP_TYPE_STR);
|
||||||
|
result->setFormDateTime();
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -59,6 +59,14 @@ const CDMAICCINFO_CID =
|
|||||||
Components.ID("{39ba3c08-aacc-46d0-8c04-9b619c387061}");
|
Components.ID("{39ba3c08-aacc-46d0-8c04-9b619c387061}");
|
||||||
const NEIGHBORINGCELLINFO_CID =
|
const NEIGHBORINGCELLINFO_CID =
|
||||||
Components.ID("{f9dfe26a-851e-4a8b-a769-cbb1baae7ded}");
|
Components.ID("{f9dfe26a-851e-4a8b-a769-cbb1baae7ded}");
|
||||||
|
const GSMCELLINFO_CID =
|
||||||
|
Components.ID("{41f6201e-7263-42e3-b31f-38a9dc8a280a}");
|
||||||
|
const WCDMACELLINFO_CID =
|
||||||
|
Components.ID("{eeaaf307-df6e-4c98-b121-e3302b1fc468}");
|
||||||
|
const CDMACELLINFO_CID =
|
||||||
|
Components.ID("{b497d6e4-4cb8-4d6e-b673-840c7d5ddf25}");
|
||||||
|
const LTECELLINFO_CID =
|
||||||
|
Components.ID("{c7e0a78a-4e99-42f5-9251-e6172c5ed8d8}");
|
||||||
|
|
||||||
const NS_XPCOM_SHUTDOWN_OBSERVER_ID = "xpcom-shutdown";
|
const NS_XPCOM_SHUTDOWN_OBSERVER_ID = "xpcom-shutdown";
|
||||||
const kNetworkInterfaceStateChangedTopic = "network-interface-state-changed";
|
const kNetworkInterfaceStateChangedTopic = "network-interface-state-changed";
|
||||||
@ -97,6 +105,9 @@ const RADIO_POWER_OFF_TIMEOUT = 30000;
|
|||||||
const SMS_HANDLED_WAKELOCK_TIMEOUT = 5000;
|
const SMS_HANDLED_WAKELOCK_TIMEOUT = 5000;
|
||||||
const HW_DEFAULT_CLIENT_ID = 0;
|
const HW_DEFAULT_CLIENT_ID = 0;
|
||||||
|
|
||||||
|
const INT32_MAX = 2147483647;
|
||||||
|
const UNKNOWN_RSSI = 99;
|
||||||
|
|
||||||
const RIL_IPC_MOBILECONNECTION_MSG_NAMES = [
|
const RIL_IPC_MOBILECONNECTION_MSG_NAMES = [
|
||||||
"RIL:GetRilContext",
|
"RIL:GetRilContext",
|
||||||
"RIL:GetAvailableNetworks",
|
"RIL:GetAvailableNetworks",
|
||||||
@ -1076,7 +1087,109 @@ NeighboringCellInfo.prototype = {
|
|||||||
gsmLocationAreaCode: -1,
|
gsmLocationAreaCode: -1,
|
||||||
gsmCellId: -1,
|
gsmCellId: -1,
|
||||||
wcdmaPsc: -1,
|
wcdmaPsc: -1,
|
||||||
signalStrength: 99
|
signalStrength: UNKNOWN_RSSI
|
||||||
|
};
|
||||||
|
|
||||||
|
function CellInfo() {}
|
||||||
|
CellInfo.prototype = {
|
||||||
|
type: null,
|
||||||
|
registered: false,
|
||||||
|
timestampType: Ci.nsICellInfo.TIMESTAMP_TYPE_UNKNOWN,
|
||||||
|
timestamp: 0
|
||||||
|
};
|
||||||
|
|
||||||
|
function GsmCellInfo() {}
|
||||||
|
GsmCellInfo.prototype = {
|
||||||
|
__proto__: CellInfo.prototype,
|
||||||
|
QueryInterface: XPCOMUtils.generateQI([Ci.nsIGsmCellInfo]),
|
||||||
|
classID: GSMCELLINFO_CID,
|
||||||
|
classInfo: XPCOMUtils.generateCI({
|
||||||
|
classID: GSMCELLINFO_CID,
|
||||||
|
classDescription: "GsmCellInfo",
|
||||||
|
interfaces: [Ci.nsIGsmCellInfo]
|
||||||
|
}),
|
||||||
|
|
||||||
|
// nsIGsmCellInfo
|
||||||
|
|
||||||
|
mcc: INT32_MAX,
|
||||||
|
mnc: INT32_MAX,
|
||||||
|
lac: INT32_MAX,
|
||||||
|
cid: INT32_MAX,
|
||||||
|
signalStrength: UNKNOWN_RSSI,
|
||||||
|
bitErrorRate: UNKNOWN_RSSI
|
||||||
|
};
|
||||||
|
|
||||||
|
function WcdmaCellInfo() {}
|
||||||
|
WcdmaCellInfo.prototype = {
|
||||||
|
__proto__: CellInfo.prototype,
|
||||||
|
QueryInterface: XPCOMUtils.generateQI([Ci.nsIWcdmaCellInfo]),
|
||||||
|
classID: WCDMACELLINFO_CID,
|
||||||
|
classInfo: XPCOMUtils.generateCI({
|
||||||
|
classID: WCDMACELLINFO_CID,
|
||||||
|
classDescription: "WcdmaCellInfo",
|
||||||
|
interfaces: [Ci.nsIWcdmaCellInfo]
|
||||||
|
}),
|
||||||
|
|
||||||
|
// nsIWcdmaCellInfo
|
||||||
|
|
||||||
|
mcc: INT32_MAX,
|
||||||
|
mnc: INT32_MAX,
|
||||||
|
lac: INT32_MAX,
|
||||||
|
cid: INT32_MAX,
|
||||||
|
psc: INT32_MAX,
|
||||||
|
signalStrength: UNKNOWN_RSSI,
|
||||||
|
bitErrorRate: UNKNOWN_RSSI
|
||||||
|
};
|
||||||
|
|
||||||
|
function LteCellInfo() {}
|
||||||
|
LteCellInfo.prototype = {
|
||||||
|
__proto__: CellInfo.prototype,
|
||||||
|
QueryInterface: XPCOMUtils.generateQI([Ci.nsILteCellInfo]),
|
||||||
|
classID: LTECELLINFO_CID,
|
||||||
|
classInfo: XPCOMUtils.generateCI({
|
||||||
|
classID: LTECELLINFO_CID,
|
||||||
|
classDescription: "LteCellInfo",
|
||||||
|
interfaces: [Ci.nsILteCellInfo]
|
||||||
|
}),
|
||||||
|
|
||||||
|
// nsILteCellInfo
|
||||||
|
|
||||||
|
mcc: INT32_MAX,
|
||||||
|
mnc: INT32_MAX,
|
||||||
|
cid: INT32_MAX,
|
||||||
|
pcid: INT32_MAX,
|
||||||
|
tac: INT32_MAX,
|
||||||
|
signalStrength: UNKNOWN_RSSI,
|
||||||
|
rsrp: INT32_MAX,
|
||||||
|
rsrq: INT32_MAX,
|
||||||
|
rssnr: INT32_MAX,
|
||||||
|
cqi: INT32_MAX,
|
||||||
|
timingAdvance: INT32_MAX
|
||||||
|
};
|
||||||
|
|
||||||
|
function CdmaCellInfo() {}
|
||||||
|
CdmaCellInfo.prototype = {
|
||||||
|
__proto__: CellInfo.prototype,
|
||||||
|
QueryInterface: XPCOMUtils.generateQI([Ci.nsICdmaCellInfo]),
|
||||||
|
classID: CDMACELLINFO_CID,
|
||||||
|
classInfo: XPCOMUtils.generateCI({
|
||||||
|
classID: CDMACELLINFO_CID,
|
||||||
|
classDescription: "CdmaCellInfo",
|
||||||
|
interfaces: [Ci.nsICdmaCellInfo]
|
||||||
|
}),
|
||||||
|
|
||||||
|
// nsICdmaCellInfo
|
||||||
|
|
||||||
|
networkId: INT32_MAX,
|
||||||
|
systemId: INT32_MAX,
|
||||||
|
baseStationId: INT32_MAX,
|
||||||
|
longitude: INT32_MAX,
|
||||||
|
latitude: INT32_MAX,
|
||||||
|
cdmaDbm: INT32_MAX,
|
||||||
|
cdmaEcio: INT32_MAX,
|
||||||
|
evdoDbm: INT32_MAX,
|
||||||
|
evdoEcio: INT32_MAX,
|
||||||
|
evdoSnr: INT32_MAX
|
||||||
};
|
};
|
||||||
|
|
||||||
function DataConnectionHandler(clientId, radioInterface) {
|
function DataConnectionHandler(clientId, radioInterface) {
|
||||||
@ -4420,6 +4533,45 @@ RadioInterface.prototype = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
getCellInfoList: function(callback) {
|
||||||
|
this.workerMessenger.send("getCellInfoList",
|
||||||
|
null,
|
||||||
|
function(response) {
|
||||||
|
if (response.errorMsg) {
|
||||||
|
callback.notifyGetCellInfoListFailed(response.errorMsg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let cellInfoList = [];
|
||||||
|
let count = response.result.length;
|
||||||
|
for (let i = 0; i < count; i++) {
|
||||||
|
let srcCellInfo = response.result[i];
|
||||||
|
let cellInfo;
|
||||||
|
switch (srcCellInfo.type) {
|
||||||
|
case RIL.CELL_INFO_TYPE_GSM:
|
||||||
|
cellInfo = new GsmCellInfo();
|
||||||
|
break;
|
||||||
|
case RIL.CELL_INFO_TYPE_WCDMA:
|
||||||
|
cellInfo = new WcdmaCellInfo();
|
||||||
|
break;
|
||||||
|
case RIL.CELL_INFO_TYPE_LTE:
|
||||||
|
cellInfo = new LteCellInfo();
|
||||||
|
break;
|
||||||
|
case RIL.CELL_INFO_TYPE_CDMA:
|
||||||
|
cellInfo = new CdmaCellInfo();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!cellInfo) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
this.updateInfo(srcCellInfo, cellInfo);
|
||||||
|
cellInfoList.push(cellInfo);
|
||||||
|
}
|
||||||
|
callback.notifyGetCellInfoList(cellInfoList);
|
||||||
|
}.bind(this));
|
||||||
|
},
|
||||||
|
|
||||||
getNeighboringCellIds: function(callback) {
|
getNeighboringCellIds: function(callback) {
|
||||||
this.workerMessenger.send("getNeighboringCellIds",
|
this.workerMessenger.send("getNeighboringCellIds",
|
||||||
null,
|
null,
|
||||||
|
@ -9,6 +9,7 @@ interface nsIDOMMozIccInfo;
|
|||||||
interface nsIMobileConnectionInfo;
|
interface nsIMobileConnectionInfo;
|
||||||
interface nsIMobileMessageCallback;
|
interface nsIMobileMessageCallback;
|
||||||
interface nsINeighboringCellIdsCallback;
|
interface nsINeighboringCellIdsCallback;
|
||||||
|
interface nsICellInfoListCallback;
|
||||||
|
|
||||||
[scriptable, uuid(6e0f45b8-410e-11e3-8c8e-b715b2cd0128)]
|
[scriptable, uuid(6e0f45b8-410e-11e3-8c8e-b715b2cd0128)]
|
||||||
interface nsIRilNetworkInterface : nsINetworkInterface
|
interface nsIRilNetworkInterface : nsINetworkInterface
|
||||||
@ -56,7 +57,7 @@ interface nsIRilSendWorkerMessageCallback : nsISupports
|
|||||||
boolean handleResponse(in jsval response);
|
boolean handleResponse(in jsval response);
|
||||||
};
|
};
|
||||||
|
|
||||||
[scriptable, uuid(31ba65b6-05c7-4bc8-abdc-f1a219811fb4)]
|
[scriptable, uuid(c13a8890-797b-4557-b92f-6b959f56c1d8)]
|
||||||
interface nsIRadioInterface : nsISupports
|
interface nsIRadioInterface : nsISupports
|
||||||
{
|
{
|
||||||
readonly attribute nsIRilContext rilContext;
|
readonly attribute nsIRilContext rilContext;
|
||||||
@ -88,9 +89,15 @@ interface nsIRadioInterface : nsISupports
|
|||||||
void getSmscAddress(in nsIMobileMessageCallback request);
|
void getSmscAddress(in nsIMobileMessageCallback request);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cell Info functionality.
|
* Request neighboring cell ids in GSM/UMTS network.
|
||||||
*/
|
*/
|
||||||
void getNeighboringCellIds(in nsINeighboringCellIdsCallback callback);
|
void getNeighboringCellIds(in nsINeighboringCellIdsCallback callback);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request all of the current cell information known to the radio, including
|
||||||
|
* neighboring cells.
|
||||||
|
*/
|
||||||
|
void getCellInfoList(in nsICellInfoListCallback callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
[scriptable, uuid(78b65e8c-68e7-4510-9a05-65bba12b283e)]
|
[scriptable, uuid(78b65e8c-68e7-4510-9a05-65bba12b283e)]
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user