Merge m-c to inbound. a=merge

CLOSED TREE
This commit is contained in:
Ryan VanderMeulen 2015-07-09 13:52:22 -04:00
commit 89eb454666
110 changed files with 1450 additions and 808 deletions

View File

@ -26,9 +26,11 @@ let librecovery = (function() {
log("Unable to open librecovery.so");
throw Cr.NS_ERROR_FAILURE;
}
// Bug 1163956, modify updatePath from ctyps.char.ptr to ctype.char.array(4096)
// align with librecovery.h. 4096 comes from PATH_MAX
let FotaUpdateStatus = new ctypes.StructType("FotaUpdateStatus", [
{ result: ctypes.int },
{ updatePath: ctypes.char.ptr }
{ updatePath: ctypes.char.array(4096) }
]);
return {

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="fc6643dd3da2ccdf2ab284479643836bb3698644"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="bdddfe1ebb796e2bc1c048d5c4e0f97f3d06f98b"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="fc6643dd3da2ccdf2ab284479643836bb3698644"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="bdddfe1ebb796e2bc1c048d5c4e0f97f3d06f98b"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
@ -135,7 +135,7 @@
<project groups="invensense" name="platform/hardware/invensense" path="hardware/invensense" revision="e6d9ab28b4f4e7684f6c07874ee819c9ea0002a2"/>
<project name="platform/hardware/ril" path="hardware/ril" revision="865ce3b4a2ba0b3a31421ca671f4d6c5595f8690"/>
<project name="kernel/common" path="kernel" revision="0f36762ab0c1d8ce10c6a5eda948b05d5d6cc379"/>
<project name="platform/system/core" path="system/core" revision="21aded5b180f7bcc9e2cefbe6e570b1d51b6065b"/>
<project name="platform/system/core" path="system/core" revision="4b989b1bec28b0838420c4d5bb454c78afa62bea"/>
<project name="u-boot" path="u-boot" revision="f1502910977ac88f43da7bf9277c3523ad4b0b2f"/>
<project name="vendor/sprd/gps" path="vendor/sprd/gps" revision="7d6e1269be7186b2073fa568958b357826692c4b"/>
<project name="vendor/sprd/open-source" path="vendor/sprd/open-source" revision="e503b1d14d7fdee532b8f391407299da193c1b2d"/>

View File

@ -19,7 +19,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="fc6643dd3da2ccdf2ab284479643836bb3698644"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="bdddfe1ebb796e2bc1c048d5c4e0f97f3d06f98b"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="87a2d8ab9248540910e56921654367b78a587095"/>

View File

@ -17,7 +17,7 @@
</project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="fc6643dd3da2ccdf2ab284479643836bb3698644"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="bdddfe1ebb796e2bc1c048d5c4e0f97f3d06f98b"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="47f48a42502b1c694db2b162011a67a2ff888c5d"/>

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="fc6643dd3da2ccdf2ab284479643836bb3698644"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="bdddfe1ebb796e2bc1c048d5c4e0f97f3d06f98b"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="61e82f99bb8bc78d52b5717e9a2481ec7267fa33">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="fc6643dd3da2ccdf2ab284479643836bb3698644"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="bdddfe1ebb796e2bc1c048d5c4e0f97f3d06f98b"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

View File

@ -19,7 +19,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="fc6643dd3da2ccdf2ab284479643836bb3698644"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="bdddfe1ebb796e2bc1c048d5c4e0f97f3d06f98b"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="87a2d8ab9248540910e56921654367b78a587095"/>

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="fc6643dd3da2ccdf2ab284479643836bb3698644"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="bdddfe1ebb796e2bc1c048d5c4e0f97f3d06f98b"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

View File

@ -1,9 +1,9 @@
{
"git": {
"git_revision": "fc6643dd3da2ccdf2ab284479643836bb3698644",
"git_revision": "bdddfe1ebb796e2bc1c048d5c4e0f97f3d06f98b",
"remote": "https://git.mozilla.org/releases/gaia.git",
"branch": ""
},
"revision": "40fc25355c4367b9e6b73384c070742ae6ff7c0c",
"revision": "4d65a0a88ccd51c22e9b591320d1fe682642dc0a",
"repo_path": "integration/gaia-central"
}

View File

@ -17,7 +17,7 @@
</project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="fc6643dd3da2ccdf2ab284479643836bb3698644"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="bdddfe1ebb796e2bc1c048d5c4e0f97f3d06f98b"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="47f48a42502b1c694db2b162011a67a2ff888c5d"/>

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="61e82f99bb8bc78d52b5717e9a2481ec7267fa33">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="fc6643dd3da2ccdf2ab284479643836bb3698644"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="bdddfe1ebb796e2bc1c048d5c4e0f97f3d06f98b"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
@ -141,7 +141,7 @@
<default remote="caf" revision="refs/tags/android-5.1.0_r1" sync-j="4"/>
<!-- Nexus 5 specific things -->
<project name="device/generic/armv7-a-neon" path="device/generic/armv7-a-neon" revision="fe7df1bc8dd0fd71571505d7be1c31a4ad1e40fb"/>
<project name="device-hammerhead" path="device/lge/hammerhead" remote="b2g" revision="74919c3e2742b3237b2f30a8cefe182d0caf1e31"/>
<project name="device-hammerhead" path="device/lge/hammerhead" remote="b2g" revision="1ad7478309fd43981973e297f5a68a480f3a3c07"/>
<project name="device_lge_hammerhead-kernel" path="device/lge/hammerhead-kernel" remote="b2g" revision="1d42cfba2e91a07b1bea1d1591b8aed4db9cb9a5"/>
<project name="platform/external/libnfc-nci" path="external/libnfc-nci" revision="5d0ae53d9588c3d70c005aec9be94af9a534de16"/>
<project name="platform/external/wpa_supplicant_8" path="external/wpa_supplicant_8" revision="c15b6e266136cd0cdd9b94d0bbed1962d9dd6672"/>

View File

@ -2168,10 +2168,16 @@ function getShortcutOrURIAndPostData(url, callback = null) {
mayInheritPrincipal };
}
let entry = yield PlacesUtils.keywords.fetch(keyword);
if (entry) {
shortcutURL = entry.url.href;
postData = entry.postData;
// A corrupt Places database could make this throw, breaking navigation
// from the location bar.
try {
let entry = yield PlacesUtils.keywords.fetch(keyword);
if (entry) {
shortcutURL = entry.url.href;
postData = entry.postData;
}
} catch (ex) {
Components.utils.reportError(`Unable to fetch data for Places keyword "${keyword}": ${ex}`);
}
if (!shortcutURL) {

View File

@ -164,6 +164,23 @@ let gPage = {
}
},
/**
* Handles unload event
*/
_handleUnloadEvent: function Page_handleUnloadEvent() {
gAllPages.unregister(this);
// compute page life-span and send telemetry probe: using milli-seconds will leave
// many low buckets empty. Instead we use half-second precision to make low end
// of histogram linear and not loose the change in user attention
let delta = Math.round((Date.now() - this._firstVisibleTime) / 500);
if (this._suggestedTilePresent) {
Services.telemetry.getHistogramById("NEWTAB_PAGE_LIFE_SPAN_SUGGESTED").add(delta);
}
else {
Services.telemetry.getHistogramById("NEWTAB_PAGE_LIFE_SPAN").add(delta);
}
},
/**
* Handles all page events.
*/
@ -173,7 +190,7 @@ let gPage = {
this.onPageVisibleAndLoaded();
break;
case "unload":
gAllPages.unregister(this);
this._handleUnloadEvent();
break;
case "click":
let {button, target} = aEvent;
@ -225,6 +242,9 @@ let gPage = {
}
}
// save timestamp to compute page life-span delta
this._firstVisibleTime = Date.now();
if (document.readyState == "complete") {
this.onPageVisibleAndLoaded();
} else {
@ -256,6 +276,10 @@ let gPage = {
if (node.classList && node.classList.contains("newtab-cell")) {
if (sites[++i]) {
lastIndex = i;
if (sites[i].link.targetedSite) {
// record that suggested tile is shown to use suggested-tiles-histogram
this._suggestedTilePresent = true;
}
}
}
}

View File

@ -47,3 +47,4 @@ support-files =
[browser_newtab_unpin.js]
[browser_newtab_update.js]
[browser_newtab_bug1145428.js]
[browser_newtab_bug1178586.js]

View File

@ -0,0 +1,85 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/*
* These tests make sure that pinned suggested tile turns into history tile
* and remains a history tile after a user clicks on it
*/
gDirectorySource = "data:application/json," + JSON.stringify({
"suggested": [{
url: "http://example.com/hardlanding/page.html",
imageURI: "data:image/png;base64,helloWORLD3",
enhancedImageURI: "data:image/png;base64,helloWORLD2",
title: "title",
type: "affiliate",
frecent_sites: ["example0.com"],
}]
});
function runTests() {
let origGetFrecentSitesName = DirectoryLinksProvider.getFrecentSitesName;
DirectoryLinksProvider.getFrecentSitesName = () => "";
function getData(cellNum) {
let cell = getCell(cellNum);
if (!cell.site)
return null;
let siteNode = cell.site.node;
return {
type: siteNode.getAttribute("type"),
thumbnail: siteNode.querySelector(".newtab-thumbnail").style.backgroundImage,
enhanced: siteNode.querySelector(".enhanced-content").style.backgroundImage,
title: siteNode.querySelector(".newtab-title").textContent,
suggested: siteNode.getAttribute("suggested"),
url: siteNode.querySelector(".newtab-link").getAttribute("href"),
};
}
yield setLinks("0,1,2,3,4,5,6,7,8,9");
setPinnedLinks("");
yield addNewTabPageTab();
// load another newtab since the first may not get suggested tile
yield addNewTabPageTab();
checkGrid("http://example.com/hardlanding/page.html,0,1,2,3,4,5,6,7,8,9");
// evaluate suggested tile
let tileData = getData(0);
is(tileData.type, "affiliate", "unpinned type");
is(tileData.thumbnail, "url(\"data:image/png;base64,helloWORLD3\")", "unpinned thumbnail");
is(tileData.enhanced, "url(\"data:image/png;base64,helloWORLD2\")", "unpinned enhanced");
is(tileData.suggested, "true", "has suggested set", "unpinned suggested exists");
is(tileData.url, "http://example.com/hardlanding/page.html", "unpinned landing page");
// suggested tile should not be pinned
is(NewTabUtils.pinnedLinks.isPinned({url: "http://example.com/hardlanding/page.html"}), false, "suggested tile is not pinned");
// pin suggested tile
whenPagesUpdated();
let siteNode = getCell(0).node.querySelector(".newtab-site");
let pinButton = siteNode.querySelector(".newtab-control-pin");
EventUtils.synthesizeMouseAtCenter(pinButton, {}, getContentWindow());
// wait for whenPagesUpdated
yield null;
// tile should be pinned and turned into history tile
is(NewTabUtils.pinnedLinks.isPinned({url: "http://example.com/hardlanding/page.html"}), true, "suggested tile is pinned");
tileData = getData(0);
is(tileData.type, "history", "pinned type");
is(tileData.suggested, null, "no suggested attribute");
is(tileData.url, "http://example.com/hardlanding/page.html", "original landing page");
// click the pinned tile
siteNode = getCell(0).node.querySelector(".newtab-site");
EventUtils.synthesizeMouseAtCenter(siteNode, {}, getContentWindow());
// add new page twice to avoid using cached version
yield addNewTabPageTab();
yield addNewTabPageTab();
// check that type and suggested did not change
tileData = getData(0);
is(tileData.type, "history", "pinned type");
is(tileData.suggested, null, "no suggested attribute");
DirectoryLinksProvider.getFrecentSitesName = origGetFrecentSitesName;
}

View File

@ -61,7 +61,7 @@
"object-curly-spacing": 0, // [2, "always"],
"quotes": [2, "double", "avoid-escape"],
"spaced-comment": [2, "always"],
"strict": 0, // [2, "function"],
"strict": [2, "function"],
// eslint-plugin-react rules. These are documented at
// <https://github.com/yannickcr/eslint-plugin-react#list-of-supported-rules>
"react/jsx-quotes": [2, "double", "avoid-escape"],

View File

@ -10,6 +10,8 @@ loop.store = loop.store || {};
* the window data and store the window type.
*/
loop.store.ConversationAppStore = (function() {
"use strict";
/**
* Constructor
*

View File

@ -4,6 +4,7 @@
var loop = loop || {};
loop.conversationViews = (function(mozL10n) {
"use strict";
var CALL_STATES = loop.store.CALL_STATES;
var CALL_TYPES = loop.shared.utils.CALL_TYPES;

View File

@ -4,6 +4,7 @@
var loop = loop || {};
loop.conversationViews = (function(mozL10n) {
"use strict";
var CALL_STATES = loop.store.CALL_STATES;
var CALL_TYPES = loop.shared.utils.CALL_TYPES;

View File

@ -31,6 +31,7 @@
.standalone .conversation-toolbar {
padding: 20px;
height: 64px;
border: none;
}
.standalone .focus-stream {
@ -1089,16 +1090,19 @@ html[dir="rtl"] .room-context-btn-close {
}
.media-layout {
/* 50px is the header, 3em is the footer. */
height: calc(100% - 50px - 3em);
height: 100%;
}
.standalone-room-wrapper > .media-layout {
/* 50px is the header, 64px for toolbar, 3em is the footer. */
height: calc(100% - 50px - 64px - 3em);
}
.media-layout > .media-wrapper {
display: flex;
flex-flow: column wrap;
/* 64px for .conversation-toolbar */
height: calc(100% - 64px);
margin: 0 10px;
height: 100%;
}
.media-wrapper > .focus-stream {
@ -1182,17 +1186,19 @@ html[dir="rtl"] .room-context-btn-close {
}
@media screen and (max-width:640px) {
.media-layout {
/* 50px is height of header, 25px is height of footer. */
height: calc(100% - 50px - 25px);
.media-layout-wrapper {
height: 100%;
}
.standalone-room-wrapper > .media-layout {
/* 50px is height of header, 38px is height of toolbar, 25px is height of footer. */
height: calc(100% - 50px - 38px - 25px);
}
.media-layout > .media-wrapper {
flex-direction: row;
margin: 0;
width: 100%;
/* conversation toolbar is 38px in narrow mode */
height: calc(100% - 38px);
}
.media-wrapper > .focus-stream {

View File

@ -6,6 +6,8 @@ var loop = loop || {};
loop.store = loop.store || {};
(function() {
"use strict";
var sharedActions = loop.shared.actions;
var CALL_TYPES = loop.shared.utils.CALL_TYPES;
var REST_ERRNOS = loop.shared.utils.REST_ERRNOS;

View File

@ -13,6 +13,7 @@
*/
var loop = loop || {};
loop.Dispatcher = (function() {
"use strict";
function Dispatcher() {
this._eventData = {};

View File

@ -4,6 +4,7 @@
var loop = loop || {};
loop.OTSdkDriver = (function() {
"use strict";
var sharedActions = loop.shared.actions;
var FAILURE_DETAILS = loop.shared.utils.FAILURE_DETAILS;

View File

@ -113,6 +113,8 @@ loop.store.createStore = (function() {
* });
*/
loop.store.StoreMixin = (function() {
"use strict";
var _stores = {};
function StoreMixin(id) {
function _getStore() {

View File

@ -6,6 +6,8 @@ var loop = loop || {};
loop.shared = loop.shared || {};
loop.shared.views = loop.shared.views || {};
loop.shared.views.chat = (function(mozL10n) {
"use strict";
var sharedActions = loop.shared.actions;
var sharedMixins = loop.shared.mixins;
var sharedViews = loop.shared.views;

View File

@ -6,6 +6,8 @@ var loop = loop || {};
loop.shared = loop.shared || {};
loop.shared.views = loop.shared.views || {};
loop.shared.views.chat = (function(mozL10n) {
"use strict";
var sharedActions = loop.shared.actions;
var sharedMixins = loop.shared.mixins;
var sharedViews = loop.shared.views;

View File

@ -476,7 +476,7 @@ loop.standaloneRoomViews = (function(mozL10n) {
});
return (
React.createElement("div", {className: "room-conversation-wrapper"},
React.createElement("div", {className: "room-conversation-wrapper standalone-room-wrapper"},
React.createElement("div", {className: "beta-logo"}),
React.createElement(StandaloneRoomHeader, {dispatcher: this.props.dispatcher}),
React.createElement(StandaloneRoomInfoArea, {activeRoomStore: this.props.activeRoomStore,
@ -517,19 +517,19 @@ loop.standaloneRoomViews = (function(mozL10n) {
posterUrl: this.props.localPosterUrl,
srcVideoObject: this.state.localSrcVideoObject})
)
),
React.createElement(sharedViews.ConversationToolbar, {
audio: {enabled: !this.state.audioMuted,
visible: this._roomIsActive()},
dispatcher: this.props.dispatcher,
edit: { visible: false, enabled: false},
enableHangup: this._roomIsActive(),
hangup: this.leaveRoom,
hangupButtonLabel: mozL10n.get("rooms_leave_button_label"),
publishStream: this.publishStream,
video: {enabled: !this.state.videoMuted,
visible: this._roomIsActive()}})
)
),
React.createElement(sharedViews.ConversationToolbar, {
audio: {enabled: !this.state.audioMuted,
visible: this._roomIsActive()},
dispatcher: this.props.dispatcher,
edit: { visible: false, enabled: false},
enableHangup: this._roomIsActive(),
hangup: this.leaveRoom,
hangupButtonLabel: mozL10n.get("rooms_leave_button_label"),
publishStream: this.publishStream,
video: {enabled: !this.state.videoMuted,
visible: this._roomIsActive()}}),
React.createElement(loop.fxOSMarketplaceViews.FxOSHiddenMarketplaceView, {
marketplaceSrc: this.state.marketplaceSrc,
onMarketplaceMessage: this.state.onMarketplaceMessage}),

View File

@ -476,7 +476,7 @@ loop.standaloneRoomViews = (function(mozL10n) {
});
return (
<div className="room-conversation-wrapper">
<div className="room-conversation-wrapper standalone-room-wrapper">
<div className="beta-logo" />
<StandaloneRoomHeader dispatcher={this.props.dispatcher} />
<StandaloneRoomInfoArea activeRoomStore={this.props.activeRoomStore}
@ -518,18 +518,18 @@ loop.standaloneRoomViews = (function(mozL10n) {
srcVideoObject={this.state.localSrcVideoObject} />
</div>
</div>
<sharedViews.ConversationToolbar
audio={{enabled: !this.state.audioMuted,
visible: this._roomIsActive()}}
dispatcher={this.props.dispatcher}
edit={{ visible: false, enabled: false }}
enableHangup={this._roomIsActive()}
hangup={this.leaveRoom}
hangupButtonLabel={mozL10n.get("rooms_leave_button_label")}
publishStream={this.publishStream}
video={{enabled: !this.state.videoMuted,
visible: this._roomIsActive()}} />
</div>
<sharedViews.ConversationToolbar
audio={{enabled: !this.state.audioMuted,
visible: this._roomIsActive()}}
dispatcher={this.props.dispatcher}
edit={{ visible: false, enabled: false }}
enableHangup={this._roomIsActive()}
hangup={this.leaveRoom}
hangupButtonLabel={mozL10n.get("rooms_leave_button_label")}
publishStream={this.publishStream}
video={{enabled: !this.state.videoMuted,
visible: this._roomIsActive()}} />
<loop.fxOSMarketplaceViews.FxOSHiddenMarketplaceView
marketplaceSrc={this.state.marketplaceSrc}
onMarketplaceMessage={this.state.onMarketplaceMessage} />

View File

@ -83,6 +83,8 @@ app.use("/test", express.static(__dirname + "/../test"));
// As we don't have hashes on the urls, the best way to serve the index files
// appears to be to be to closely filter the url and match appropriately.
function serveIndex(req, res) {
"use strict";
return res.sendfile(__dirname + "/content/index.html");
}

View File

@ -2,6 +2,7 @@
* http://creativecommons.org/publicdomain/zero/1.0/ */
describe("loop.store.ConversationAppStore", function () {
"use strict";
var expect = chai.expect;
var sharedActions = loop.shared.actions;

View File

@ -2,6 +2,8 @@
* http://creativecommons.org/publicdomain/zero/1.0/ */
describe("loop.store.StandaloneAppStore", function () {
"use strict";
var expect = chai.expect;
var sharedActions = loop.shared.actions;
var sharedUtils = loop.shared.utils;

View File

@ -2,30 +2,33 @@
* 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/. */
/**
* /!\ FIXME: THIS IS A HORRID HACK which fakes both the mozL10n and webL10n
* objects and makes them returning the string id and serialized vars if any,
* for any requested string id.
* @type {Object}
*/
navigator.mozL10n = document.mozL10n = {
initialize: function(){},
(function() {
"use strict";
getDirection: function(){},
/**
* /!\ FIXME: THIS IS A HORRID HACK which fakes both the mozL10n and webL10n
* objects and makes them returning the string id and serialized vars if any,
* for any requested string id.
* @type {Object}
*/
navigator.mozL10n = document.mozL10n = {
initialize: function(){},
get: function(stringId, vars) {
getDirection: function(){},
// upcase the first letter
var readableStringId = stringId.replace(/^./, function(match) {
"use strict";
return match.toUpperCase();
}).replace(/_/g, " "); // and convert _ chars to spaces
get: function(stringId, vars) {
return "" + readableStringId + (vars ? ";" + JSON.stringify(vars) : "");
},
// upcase the first letter
var readableStringId = stringId.replace(/^./, function(match) {
return match.toUpperCase();
}).replace(/_/g, " "); // and convert _ chars to spaces
/* For timestamp formatting reasons. */
language: {
code: "en-US"
}
};
return "" + readableStringId + (vars ? ";" + JSON.stringify(vars) : "");
},
/* For timestamp formatting reasons. */
language: {
code: "en-US"
}
};
})();

View File

@ -114,52 +114,56 @@ var fakeContacts = [{
updated: 1406798311748
}];
/**
* Faking the mozLoop object which doesn't exist in regular web pages.
* @type {Object}
*/
navigator.mozLoop = {
ensureRegistered: function() {},
getAudioBlob: function(){},
getLoopPref: function(pref) {
switch(pref) {
// Ensure we skip FTE completely.
case "gettingStarted.seen":
case "contacts.gravatars.promo":
case "contextInConversations.enabled":
return true;
case "contacts.gravatars.show":
return false;
}
},
hasEncryptionKey: true,
setLoopPref: function(){},
releaseCallData: function() {},
copyString: function() {},
getUserAvatar: function(emailAddress) {
return "http://www.gravatar.com/avatar/" + (Math.ceil(Math.random() * 3) === 2 ?
"0a996f0fe2727ef1668bdb11897e4459" : "foo") + ".jpg?default=blank&s=40";
},
getSelectedTabMetadata: function(callback) {
callback({
previews: ["chrome://branding/content/about-logo.png"],
description: "sample webpage description",
url: "https://www.example.com"
});
},
contacts: {
getAll: function(callback) {
callback(null, [].concat(fakeContacts));
(function() {
"use strict";
/**
* Faking the mozLoop object which doesn't exist in regular web pages.
* @type {Object}
*/
navigator.mozLoop = {
ensureRegistered: function() {},
getAudioBlob: function(){},
getLoopPref: function(pref) {
switch(pref) {
// Ensure we skip FTE completely.
case "gettingStarted.seen":
case "contacts.gravatars.promo":
case "contextInConversations.enabled":
return true;
case "contacts.gravatars.show":
return false;
}
},
on: function() {}
},
rooms: {
getAll: function(version, callback) {
callback(null, [].concat(fakeRooms));
hasEncryptionKey: true,
setLoopPref: function(){},
releaseCallData: function() {},
copyString: function() {},
getUserAvatar: function(emailAddress) {
return "http://www.gravatar.com/avatar/" + (Math.ceil(Math.random() * 3) === 2 ?
"0a996f0fe2727ef1668bdb11897e4459" : "foo") + ".jpg?default=blank&s=40";
},
on: function() {}
},
fxAEnabled: true,
startAlerting: function() {},
stopAlerting: function() {}
};
getSelectedTabMetadata: function(callback) {
callback({
previews: ["chrome://branding/content/about-logo.png"],
description: "sample webpage description",
url: "https://www.example.com"
});
},
contacts: {
getAll: function(callback) {
callback(null, [].concat(fakeContacts));
},
on: function() {}
},
rooms: {
getAll: function(version, callback) {
callback(null, [].concat(fakeRooms));
},
on: function() {}
},
fxAEnabled: true,
startAlerting: function() {},
stopAlerting: function() {}
};
})();

View File

@ -12,159 +12,163 @@
*/
window.queuedFrames = [];
/**
* Renders this.props.children inside an <iframe>.
*
* Works by creating the iframe, waiting for that to finish, and then
* rendering the children inside that. Waits for a while in the hopes that the
* contents will have been rendered, and then fires a callback indicating that.
*
* @see onContentsRendered for the gory details about this.
*
* @type {ReactComponentFactory<P>}
*/
window.Frame = React.createClass({
propTypes: {
children: React.PropTypes.oneOfType([
React.PropTypes.element,
React.PropTypes.arrayOf(React.PropTypes.element)
]).isRequired,
className: React.PropTypes.string,
/* By default, <link rel="stylesheet> nodes from the containing frame's
head will be cloned into this iframe. However, if the link also has
a "class" attribute, we only clone it if that class attribute is the
same as cssClass. This allows us to avoid injecting stylesheets that
aren't intended for this rendering of this component. */
cssClass: React.PropTypes.string,
head: React.PropTypes.node,
height: React.PropTypes.number,
onContentsRendered: React.PropTypes.func,
style: React.PropTypes.object,
width: React.PropTypes.number
},
render: function() {
return React.createElement("iframe", {
style: this.props.style,
head: this.props.head,
width: this.props.width,
height: this.props.height,
className: this.props.className
});
},
componentDidMount: function() {
this.renderFrameContents();
},
renderFrameContents: function() {
function isStyleSheet(node) {
return node.tagName.toLowerCase() === "link" &&
node.getAttribute("rel") === "stylesheet";
}
(function() {
"use strict";
var childDoc = this.getDOMNode().contentDocument;
if (childDoc && childDoc.readyState === "complete") {
// Remove this from the queue.
window.queuedFrames.splice(window.queuedFrames.indexOf(this), 1);
/**
* Renders this.props.children inside an <iframe>.
*
* Works by creating the iframe, waiting for that to finish, and then
* rendering the children inside that. Waits for a while in the hopes that the
* contents will have been rendered, and then fires a callback indicating that.
*
* @see onContentsRendered for the gory details about this.
*
* @type {ReactComponentFactory<P>}
*/
window.Frame = React.createClass({
propTypes: {
children: React.PropTypes.oneOfType([
React.PropTypes.element,
React.PropTypes.arrayOf(React.PropTypes.element)
]).isRequired,
className: React.PropTypes.string,
/* By default, <link rel="stylesheet> nodes from the containing frame's
head will be cloned into this iframe. However, if the link also has
a "class" attribute, we only clone it if that class attribute is the
same as cssClass. This allows us to avoid injecting stylesheets that
aren't intended for this rendering of this component. */
cssClass: React.PropTypes.string,
head: React.PropTypes.node,
height: React.PropTypes.number,
onContentsRendered: React.PropTypes.func,
style: React.PropTypes.object,
width: React.PropTypes.number
},
render: function() {
return React.createElement("iframe", {
style: this.props.style,
head: this.props.head,
width: this.props.width,
height: this.props.height,
className: this.props.className
});
},
componentDidMount: function() {
this.renderFrameContents();
},
renderFrameContents: function() {
function isStyleSheet(node) {
return node.tagName.toLowerCase() === "link" &&
node.getAttribute("rel") === "stylesheet";
}
var iframeHead = childDoc.querySelector("head");
var parentHeadChildren = document.querySelector("head").children;
var childDoc = this.getDOMNode().contentDocument;
if (childDoc && childDoc.readyState === "complete") {
// Remove this from the queue.
window.queuedFrames.splice(window.queuedFrames.indexOf(this), 1);
[].forEach.call(parentHeadChildren, function(parentHeadNode) {
var iframeHead = childDoc.querySelector("head");
var parentHeadChildren = document.querySelector("head").children;
// if this node is a CSS stylesheet...
if (isStyleSheet(parentHeadNode)) {
// and it has a class different from the one that this frame does,
// return immediately instead of appending it. Note that this
// explicitly does not check for cssClass existence, because
// non-existence of cssClass will be different from a style
// element that does have a class on it, and we want it to return
// in that case.
if (parentHeadNode.hasAttribute("class") &&
parentHeadNode.getAttribute("class") !== this.props.cssClass) {
return;
[].forEach.call(parentHeadChildren, function(parentHeadNode) {
// if this node is a CSS stylesheet...
if (isStyleSheet(parentHeadNode)) {
// and it has a class different from the one that this frame does,
// return immediately instead of appending it. Note that this
// explicitly does not check for cssClass existence, because
// non-existence of cssClass will be different from a style
// element that does have a class on it, and we want it to return
// in that case.
if (parentHeadNode.hasAttribute("class") &&
parentHeadNode.getAttribute("class") !== this.props.cssClass) {
return;
}
}
iframeHead.appendChild(parentHeadNode.cloneNode(true));
}.bind(this));
var contents = React.createElement("div",
undefined,
this.props.head,
this.props.children
);
React.render(contents, childDoc.body, this.fireOnContentsRendered);
// Set the RTL mode. We assume for now that rtl is the only query parameter.
//
// See also "ShowCase" in ui-showcase.jsx
if (document.location.search === "?rtl=1") {
childDoc.documentElement.setAttribute("lang", "ar");
childDoc.documentElement.setAttribute("dir", "rtl");
}
} else {
// Queue it, only if it isn't already. We do need to set the timeout
// regardless, as this function can get re-entered several times.
if (window.queuedFrames.indexOf(this) === -1) {
window.queuedFrames.push(this);
}
setTimeout(this.renderFrameContents, 0);
}
},
/**
* Fires the onContentsRendered callback passed in via this.props,
* with the first argument set to the window global used by the iframe.
* This is useful in extracting things specific to that iframe (such as
* the matchMedia function) for use by code running in that iframe. Once
* React gets a more complete "context" feature:
*
* https://facebook.github.io/react/blog/2015/02/24/streamlining-react-elements.html#solution-make-context-parent-based-instead-of-owner-based
*
* we should be able to avoid reaching into the DOM like this.
*
* XXX wait a little while. After React has rendered this iframe (eg the
* virtual DOM cache gets flushed to the browser), there's still more stuff
* that needs to happen before layout completes. If onContentsRendered fires
* before that happens, the wrong sizes (eg remote stream vertical height
* of 0) are used to compute the position in the MediaSetupStream, resulting
* in everything looking wonky. One high likelihood candidate for the delay
* here involves loading/decode poster images, but even using link
* rel=prefetch on those isn't enough to workaround this problem, so there
* may be more.
*
* There doesn't appear to be a good cross-browser way to handle this
* at the moment without gross violation of encapsulation (see
* http://stackoverflow.com/questions/27241186/how-to-determine-when-document-has-loaded-after-loading-external-csshttp://stackoverflow.com/questions/27241186/how-to-determine-when-document-has-loaded-after-loading-external-css
* for discussion of a related problem.
*
* For now, just wait for multiple seconds. Yuck.
*/
fireOnContentsRendered: function() {
if (!this.props.onContentsRendered) {
return;
}
var contentWindow;
try {
contentWindow = this.getDOMNode().contentWindow;
if (!contentWindow) {
throw new Error("no content window returned");
}
iframeHead.appendChild(parentHeadNode.cloneNode(true));
}.bind(this));
var contents = React.createElement("div",
undefined,
this.props.head,
this.props.children
);
React.render(contents, childDoc.body, this.fireOnContentsRendered);
// Set the RTL mode. We assume for now that rtl is the only query parameter.
//
// See also "ShowCase" in ui-showcase.jsx
if (document.location.search === "?rtl=1") {
childDoc.documentElement.setAttribute("lang", "ar");
childDoc.documentElement.setAttribute("dir", "rtl");
}
} else {
// Queue it, only if it isn't already. We do need to set the timeout
// regardless, as this function can get re-entered several times.
if (window.queuedFrames.indexOf(this) === -1) {
window.queuedFrames.push(this);
}
setTimeout(this.renderFrameContents, 0);
}
},
/**
* Fires the onContentsRendered callback passed in via this.props,
* with the first argument set to the window global used by the iframe.
* This is useful in extracting things specific to that iframe (such as
* the matchMedia function) for use by code running in that iframe. Once
* React gets a more complete "context" feature:
*
* https://facebook.github.io/react/blog/2015/02/24/streamlining-react-elements.html#solution-make-context-parent-based-instead-of-owner-based
*
* we should be able to avoid reaching into the DOM like this.
*
* XXX wait a little while. After React has rendered this iframe (eg the
* virtual DOM cache gets flushed to the browser), there's still more stuff
* that needs to happen before layout completes. If onContentsRendered fires
* before that happens, the wrong sizes (eg remote stream vertical height
* of 0) are used to compute the position in the MediaSetupStream, resulting
* in everything looking wonky. One high likelihood candidate for the delay
* here involves loading/decode poster images, but even using link
* rel=prefetch on those isn't enough to workaround this problem, so there
* may be more.
*
* There doesn't appear to be a good cross-browser way to handle this
* at the moment without gross violation of encapsulation (see
* http://stackoverflow.com/questions/27241186/how-to-determine-when-document-has-loaded-after-loading-external-csshttp://stackoverflow.com/questions/27241186/how-to-determine-when-document-has-loaded-after-loading-external-css
* for discussion of a related problem.
*
* For now, just wait for multiple seconds. Yuck.
*/
fireOnContentsRendered: function() {
if (!this.props.onContentsRendered) {
return;
}
var contentWindow;
try {
contentWindow = this.getDOMNode().contentWindow;
if (!contentWindow) {
throw new Error("no content window returned");
} catch (ex) {
console.error("exception getting content window", ex);
}
} catch (ex) {
console.error("exception getting content window", ex);
// Using bind to construct a "partial function", where |this| is unchanged,
// but the first parameter is guaranteed to be set. Details at
// https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/Function/bind#Example.3A_Partial_Functions
setTimeout(this.props.onContentsRendered.bind(undefined, contentWindow),
3000);
},
componentDidUpdate: function() {
this.renderFrameContents();
},
componentWillUnmount: function() {
React.unmountComponentAtNode(React.findDOMNode(this).contentDocument.body);
}
// Using bind to construct a "partial function", where |this| is unchanged,
// but the first parameter is guaranteed to be set. Details at
// https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/Function/bind#Example.3A_Partial_Functions
setTimeout(this.props.onContentsRendered.bind(undefined, contentWindow),
3000);
},
componentDidUpdate: function() {
this.renderFrameContents();
},
componentWillUnmount: function() {
React.unmountComponentAtNode(React.findDOMNode(this).contentDocument.body);
}
});
});
})();

View File

@ -1219,6 +1219,8 @@
),
React.createElement(FramedExample, {
cssClass: "standalone",
dashed: true,
height: 480,
onContentsRendered: updatingSharingRoomStore.forcedUpdate,
summary: "Standalone room convo (has-participants, receivingScreenShare, 600x480)",

View File

@ -1219,6 +1219,8 @@
</FramedExample>
<FramedExample
cssClass="standalone"
dashed={true}
height={480}
onContentsRendered={updatingSharingRoomStore.forcedUpdate}
summary="Standalone room convo (has-participants, receivingScreenShare, 600x480)"

View File

@ -491,6 +491,65 @@ BrowserGlue.prototype = {
if (JSON.parse(data).disabled.length)
this._notifyUnsignedAddonsDisabled();
break;
case "autocomplete-did-enter-text":
this._handleURLBarTelemetry(subject.QueryInterface(Ci.nsIAutoCompleteInput));
break;
}
},
_handleURLBarTelemetry(input) {
if (!input ||
input.id != "urlbar" ||
input.inPrivateContext ||
input.popup.selectedIndex < 0) {
return;
}
let controller =
input.popup.view.QueryInterface(Ci.nsIAutoCompleteController);
let idx = input.popup.selectedIndex;
let value = controller.getValueAt(idx);
let action = input._parseActionUrl(value);
let actionType;
if (action) {
actionType =
action.type == "searchengine" && action.params.searchSuggestion ?
"searchsuggestion" :
action.type;
}
if (!actionType) {
let styles = controller.getStyleAt(idx).split(/\s+/);
let style = ["autofill", "tag", "bookmark"].find(s => styles.includes(s));
actionType = style || "history";
}
Services.telemetry
.getHistogramById("FX_URLBAR_SELECTED_RESULT_INDEX")
.add(idx);
// Ideally this would be a keyed histogram and we'd just add(actionType),
// but keyed histograms aren't currently shown on the telemetry dashboard
// (bug 1151756).
//
// You can add values but don't change any of the existing values.
// Otherwise you'll break our data.
let buckets = {
autofill: 0,
bookmark: 1,
history: 2,
keyword: 3,
searchengine: 4,
searchsuggestion: 5,
switchtab: 6,
tag: 7,
visiturl: 8,
};
if (actionType in buckets) {
Services.telemetry
.getHistogramById("FX_URLBAR_SELECTED_RESULT_TYPE")
.add(buckets[actionType]);
} else {
Cu.reportError("Unknown FX_URLBAR_SELECTED_RESULT_TYPE type: " +
actionType);
}
},
@ -540,6 +599,7 @@ BrowserGlue.prototype = {
os.addObserver(this, "restart-in-safe-mode", false);
os.addObserver(this, "flash-plugin-hang", false);
os.addObserver(this, "xpi-signature-changed", false);
os.addObserver(this, "autocomplete-did-enter-text", false);
this._flashHangCount = 0;
},
@ -588,6 +648,7 @@ BrowserGlue.prototype = {
#endif
os.removeObserver(this, "flash-plugin-hang");
os.removeObserver(this, "xpi-signature-changed");
os.removeObserver(this, "autocomplete-did-enter-text");
},
_onAppDefaults: function BG__onAppDefaults() {

View File

@ -507,13 +507,13 @@
if (!selection || (selection.index == -1)) {
let source = "unknown";
let type = "unknown";
let target = aEvent.originalTarget;
if (aEvent instanceof KeyboardEvent) {
type = "key";
if (this._textbox.selectedButton) {
source = "oneoff";
}
} else if (aEvent instanceof MouseEvent) {
let target = aEvent.originalTarget;
type = "mouse";
if (target.classList.contains("searchbar-engine-one-off-item")) {
source = "oneoff";
@ -523,11 +523,13 @@
}
} else if (aEvent instanceof XULCommandEvent) {
if (target.getAttribute("anonid") == "paste-and-search") {
aEngine = this.currentEngine;
source = "paste";
}
}
if (!aEngine) {
aEngine = this.currentEngine;
}
BrowserSearch.recordOneoffSearchInTelemetry(aEngine, source, type, where);
}

View File

@ -8,12 +8,14 @@ support-files =
[browser_backgroundTab.js]
skip-if = e10s # Bug 941428 - UITour.jsm not e10s friendly
[browser_no_tabs.js]
[browser_openSearchPanel.js]
skip-if = true # Bug 1113038 - Intermittent "Popup was opened"
[browser_UITour.js]
skip-if = os == "linux" || e10s # Intermittent failures, bug 951965
[browser_UITour2.js]
skip-if = e10s # Bug 1073247 - UITour.jsm not e10s friendly
# [browser_UITour3.js] Bug 1113038
# skip-if = os == "linux" || e10s # Linux: Bug 986760, Bug 989101; e10s: Bug 1073247 - UITour.jsm not e10s friendly
[browser_UITour3.js]
skip-if = os == "linux" || e10s # Linux: Bug 986760, Bug 989101; e10s: Bug 1073247 - UITour.jsm not e10s friendly
[browser_UITour_availableTargets.js]
skip-if = e10s # Bug 1073247 - UITour.jsm not e10s friendly
[browser_UITour_detach_tab.js]

View File

@ -176,24 +176,4 @@ let tests = [
// only happens after a tick.
waitForCondition(() => searchbar.value == "", done, "Search term cleared");
},
function test_openSearchPanel(done) {
let searchbar = document.getElementById("searchbar");
// If suggestions are enabled, the panel will attempt to use the network to connect
// to the suggestions provider, causing the test suite to fail.
Services.prefs.setBoolPref("browser.search.suggest.enabled", false);
registerCleanupFunction(() => {
Services.prefs.clearUserPref("browser.search.suggest.enabled");
});
ok(!searchbar.textbox.open, "Popup starts as closed");
gContentAPI.openSearchPanel(() => {
ok(searchbar.textbox.open, "Popup was opened");
searchbar.textbox.closePopup();
ok(!searchbar.textbox.open, "Popup was closed");
done();
});
},
];

View File

@ -0,0 +1,36 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
let gTestTab;
let gContentAPI;
let gContentWindow;
Components.utils.import("resource:///modules/UITour.jsm");
Components.utils.import("resource://gre/modules/Services.jsm");
function test() {
UITourTest();
}
let tests = [
function test_openSearchPanel(done) {
let searchbar = document.getElementById("searchbar");
// If suggestions are enabled, the panel will attempt to use the network to connect
// to the suggestions provider, causing the test suite to fail.
Services.prefs.setBoolPref("browser.search.suggest.enabled", false);
registerCleanupFunction(() => {
Services.prefs.clearUserPref("browser.search.suggest.enabled");
});
ok(!searchbar.textbox.open, "Popup starts as closed");
gContentAPI.openSearchPanel(() => {
ok(searchbar.textbox.open, "Popup was opened");
searchbar.textbox.closePopup();
ok(!searchbar.textbox.open, "Popup was closed");
done();
});
},
];

View File

@ -30,6 +30,7 @@ const Heritage = require("sdk/core/heritage");
const {setTimeout, clearTimeout, setInterval, clearInterval} = require("sdk/timers");
const {parseAttribute} = require("devtools/shared/node-attribute-parser");
const ELLIPSIS = Services.prefs.getComplexValue("intl.ellipsis", Ci.nsIPrefLocalizedString).data;
const {Task} = require("resource://gre/modules/Task.jsm");
Cu.import("resource://gre/modules/devtools/LayoutHelpers.jsm");
Cu.import("resource://gre/modules/devtools/Templater.jsm");
@ -1955,7 +1956,7 @@ MarkupContainer.prototype = {
/**
* On mouse up, stop dragging.
*/
_onMouseUp: function(event) {
_onMouseUp: Task.async(function*() {
this._isMouseDown = false;
if (!this.isDragging) {
@ -1967,13 +1968,14 @@ MarkupContainer.prototype = {
let dropTargetNodes = this.markup.dropTargetNodes;
if(!dropTargetNodes) {
if (!dropTargetNodes) {
return;
}
this.markup.walker.insertBefore(this.node, dropTargetNodes.parent,
dropTargetNodes.nextSibling);
},
yield this.markup.walker.insertBefore(this.node, dropTargetNodes.parent,
dropTargetNodes.nextSibling);
this.markup.emit("drop-completed");
}),
/**
* On mouse move, move the dragged element if any and indicate the drop target.

View File

@ -46,9 +46,13 @@ add_task(function*() {
yield scroll;
let dropCompleted = once(markup, "drop-completed");
container._onMouseUp(ev);
markup._onMouseUp(ev);
yield dropCompleted;
ok("Scroll event fired");
});
@ -58,4 +62,4 @@ function onScroll(win) {
resolve(e);
}
});
};
};

View File

@ -31,6 +31,8 @@ add_task(function*() {
yield wait(GRAB_DELAY + 1);
ok(el.isDragging, "isDragging true after GRAB_DELAY has passed");
let dropCompleted = once(inspector.markup, "drop-completed");
info("Simulating mouseUp on #test");
el._onMouseUp({
target: el.tagLine,
@ -38,5 +40,7 @@ add_task(function*() {
pageY: rect.y
});
yield dropCompleted;
is(el.isDragging, false, "isDragging false after mouseUp");
});

View File

@ -307,7 +307,10 @@ InplaceEditor.prototype = {
this._stopAutosize();
this.elt.style.display = this.originalDisplay;
this.elt.focus();
if (this.doc.activeElement == this.input) {
this.elt.focus();
}
this.input.remove();
this.input = null;

View File

@ -145,6 +145,7 @@ function CssHtmlTree(aStyleInspector, aPageStyle)
// Create bound methods.
this.focusWindow = this.focusWindow.bind(this);
this._onKeypress = this._onKeypress.bind(this);
this._onContextMenu = this._onContextMenu.bind(this);
this._contextMenuUpdate = this._contextMenuUpdate.bind(this);
this._onSelectAll = this._onSelectAll.bind(this);
@ -166,6 +167,7 @@ function CssHtmlTree(aStyleInspector, aPageStyle)
this.searchClearButton = doc.getElementById("computedview-searchinput-clear");
this.includeBrowserStylesCheckbox = doc.getElementById("browser-style-checkbox");
this.styleDocument.addEventListener("keypress", this._onKeypress);
this.styleDocument.addEventListener("mousedown", this.focusWindow);
this.element.addEventListener("click", this._onClick);
this.element.addEventListener("copy", this._onCopy);
@ -521,6 +523,20 @@ CssHtmlTree.prototype = {
}).then(null, (err) => console.error(err));
},
/**
* Handle the keypress event in the computed view.
*/
_onKeypress: function(event) {
let isOSX = Services.appinfo.OS == "Darwin";
if (((isOSX && event.metaKey && !event.ctrlKey && !event.altKey) ||
(!isOSX && event.ctrlKey && !event.metaKey && !event.altKey)) &&
event.code === "KeyF") {
this.searchField.focus();
event.preventDefault();
}
},
/**
* Called when the user enters a search term in the filter style search box.
*

View File

@ -1154,6 +1154,7 @@ function CssRuleView(aInspector, aDoc, aStore, aPageStyle) {
this._buildContextMenu = this._buildContextMenu.bind(this);
this._onContextMenu = this._onContextMenu.bind(this);
this._contextMenuUpdate = this._contextMenuUpdate.bind(this);
this._onKeypress = this._onKeypress.bind(this);
this._onAddRule = this._onAddRule.bind(this);
this._onSelectAll = this._onSelectAll.bind(this);
this._onCopy = this._onCopy.bind(this);
@ -1189,6 +1190,7 @@ function CssRuleView(aInspector, aDoc, aStore, aPageStyle) {
this.searchClearButton.hidden = true;
this.doc.addEventListener("keypress", this._onKeypress);
this.element.addEventListener("copy", this._onCopy);
this.element.addEventListener("contextmenu", this._onContextMenu);
this.addRuleButton.addEventListener("click", this._onAddRule);
@ -2634,6 +2636,20 @@ CssRuleView.prototype = {
_onTogglePseudoClass: function(event) {
let target = event.currentTarget;
this.inspector.togglePseudoClass(target.value);
},
/**
* Handle the keypress event in the rule view.
*/
_onKeypress: function(event) {
let isOSX = Services.appinfo.OS == "Darwin";
if (((isOSX && event.metaKey && !event.ctrlKey && !event.altKey) ||
(!isOSX && event.ctrlKey && !event.metaKey && !event.altKey)) &&
event.code === "KeyF") {
this.searchField.focus();
event.preventDefault();
}
}
};

View File

@ -679,10 +679,14 @@ let DirectoryLinksProvider = {
}
});
}
// Use up all views if the user clicked on a frequency capped tile
else if (action == "click") {
let {targetedSite, url} = sites[triggeringSiteIndex].link;
if (targetedSite) {
// any click action on a suggested tile should stop that tile suggestion
// click/block - user either removed a tile or went to a landing page
// pin - tile turned into history tile, should no longer be suggested
// unpin - the tile was pinned before, should not matter
else {
// suggested tile has targetedSite, or frecent_sites if it was pinned
let {frecent_sites, targetedSite, url} = sites[triggeringSiteIndex].link;
if (frecent_sites || targetedSite) {
this._setFrequencyCapClick(url);
}
}

View File

@ -131,8 +131,12 @@ this.ImportExport = {
}
let files = [];
debug("aApp=" + uneval(aApp));
if (aApp.origin.startsWith("app://")) {
files.push("update.webapp");
// Apps sideloaded from WebIDE don't have an update manifest.
if (!aApp.sideloaded) {
files.push("update.webapp");
}
files.push("application.zip");
} else {
files.push("manifest.webapp");
@ -215,18 +219,19 @@ this.ImportExport = {
_importPackagedApp: function(aZipReader, aManifestURL, aDir) {
debug("Importing packaged app " + aManifestURL);
if (!aZipReader.hasEntry("update.webapp")) {
throw "NoUpdateManifestFound";
}
if (!aZipReader.hasEntry("application.zip")) {
throw "NoPackageFound";
}
// The order matters, application.zip needs to be the last element.
let files = [];
aZipReader.hasEntry("update.webapp") && files.push("update.webapp");
files.push("application.zip");
// Extract application.zip and update.webapp
// We get manifest.webapp from application.zip itself.
let file;
["update.webapp", "application.zip"].forEach((aName) => {
files.forEach((aName) => {
file = aDir.clone();
file.append(aName);
aZipReader.extract(aName, file);

View File

@ -114,6 +114,9 @@ ConsoleAPIStorageService.prototype = {
* @param string aId
* The ID of the inner window for which the event occurred or "jsm" for
* messages logged from JavaScript modules..
* @param string aOuterId
* This ID is used as 3rd parameters for the console-api-log-event
* notification.
* @param object aEvent
* A JavaScript object you want to store.
*/

View File

@ -1072,8 +1072,9 @@ CancellableTransaction.prototype = {
break;
}
case kSmsDeletedObserverTopic: {
if (subject && subject.deletedMessageIds &&
subject.deletedMessageIds.indexOf(this.cancellableId) >= 0) {
let deletedInfo = subject.QueryInterface(Ci.nsIDeletedMessageInfo);
if (deletedInfo && deletedInfo.deletedMessageIds &&
deletedInfo.deletedMessageIds.indexOf(this.cancellableId) >= 0) {
this.cancelRunning(_MMS_ERROR_MESSAGE_DELETED);
}
break;

View File

@ -1307,19 +1307,19 @@ SmsSendingScheduler.prototype = {
observe: function(aSubject, aTopic, aData) {
switch (aTopic) {
case kSmsDeletedObserverTopic:
let deletedInfo = aSubject.QueryInterface(Ci.nsIDeletedMessageInfo);
if (DEBUG) {
debug("Observe " + kSmsDeletedObserverTopic + ": " +
JSON.stringify(aSubject));
JSON.stringify(deletedInfo));
}
if (aSubject && aSubject.deletedMessageIds) {
for (let id of aSubject.deletedMessageIds) {
for (let i = 0; i < this._queue.length; i++) {
if (this._queue[i].messageId === id) {
if (DEBUG) debug("Deleting message with id=" + id);
this._queue.splice(i, 1)[0].onCancel(
Ci.nsIMobileMessageCallback.NOT_FOUND_ERROR);
}
if (deletedInfo && deletedInfo.deletedMessageIds) {
for (let i = 0; i < this._queue.length; i++) {
let id = this._queue[i].messageId;
if (deletedInfo.deletedMessageIds.includes(id)) {
if (DEBUG) debug("Deleting message with id=" + id);
this._queue.splice(i, 1)[0].onCancel(
Ci.nsIMobileMessageCallback.NOT_FOUND_ERROR);
}
}
}

View File

@ -50,7 +50,7 @@ function test() {
aWindow.Services.obs.addObserver(
consoleObserver, "console-api-log-event", false);
aWindow.console.log("foo bar baz (private: " + aIsPrivateMode + ")");
aWindow.nativeConsole.log("foo bar baz (private: " + aIsPrivateMode + ")");
}, true);
// We expect that console API messages are always stored.

View File

@ -467,7 +467,6 @@ pref("app.faqURL", "http://www.mozilla.com/%LOCALE%/mobile/beta/faq/");
#else
pref("app.faqURL", "http://www.mozilla.com/%LOCALE%/mobile/faq/");
#endif
pref("app.marketplaceURL", "https://marketplace.firefox.com/");
// Name of alternate about: page for certificate errors (when undefined, defaults to about:neterror)
pref("security.alternate_certificate_error_page", "certerror");

View File

@ -13,7 +13,6 @@ import org.mozilla.gecko.util.StringUtils;
public class AboutPages {
// All of our special pages.
public static final String ADDONS = "about:addons";
public static final String APPS = "about:apps";
public static final String CONFIG = "about:config";
public static final String DOWNLOADS = "about:downloads";
public static final String FIREFOX = "about:firefox";

View File

@ -1687,14 +1687,20 @@ public class BrowserApp extends GeckoApp
final byte[] unwrapkB = Utils.hex2Byte(json.getString("unwrapBKey"));
final byte[] sessionToken = Utils.hex2Byte(json.getString("sessionToken"));
final byte[] keyFetchToken = Utils.hex2Byte(json.getString("keyFetchToken"));
final String authServerEndpoint =
json.optString("authServerEndpoint", FxAccountConstants.DEFAULT_AUTH_SERVER_ENDPOINT);
final String tokenServerEndpoint =
json.optString("tokenServerEndpoint", FxAccountConstants.DEFAULT_TOKEN_SERVER_ENDPOINT);
final String profileServerEndpoint =
json.optString("profileServerEndpoint", FxAccountConstants.DEFAULT_PROFILE_SERVER_ENDPOINT);
// TODO: handle choose what to Sync.
State state = new Engaged(email, uid, verified, unwrapkB, sessionToken, keyFetchToken);
fxAccount = AndroidFxAccount.addAndroidAccount(this,
email,
getProfile().getName(),
FxAccountConstants.DEFAULT_AUTH_SERVER_ENDPOINT,
FxAccountConstants.DEFAULT_TOKEN_SERVER_ENDPOINT,
FxAccountConstants.DEFAULT_PROFILE_SERVER_ENDPOINT,
authServerEndpoint,
tokenServerEndpoint,
profileServerEndpoint,
state,
AndroidFxAccount.DEFAULT_AUTHORITIES_TO_SYNC_AUTOMATICALLY_MAP);
} catch (Exception e) {
@ -3263,7 +3269,6 @@ public class BrowserApp extends GeckoApp
share.setVisible(shareVisible);
final boolean shareEnabled = StringUtils.isShareableUrl(url) && shareVisible;
share.setEnabled(shareEnabled);
MenuUtils.safeSetEnabled(aMenu, R.id.apps, RestrictedProfiles.isAllowed(this, RestrictedProfiles.Restriction.DISALLOW_INSTALL_APPS));
MenuUtils.safeSetEnabled(aMenu, R.id.addons, RestrictedProfiles.isAllowed(this, RestrictedProfiles.Restriction.DISALLOW_INSTALL_EXTENSION));
MenuUtils.safeSetEnabled(aMenu, R.id.downloads, RestrictedProfiles.isAllowed(this, RestrictedProfiles.Restriction.DISALLOW_DOWNLOADS));
@ -3481,11 +3486,6 @@ public class BrowserApp extends GeckoApp
return true;
}
if (itemId == R.id.apps) {
Tabs.getInstance().loadUrlInTab(AboutPages.APPS);
return true;
}
if (itemId == R.id.downloads) {
Tabs.getInstance().loadUrlInTab(AboutPages.DOWNLOADS);
return true;

View File

@ -424,7 +424,7 @@ extra_packages := $(subst $(NULL) ,:,$(strip $(extra_packages)))
# thinking aapt's outputs are stale. This is safe because Make
# removes the target file if any recipe command fails.
CONSTRAINED_AAPT_CONFIGURATIONS := mdpi,hdpi
CONSTRAINED_AAPT_CONFIGURATIONS := hdpi
define aapt_command
$(1): $$(call mkdir_deps,$(filter-out ./,$(dir $(3) $(4) $(5)))) $(2)

View File

@ -330,7 +330,6 @@ size. -->
<!ENTITY addons "Add-ons">
<!ENTITY logins "Logins">
<!ENTITY downloads "Downloads">
<!ENTITY apps "Apps">
<!ENTITY char_encoding "Character Encoding">
<!ENTITY share "Share">

Binary file not shown.

Before

Width:  |  Height:  |  Size: 673 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 281 B

After

Width:  |  Height:  |  Size: 281 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 281 B

After

Width:  |  Height:  |  Size: 281 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 368 B

After

Width:  |  Height:  |  Size: 367 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 368 B

After

Width:  |  Height:  |  Size: 367 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 500 B

After

Width:  |  Height:  |  Size: 499 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 500 B

After

Width:  |  Height:  |  Size: 500 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 777 B

View File

@ -7,7 +7,6 @@
<merge
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/tab_queue_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipChildren="false"

View File

@ -107,10 +107,6 @@
<item android:id="@+id/logins"
android:title="@string/logins"/>
<item android:id="@+id/apps"
android:icon="@drawable/ic_menu_apps"
android:title="@string/apps"/>
<item android:id="@+id/new_guest_session"
android:icon="@drawable/ic_menu_guest"
android:visible="false"

View File

@ -107,10 +107,6 @@
<item android:id="@+id/logins"
android:title="@string/logins"/>
<item android:id="@+id/apps"
android:icon="@drawable/ic_menu_apps"
android:title="@string/apps"/>
<item android:id="@+id/new_guest_session"
android:icon="@drawable/ic_menu_guest"
android:visible="false"

View File

@ -108,10 +108,6 @@
<item android:id="@+id/logins"
android:title="@string/logins"/>
<item android:id="@+id/apps"
android:icon="@drawable/ic_menu_apps"
android:title="@string/apps"/>
<item android:id="@+id/new_guest_session"
android:icon="@drawable/ic_menu_guest"
android:visible="false"

View File

@ -55,9 +55,6 @@
<item android:id="@+id/logins"
android:title="@string/logins"/>
<item android:id="@+id/apps"
android:title="@string/apps"/>
<item android:id="@+id/char_encoding"
android:visible="false"
android:title="@string/char_encoding"/>

View File

@ -310,7 +310,6 @@
<string name="addons">&addons;</string>
<string name="logins">&logins;</string>
<string name="downloads">&downloads;</string>
<string name="apps">&apps;</string>
<string name="char_encoding">&char_encoding;</string>
<string name="new_tab">&new_tab;</string>
<string name="new_private_tab">&new_private_tab;</string>

View File

@ -1,162 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
*
* 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/.
*
* ***** END LICENSE BLOCK ***** */
/*globals gChromeWin */
let Ci = Components.interfaces, Cc = Components.classes, Cu = Components.utils;
Cu.import("resource://gre/modules/Services.jsm")
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/AppsUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "WebappManager", "resource://gre/modules/WebappManager.jsm");
const DEFAULT_ICON = "chrome://browser/skin/images/default-app-icon.png";
let gStrings = Services.strings.createBundle("chrome://browser/locale/aboutApps.properties");
XPCOMUtils.defineLazyGetter(window, "gChromeWin", function() {
return window.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIDocShellTreeItem)
.rootTreeItem
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindow)
.QueryInterface(Ci.nsIDOMChromeWindow);
});
document.addEventListener("DOMContentLoaded", onLoad, false);
var AppsUI = {
uninstall: null,
shortcut: null
};
function openLink(aEvent) {
try {
let formatter = Cc["@mozilla.org/toolkit/URLFormatterService;1"].getService(Ci.nsIURLFormatter);
let url = formatter.formatURLPref(aEvent.currentTarget.getAttribute("pref"));
let BrowserApp = gChromeWin.BrowserApp;
BrowserApp.addTab(url, { selected: true, parentId: BrowserApp.selectedTab.id });
} catch (ex) {}
}
function checkForUpdates(aEvent) {
WebappManager.checkForUpdates(true);
}
let ContextMenus = {
target: null,
init: function() {
document.addEventListener("contextmenu", this, false);
document.getElementById("uninstallLabel").addEventListener("click", this.uninstall.bind(this), false);
},
handleEvent: function(event) {
// store the target of context menu events so that we know which app to act on
this.target = event.target;
while (!this.target.hasAttribute("contextmenu")) {
this.target = this.target.parentNode;
}
},
uninstall: function() {
navigator.mozApps.mgmt.uninstall(this.target.app);
this.target = null;
}
};
function onLoad(aEvent) {
let elmts = document.querySelectorAll("[pref]");
for (let i = 0; i < elmts.length; i++) {
elmts[i].addEventListener("click", openLink, false);
}
document.getElementById("update-item").addEventListener("click", checkForUpdates, false);
navigator.mozApps.mgmt.oninstall = onInstall;
navigator.mozApps.mgmt.onuninstall = onUninstall;
updateList();
ContextMenus.init();
// XXX - Hack to fix bug 985867 for now
document.addEventListener("touchstart", function() { });
}
function updateList() {
let grid = document.getElementById("appgrid");
while (grid.lastChild) {
grid.removeChild(grid.lastChild);
}
let request = navigator.mozApps.mgmt.getAll();
request.onsuccess = function() {
for (let i = 0; i < request.result.length; i++)
addApplication(request.result[i]);
if (request.result.length)
document.getElementById("main-container").classList.remove("hidden");
}
}
function addApplication(aApp) {
let list = document.getElementById("appgrid");
let manifest = new ManifestHelper(aApp.manifest, aApp.origin, aApp.manifestURL);
let container = document.createElement("div");
container.className = "app list-item";
container.setAttribute("contextmenu", "appmenu");
container.setAttribute("id", "app-" + aApp.manifestURL);
container.setAttribute("title", manifest.name);
let img = document.createElement("img");
img.src = manifest.biggestIconURL() || DEFAULT_ICON;
img.onerror = function() {
// If the image failed to load, and it was not our default icon, attempt to
// use our default as a fallback.
if (img.src != DEFAULT_ICON) {
img.src = DEFAULT_ICON;
}
}
img.setAttribute("title", manifest.name);
let title = document.createElement("div");
title.appendChild(document.createTextNode(manifest.name));
container.appendChild(img);
container.appendChild(title);
list.appendChild(container);
container.addEventListener("click", function(aEvent) {
aApp.launch();
}, false);
container.app = aApp;
container.manifest = manifest;
}
function onInstall(aEvent) {
let node = document.getElementById("app-" + aEvent.application.manifestURL);
if (node)
return;
addApplication(aEvent.application);
document.getElementById("main-container").classList.remove("hidden");
}
function onUninstall(aEvent) {
let node = document.getElementById("app-" + aEvent.application.manifestURL);
if (node) {
let parent = node.parentNode;
parent.removeChild(node);
if (!parent.firstChild)
document.getElementById("main-container").classList.add("hidden");
}
}

View File

@ -1,61 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html [
<!ENTITY % htmlDTD
PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"DTD/xhtml1-strict.dtd">
%htmlDTD;
<!ENTITY % globalDTD SYSTEM "chrome://global/locale/global.dtd">
%globalDTD;
<!ENTITY % aboutAppsDTD SYSTEM "chrome://browser/locale/aboutApps.dtd">
%aboutAppsDTD;
<!ENTITY % browserDTD SYSTEM "chrome://browser/locale/browser.dtd" >
%browserDTD;
]>
<!-- 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 xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>&aboutApps.title2;</title>
<meta name="viewport" content="width=device-width; user-scalable=0" />
<link rel="icon" type="image/png" sizes="64x64" href="chrome://branding/content/favicon64.png" />
<link rel="stylesheet" type="text/css" href="chrome://browser/skin/aboutBase.css" media="all" />
<link rel="stylesheet" type="text/css" href="chrome://browser/skin/aboutApps.css" media="all" />
<script type="text/javascript;version=1.8" src="chrome://browser/content/aboutApps.js"></script>
</head>
<body dir="&locale.dir;">
<menu type="context" id="appmenu">
<menuitem id="uninstallLabel" label="&aboutApps.uninstall;"></menuitem>
</menu>
<div class="header">
<div>&aboutApps.header;</div>
</div>
<div id="main-container" class="hidden">
<div>
<div class="spacer" id="spacer1"> </div>
<div id="appgrid"/>
<div class="spacer" id="spacer1"> </div>
</div>
</div>
<div class="list-item" role="button" pref="app.marketplaceURL">
<img class="icon" src="chrome://browser/skin/images/marketplace-logo.png" />
<div class="inner">
<div id="browse-title" class="title">&aboutApps.browseMarketplace;</div>
</div>
</div>
<div class="list-item" id="update-item" role="button">
<img class="icon" src="chrome://browser/skin/images/update.png" />
<div class="inner">
<div id="browse-title" class="title">&aboutApps.checkForUpdates;</div>
</div>
</div>
</body>
</html>

View File

@ -24,8 +24,6 @@ chrome.jar:
content/Reader.js (content/Reader.js)
content/aboutHome.xhtml (content/aboutHome.xhtml)
content/aboutRights.xhtml (content/aboutRights.xhtml)
content/aboutApps.xhtml (content/aboutApps.xhtml)
content/aboutApps.js (content/aboutApps.js)
content/blockedSite.xhtml (content/blockedSite.xhtml)
content/languages.properties (content/languages.properties)
content/browser.xul (content/browser.xul)

View File

@ -53,10 +53,6 @@ let modules = {
uri: "chrome://browser/content/aboutHome.xhtml",
privileged: false
},
apps: {
uri: "chrome://browser/content/aboutApps.xhtml",
privileged: true
},
downloads: {
uri: "chrome://browser/content/aboutDownloads.xhtml",
privileged: true

View File

@ -1,10 +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/. -->
<!ENTITY aboutApps.title2 "Apps">
<!ENTITY aboutApps.header "Your Apps">
<!ENTITY aboutApps.browseMarketplace "Browse the Firefox Marketplace">
<!ENTITY aboutApps.uninstall "Uninstall">
<!ENTITY aboutApps.checkForUpdates "Check for Updates">

View File

@ -9,7 +9,6 @@
locale/@AB_CD@/browser/about.dtd (%chrome/about.dtd)
locale/@AB_CD@/browser/aboutAddons.dtd (%chrome/aboutAddons.dtd)
locale/@AB_CD@/browser/aboutAddons.properties (%chrome/aboutAddons.properties)
locale/@AB_CD@/browser/aboutApps.dtd (%chrome/aboutApps.dtd)
#ifdef MOZ_DEVICES
locale/@AB_CD@/browser/aboutDevices.dtd (%chrome/aboutDevices.dtd)
#endif

View File

@ -33,7 +33,6 @@ public class StringHelper {
public final String ABOUT_HOME_URL = "about:home";
public final String ABOUT_ADDONS_URL = "about:addons";
public static final String ABOUT_LOGINS_URL = "about:logins";
public final String ABOUT_APPS_URL = "about:apps";
public final String ABOUT_ABOUT_URL = "about:about";
public final String ABOUT_SCHEME = "about:";
@ -191,7 +190,6 @@ public class StringHelper {
public final String DOWNLOADS_LABEL;
public final String ADDONS_LABEL;
public final String LOGINS_LABEL;
public final String APPS_LABEL;
public final String SETTINGS_LABEL;
public final String GUEST_MODE_LABEL;
public final String TAB_QUEUE_LABEL;
@ -368,7 +366,6 @@ public class StringHelper {
DOWNLOADS_LABEL = res.getString(R.string.downloads);
ADDONS_LABEL = res.getString(R.string.addons);
LOGINS_LABEL = res.getString(R.string.logins);
APPS_LABEL = res.getString(R.string.apps);
SETTINGS_LABEL = res.getString(R.string.settings);
GUEST_MODE_LABEL = res.getString(R.string.new_guest_session);
TAB_QUEUE_LABEL = res.getString(R.string.pref_tab_queue_title);

View File

@ -19,8 +19,7 @@ public class testSystemPages extends PixelTest {
mStringHelper.ABOUT_HEALTHREPORT_URL, mStringHelper.ABOUT_SCHEME
};
// Pages to be tested from the menu and their expected urls. This if of the form { {{ <path to item> }, { <expected url> }}* }
String menuItems [][][] = {{{ mStringHelper.APPS_LABEL }, { mStringHelper.ABOUT_APPS_URL }},
{{ mStringHelper.DOWNLOADS_LABEL }, { mStringHelper.ABOUT_DOWNLOADS_URL}},
String menuItems [][][] = {{{ mStringHelper.DOWNLOADS_LABEL }, { mStringHelper.ABOUT_DOWNLOADS_URL}},
{{ mStringHelper.LOGINS_LABEL}, { StringHelper.ABOUT_LOGINS_URL }},
{{ mStringHelper.ADDONS_LABEL }, { mStringHelper.ABOUT_ADDONS_URL }},
{{ mStringHelper.SETTINGS_LABEL, mStringHelper.MOZILLA_SECTION_LABEL, mStringHelper.ABOUT_LABEL }, { mStringHelper.ABOUT_SCHEME }},

View File

@ -1,43 +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/. */
.app:active {
background-color: #febc2b;
}
#main-container {
padding: 2em;
background-color: #EEF2F5;
border-bottom: 1px solid #BAC2AC;
}
.hidden {
display: none;
}
.spacer {
clear: both;
}
.app {
float: left;
cursor: pointer;
text-align: center;
margin: 1em;
width: 5.6em;
height: 6.7em;
font-size: .8em;
background-color: transparent;
border: none;
}
.app img {
width: 5em;
height: 5em;
pointer-events: none;
}
.app div {
pointer-events: none;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 708 B

View File

@ -9,7 +9,6 @@ chrome.jar:
skin/aboutPage.css (aboutPage.css)
skin/about.css (about.css)
* skin/aboutAddons.css (aboutAddons.css)
skin/aboutApps.css (aboutApps.css)
* skin/aboutBase.css (aboutBase.css)
#ifdef MOZ_DEVICES
skin/aboutDevices.css (aboutDevices.css)
@ -77,7 +76,6 @@ chrome.jar:
skin/images/certerror-warning.png (images/certerror-warning.png)
skin/images/errorpage-larry-white.png (images/errorpage-larry-white.png)
skin/images/errorpage-larry-black.png (images/errorpage-larry-black.png)
skin/images/marketplace-logo.png (images/marketplace-logo.png)
skin/images/throbber.png (images/throbber.png)
skin/images/search-clear-30.png (images/search-clear-30.png)
skin/images/play-hdpi.png (images/play-hdpi.png)
@ -120,7 +118,6 @@ chrome.jar:
skin/images/reader-style-icon-xhdpi.png (images/reader-style-icon-xhdpi.png)
skin/images/reader-style-icon-xxhdpi.png (images/reader-style-icon-xxhdpi.png)
skin/images/privatebrowsing-mask.png (images/privatebrowsing-mask.png)
skin/images/update.png (images/update.png)
skin/images/icon_floaty_hdpi.png (images/icon_floaty_hdpi.png)
skin/images/icon_floaty_mdpi.png (images/icon_floaty_mdpi.png)
skin/images/icon_floaty_xhdpi.png (images/icon_floaty_xhdpi.png)

View File

@ -29,6 +29,10 @@ XPCOMUtils.defineLazyModuleGetter(this, "ContentSearch",
XPCOMUtils.defineLazyModuleGetter(this, "SelfSupportBackend",
"resource:///modules/SelfSupportBackend.jsm");
var nativeConsole = console;
XPCOMUtils.defineLazyModuleGetter(this, "console",
"resource://gre/modules/devtools/Console.jsm");
const SIMPLETEST_OVERRIDES =
["ok", "is", "isnot", "todo", "todo_is", "todo_isnot", "info", "expectAssertions", "requestCompleteLog"];

View File

@ -29,6 +29,8 @@ config = {
],
"pip_index": False,
"in_tree_config": "config/mozharness/linux_config.py",
"buildbot_json_path": "buildprops.json",
"default_blob_upload_servers": [

View File

@ -302,6 +302,34 @@ config = {
"url": "https://api.pub.build.mozilla.org/mapper",
"project": "gecko-dev"
},
}, {
"repo": "https://hg.mozilla.org/releases/mozilla-b2g37_v2_2r",
"revision": "default",
"repo_name": "mozilla-b2g37_v2_2r",
"targets": [{
"target_dest": "beagle/.git",
"vcs": "git",
"test_push": True,
}, {
"target_dest": "gitmo-beagle",
}, {
"target_dest": "github-beagle",
}],
"vcs": "hg",
"branch_config": {
"branches": {
"default": "b2g37_v2_2r",
},
},
"tag_config": {
"tag_regexes": [
"^B2G_",
],
},
"mapper": {
"url": "https://api.pub.build.mozilla.org/mapper",
"project": "gecko-dev"
},
}, {
"repo": "https://hg.mozilla.org/releases/mozilla-b2g32_v2_0",
"revision": "default",

View File

@ -1,4 +1,4 @@
{
"repo": "https://hg.mozilla.org/build/mozharness",
"revision": "4d855a6835ed"
"revision": "4a31e6739409"
}

View File

@ -1054,7 +1054,6 @@ or run without that action (ie: --no-{action})"
os.path.join(dirs['abs_src_dir'], '.mozconfig'))
self.info("mozconfig content:")
with open(abs_src_mozconfig) as mozconfig:
next(mozconfig)
for line in mozconfig:
self.info(line)
else:

View File

@ -18,9 +18,10 @@ from mozharness.base.python import (
virtualenv_config_options,
)
from mozharness.mozilla.vcstools import VCSToolsScript
from mozharness.mozilla.purge import PurgeMixin
class FirefoxUITests(VCSToolsScript, VirtualenvMixin):
class FirefoxUITests(VCSToolsScript, VirtualenvMixin, PurgeMixin):
config_options = [
[['--firefox-ui-repo'], {
'dest': 'firefox_ui_repo',
@ -33,12 +34,22 @@ class FirefoxUITests(VCSToolsScript, VirtualenvMixin):
}],
] + copy.deepcopy(virtualenv_config_options)
def __init__(self, config_options=[], all_actions=[], **kwargs):
def __init__(self,
config={},
config_options=[],
all_actions=[],
**kwargs):
default_config = {
'purge_minsize': 2,
}
default_config.update(config)
self.config_options += config_options
if all_actions is None:
# Default actions
all_actions = [
'purge-builds',
'clobber',
'checkout',
'create-virtualenv',
@ -47,6 +58,8 @@ class FirefoxUITests(VCSToolsScript, VirtualenvMixin):
super(FirefoxUITests, self).__init__(
config_options=self.config_options,
require_config_file=True,
config=default_config,
all_actions=all_actions,
**kwargs
)

View File

@ -92,6 +92,7 @@ class FirefoxUIUpdates(FirefoxUITests):
super(FirefoxUIUpdates, self).__init__(
config_options=config_options,
all_actions=[
'purge-builds',
'clobber',
'checkout',
'create-virtualenv',

View File

@ -228,26 +228,32 @@ class LuciddreamTest(TestingMixin, MercurialScript, MozbaseMixin, BaseScript,
ld_parser = self.parser_class(config=self.config,
log_obj=self.log_obj,
error_list=BaseErrorList)
raw_log = os.path.join(dirs['abs_work_dir'], 'luciddream_raw.log')
cmd = [self.query_python_path('python'),
os.path.join(ld_dir, 'luciddream', 'runluciddream.py'),
'--log-raw=%s' % raw_log
os.path.join(ld_dir, 'luciddream', 'runluciddream.py')
]
str_format_values = {
'browser_path': self.binary_path,
'raw_log_file': os.path.join(dirs['abs_work_dir'], 'luciddream_raw.log'),
'test_manifest': os.path.join(ld_dir, 'example-tests', 'luciddream.ini')
}
if self.config.get('emulator_url'):
cmd += ['--b2gpath', dirs['abs_b2g-distro_dir'],
'--browser-path', self.binary_path,
]
str_format_values['emulator_path'] = dirs['abs_b2g-distro_dir']
else:
if self.config.get('b2gdesktop_url'):
bin_path = os.path.join(dirs['abs_b2g_desktop'], 'b2g', 'b2g')
str_format_values['fxos_desktop_path'] = os.path.join(dirs['abs_b2g_desktop'], 'b2g', 'b2g')
else:
bin_path = self.config.get('b2gdesktop_path')
cmd += ['--b2g-desktop-path', bin_path,
'--browser-path', self.binary_path,
'--gaia-profile', os.path.join(dirs['abs_gaia_dir'], 'profile'),
]
cmd += [os.path.join(ld_dir, 'example-tests', 'luciddream.ini')]
str_format_values['fxos_desktop_path'] = self.config.get('b2gdesktop_path')
str_format_values['gaia_profile'] = os.path.join(dirs['abs_gaia_dir'], 'profile')
suite = 'luciddream-emulator' if self.config.get('emulator_url') else 'luciddream-b2gdt'
options = self.tree_config['suite_definitions'][suite]['options']
for option in options:
option = option % str_format_values
if not option.endswith('None'):
cmd.append(option)
code = self.run_command(cmd, env=env,
output_timeout=1000,

View File

@ -4223,6 +4223,18 @@
"extended_statistics_ok": true,
"description": "Session restore: Time spent blocking the main thread while restoring a window state (ms)"
},
"FX_URLBAR_SELECTED_RESULT_INDEX": {
"expires_in_version": "45",
"kind": "enumerated",
"n_values": 17,
"description": "Firefox: The index of the selected result in the URL bar popup"
},
"FX_URLBAR_SELECTED_RESULT_TYPE": {
"expires_in_version": "45",
"kind": "enumerated",
"n_values": 14,
"description": "Firefox: The type of the selected result in the URL bar popup"
},
"INNERWINDOWS_WITH_MUTATION_LISTENERS": {
"expires_in_version": "never",
"kind": "boolean",
@ -4769,6 +4781,20 @@
"kind": "boolean",
"description": "New tab page is enhanced (showing suggestions)."
},
"NEWTAB_PAGE_LIFE_SPAN": {
"expires_in_version": "default",
"kind": "exponential",
"high": "1200",
"n_buckets": 100,
"description": "Life-span of a new tab without suggested tile: time delta between first-visible and unload events (half-seconds)."
},
"NEWTAB_PAGE_LIFE_SPAN_SUGGESTED": {
"expires_in_version": "default",
"kind": "exponential",
"high": "1200",
"n_buckets": 100,
"description": "Life-span of a new tab with suggested tile: time delta between first-visible and unload events (half-seconds)."
},
"NEWTAB_PAGE_PINNED_SITES_COUNT": {
"expires_in_version": "default",
"kind": "enumerated",

View File

@ -803,6 +803,7 @@ let Impl = {
haveDelayedInitTask: !!this._delayedInitTask,
shutdownBarrier: this._shutdownBarrier.state,
connectionsBarrier: this._connectionsBarrier.state,
sendModule: TelemetrySend.getShutdownState(),
};
},

View File

@ -253,6 +253,13 @@ this.TelemetrySend = {
setTestModeEnabled: function(testing) {
TelemetrySendImpl.setTestModeEnabled(testing);
},
/**
* This returns state info for this module for AsyncShutdown timeout diagnostics.
*/
getShutdownState: function() {
return TelemetrySendImpl.getShutdownState();
},
};
let CancellableTimeout = {
@ -305,6 +312,8 @@ let SendScheduler = {
_backoffDelay: SEND_TICK_DELAY,
_shutdown: false,
_sendTask: null,
// A string that tracks the last seen send task state, null if it never ran.
_sendTaskState: null,
_logger: null,
@ -377,6 +386,7 @@ let SendScheduler = {
},
_doSendTask: Task.async(function*() {
this._sendTaskState = "send task started";
this._backoffDelay = SEND_TICK_DELAY;
this._sendsFailed = false;
@ -386,9 +396,11 @@ let SendScheduler = {
for (;;) {
this._log.trace("_doSendTask iteration");
this._sendTaskState = "start iteration";
if (this._shutdown) {
this._log.trace("_doSendTask - shutting down, bailing out");
this._sendTaskState = "bail out - shutdown check";
return;
}
@ -405,6 +417,7 @@ let SendScheduler = {
// Bail out if there is nothing to send.
if ((pending.length == 0) && (current.length == 0)) {
this._log.trace("_doSendTask - no pending pings, bailing out");
this._sendTaskState = "bail out - no pings to send";
return;
}
@ -413,6 +426,8 @@ let SendScheduler = {
if (this.isThrottled()) {
const nextPingSendTime = this._getNextPingSendTime(now);
this._log.trace("_doSendTask - throttled, delaying ping send to " + new Date(nextPingSendTime));
this._sendTaskState = "wait for throttling to pass";
const delay = nextPingSendTime - now.getTime();
const cancelled = yield CancellableTimeout.promiseWaitOnTimeout(delay);
if (cancelled) {
@ -430,10 +445,12 @@ let SendScheduler = {
this._sendsFailed = false;
const sendStartTime = Policy.now();
this._sendTaskState = "wait on ping sends";
yield TelemetrySendImpl.sendPings(current, [for (p of sending) p.id]);
if (this._shutdown || (TelemetrySend.pendingPingCount == 0)) {
this._log.trace("_doSendTask - bailing out after sending, shutdown: " + this._shutdown +
", pendingPingCount: " + TelemetrySend.pendingPingCount);
this._sendTaskState = "bail out - shutdown & pending check after send";
return;
}
@ -458,6 +475,7 @@ let SendScheduler = {
}
this._log.trace("_doSendTask - waiting for next send opportunity, timeout is " + nextSendDelay)
this._sendTaskState = "wait on next send opportunity";
const cancelled = yield CancellableTimeout.promiseWaitOnTimeout(nextSendDelay);
if (cancelled) {
this._log.trace("_doSendTask - batch send wait was cancelled, resetting backoff timer");
@ -491,13 +509,21 @@ let SendScheduler = {
// We spread those ping sends out between |midnight| and |midnight + midnightPingFuzzingDelay|.
return midnight.getTime() + Policy.midnightPingFuzzingDelay();
},
getShutdownState: function() {
return {
shutdown: this._shutdown,
hasSendTask: !!this._sendTask,
sendsFailed: this._sendsFailed,
sendTaskState: this._sendTaskState,
backoffDelay: this._backoffDelay,
};
},
};
let TelemetrySendImpl = {
_sendingEnabled: false,
_logger: null,
// Timer for scheduled ping sends.
_pingSendTimer: null,
// This tracks all pending ping requests to the server.
_pendingPingRequests: new Map(),
// This tracks all the pending async ping activity.
@ -1017,4 +1043,15 @@ let TelemetrySendImpl = {
current.reverse();
return current;
},
getShutdownState: function() {
return {
sendingEnabled: this._sendingEnabled,
pendingPingRequestCount: this._pendingPingRequests.size,
pendingPingActivityCount: this._pendingPingActivity.size,
unpersistedPingCount: this._currentPings.size,
persistedPingCount: TelemetryStorage.getPendingPingList().length,
schedulerState: SendScheduler.getShutdownState(),
};
},
};

View File

@ -450,6 +450,12 @@ TabSources.prototype = {
* Sets the source map's sourceRoot to be relative to the source map url.
*/
_setSourceMapRoot: function (aSourceMap, aAbsSourceMapURL, aScriptURL) {
// No need to do this fiddling if we won't be fetching any sources over the
// wire.
if (aSourceMap.hasContentsOfAllSources()) {
return;
}
const base = this._dirname(
aAbsSourceMapURL.indexOf("data:") === 0
? aScriptURL

View File

@ -0,0 +1,79 @@
(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
"use strict";
var add = require("./lib/add");
var subtract = require("./lib/subtract");
var upperCase = require("upper-case");
(function () {
return add(1, 2);
});
},{"./lib/add":2,"./lib/subtract":3,"upper-case":4}],2:[function(require,module,exports){
"use strict";
module.exports = function (a, b) {
return a + b;
};
},{}],3:[function(require,module,exports){
"use strict";
module.exports = function (a, b) {
return a - b;
};
},{}],4:[function(require,module,exports){
/**
* Special language-specific overrides.
*
* Source: ftp://ftp.unicode.org/Public/UCD/latest/ucd/SpecialCasing.txt
*
* @type {Object}
*/
var LANGUAGES = {
tr: {
regexp: /[\u0069]/g,
map: {
'\u0069': '\u0130'
}
},
az: {
regexp: /[\u0069]/g,
map: {
'\u0069': '\u0130'
}
},
lt: {
regexp: /[\u0069\u006A\u012F]\u0307|\u0069\u0307[\u0300\u0301\u0303]/g,
map: {
'\u0069\u0307': '\u0049',
'\u006A\u0307': '\u004A',
'\u012F\u0307': '\u012E',
'\u0069\u0307\u0300': '\u00CC',
'\u0069\u0307\u0301': '\u00CD',
'\u0069\u0307\u0303': '\u0128'
}
}
}
/**
* Upper case a string.
*
* @param {String} str
* @return {String}
*/
module.exports = function (str, locale) {
var lang = LANGUAGES[locale]
str = str == null ? '' : String(str)
if (lang) {
str = str.replace(lang.regexp, function (m) { return lang.map[m] })
}
return str.toUpperCase()
}
},{}]},{},[1])
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3Vzci9sb2NhbC9saWIvbm9kZV9tb2R1bGVzL2Jyb3dzZXJpZnkvbm9kZV9tb2R1bGVzL2Jyb3dzZXItcGFjay9fcHJlbHVkZS5qcyIsIi9Vc2Vycy9qc2FudGVsbC9EZXYvc291cmNlLW1hcC10ZXN0L2luZGV4LmpzIiwiL1VzZXJzL2pzYW50ZWxsL0Rldi9zb3VyY2UtbWFwLXRlc3QvbGliL2FkZC5qcyIsIi9Vc2Vycy9qc2FudGVsbC9EZXYvc291cmNlLW1hcC10ZXN0L2xpYi9zdWJ0cmFjdC5qcyIsIm5vZGVfbW9kdWxlcy91cHBlci1jYXNlL3VwcGVyLWNhc2UuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7OztBQ0FBLElBQUksR0FBRyxHQUFHLE9BQU8sQ0FBQyxXQUFXLENBQUMsQ0FBQztBQUMvQixJQUFJLFFBQVEsR0FBRyxPQUFPLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztBQUN6QyxJQUFJLFNBQVMsR0FBRyxPQUFPLENBQUMsWUFBWSxDQUFDLENBQUM7O0FBRXRDLENBQUM7U0FBTSxHQUFHLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQztFQUFBLENBQUU7Ozs7O0FDSmpCLE1BQU0sQ0FBQyxPQUFPLEdBQUcsVUFBVSxDQUFDLEVBQUUsQ0FBQyxFQUFFO0FBQy9CLFNBQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQztDQUNkLENBQUM7Ozs7O0FDRkYsTUFBTSxDQUFDLE9BQU8sR0FBRyxVQUFVLENBQUMsRUFBRSxDQUFDLEVBQUU7QUFDL0IsU0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDO0NBQ2QsQ0FBQzs7O0FDRkY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBIiwiZmlsZSI6ImdlbmVyYXRlZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzQ29udGVudCI6WyIoZnVuY3Rpb24gZSh0LG4scil7ZnVuY3Rpb24gcyhvLHUpe2lmKCFuW29dKXtpZighdFtvXSl7dmFyIGE9dHlwZW9mIHJlcXVpcmU9PVwiZnVuY3Rpb25cIiYmcmVxdWlyZTtpZighdSYmYSlyZXR1cm4gYShvLCEwKTtpZihpKXJldHVybiBpKG8sITApO3ZhciBmPW5ldyBFcnJvcihcIkNhbm5vdCBmaW5kIG1vZHVsZSAnXCIrbytcIidcIik7dGhyb3cgZi5jb2RlPVwiTU9EVUxFX05PVF9GT1VORFwiLGZ9dmFyIGw9bltvXT17ZXhwb3J0czp7fX07dFtvXVswXS5jYWxsKGwuZXhwb3J0cyxmdW5jdGlvbihlKXt2YXIgbj10W29dWzFdW2VdO3JldHVybiBzKG4/bjplKX0sbCxsLmV4cG9ydHMsZSx0LG4scil9cmV0dXJuIG5bb10uZXhwb3J0c312YXIgaT10eXBlb2YgcmVxdWlyZT09XCJmdW5jdGlvblwiJiZyZXF1aXJlO2Zvcih2YXIgbz0wO288ci5sZW5ndGg7bysrKXMocltvXSk7cmV0dXJuIHN9KSIsInZhciBhZGQgPSByZXF1aXJlKFwiLi9saWIvYWRkXCIpO1xudmFyIHN1YnRyYWN0ID0gcmVxdWlyZShcIi4vbGliL3N1YnRyYWN0XCIpO1xudmFyIHVwcGVyQ2FzZSA9IHJlcXVpcmUoXCJ1cHBlci1jYXNlXCIpO1xuXG4oKCkgPT4gYWRkKDEsMikpO1xuIiwibW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoYSwgYikge1xuICByZXR1cm4gYSArIGI7XG59O1xuIiwibW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoYSwgYikge1xuICByZXR1cm4gYSAtIGI7XG59O1xuIiwiLyoqXG4gKiBTcGVjaWFsIGxhbmd1YWdlLXNwZWNpZmljIG92ZXJyaWRlcy5cbiAqXG4gKiBTb3VyY2U6IGZ0cDovL2Z0cC51bmljb2RlLm9yZy9QdWJsaWMvVUNEL2xhdGVzdC91Y2QvU3BlY2lhbENhc2luZy50eHRcbiAqXG4gKiBAdHlwZSB7T2JqZWN0fVxuICovXG52YXIgTEFOR1VBR0VTID0ge1xuICB0cjoge1xuICAgIHJlZ2V4cDogL1tcXHUwMDY5XS9nLFxuICAgIG1hcDoge1xuICAgICAgJ1xcdTAwNjknOiAnXFx1MDEzMCdcbiAgICB9XG4gIH0sXG4gIGF6OiB7XG4gICAgcmVnZXhwOiAvW1xcdTAwNjldL2csXG4gICAgbWFwOiB7XG4gICAgICAnXFx1MDA2OSc6ICdcXHUwMTMwJ1xuICAgIH1cbiAgfSxcbiAgbHQ6IHtcbiAgICByZWdleHA6IC9bXFx1MDA2OVxcdTAwNkFcXHUwMTJGXVxcdTAzMDd8XFx1MDA2OVxcdTAzMDdbXFx1MDMwMFxcdTAzMDFcXHUwMzAzXS9nLFxuICAgIG1hcDoge1xuICAgICAgJ1xcdTAwNjlcXHUwMzA3JzogJ1xcdTAwNDknLFxuICAgICAgJ1xcdTAwNkFcXHUwMzA3JzogJ1xcdTAwNEEnLFxuICAgICAgJ1xcdTAxMkZcXHUwMzA3JzogJ1xcdTAxMkUnLFxuICAgICAgJ1xcdTAwNjlcXHUwMzA3XFx1MDMwMCc6ICdcXHUwMENDJyxcbiAgICAgICdcXHUwMDY5XFx1MDMwN1xcdTAzMDEnOiAnXFx1MDBDRCcsXG4gICAgICAnXFx1MDA2OVxcdTAzMDdcXHUwMzAzJzogJ1xcdTAxMjgnXG4gICAgfVxuICB9XG59XG5cbi8qKlxuICogVXBwZXIgY2FzZSBhIHN0cmluZy5cbiAqXG4gKiBAcGFyYW0gIHtTdHJpbmd9IHN0clxuICogQHJldHVybiB7U3RyaW5nfVxuICovXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChzdHIsIGxvY2FsZSkge1xuICB2YXIgbGFuZyA9IExBTkdVQUdFU1tsb2NhbGVdXG5cbiAgc3RyID0gc3RyID09IG51bGwgPyAnJyA6IFN0cmluZyhzdHIpXG5cbiAgaWYgKGxhbmcpIHtcbiAgICBzdHIgPSBzdHIucmVwbGFjZShsYW5nLnJlZ2V4cCwgZnVuY3Rpb24gKG0pIHsgcmV0dXJuIGxhbmcubWFwW21dIH0pXG4gIH1cblxuICByZXR1cm4gc3RyLnRvVXBwZXJDYXNlKClcbn1cbiJdfQ==

View File

@ -706,6 +706,18 @@ function unBlackBox(sourceClient) {
return rdpRequest(sourceClient, sourceClient.unblackBox);
}
/**
* Perform a "source" RDP request with the given SourceClient to get the source
* content and content type.
*
* @param SourceClient sourceClient
* @returns Promise
*/
function getSourceContent(sourceClient) {
dumpn("Getting source content for " + sourceClient.actor);
return rdpRequest(sourceClient, sourceClient.source);
}
/**
* Get a source at the specified url.
*

View File

@ -52,9 +52,9 @@ function test_source_content()
new SourceNode(1, 0, "c.js", "function c() { return 'c'; }\n"),
]);
node.setSourceContent("a.js", "content for http://example.com/www/js/a.js");
node.setSourceContent("b.js", "content for http://example.com/www/js/b.js");
node.setSourceContent("c.js", "content for http://example.com/www/js/c.js");
node.setSourceContent("a.js", "content for a.js");
node.setSourceContent("b.js", "content for b.js");
node.setSourceContent("c.js", "content for c.js");
let { code, map } = node.toStringWithSourceMap({
file: "abc.js"

Some files were not shown because too many files have changed in this diff Show More