Merge m-c to inbound. a=merge

This commit is contained in:
Ryan VanderMeulen 2016-01-06 09:50:26 -05:00
commit d051a1eb3c
343 changed files with 2916 additions and 1031 deletions

View File

@ -21,7 +21,7 @@
<!--
B2G repositories for all targets
-->
<project name="gaia" path="gaia" remote="mozillaorg" revision="16ebbfb6ce62c14573982b0aa87537ef8f857047"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="81c021654c657f6995e5e70ef02ee067d4bfedbd"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="4a962bdab532e18f53e9d2d114c349983262c6b7"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>

View File

@ -21,7 +21,7 @@
<!--
B2G repositories for all targets
-->
<project name="gaia" path="gaia" remote="mozillaorg" revision="16ebbfb6ce62c14573982b0aa87537ef8f857047"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="81c021654c657f6995e5e70ef02ee067d4bfedbd"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="4a962bdab532e18f53e9d2d114c349983262c6b7"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>

View File

@ -21,7 +21,7 @@
<!--
B2G repositories for all targets
-->
<project name="gaia" path="gaia" remote="mozillaorg" revision="16ebbfb6ce62c14573982b0aa87537ef8f857047"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="81c021654c657f6995e5e70ef02ee067d4bfedbd"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="4a962bdab532e18f53e9d2d114c349983262c6b7"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>

View File

@ -21,7 +21,7 @@
<!--
B2G repositories for all targets
-->
<project name="gaia" path="gaia" remote="mozillaorg" revision="16ebbfb6ce62c14573982b0aa87537ef8f857047"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="81c021654c657f6995e5e70ef02ee067d4bfedbd"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="4a962bdab532e18f53e9d2d114c349983262c6b7"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>

View File

@ -21,7 +21,7 @@
<!--
B2G repositories for all targets
-->
<project name="gaia" path="gaia" remote="mozillaorg" revision="16ebbfb6ce62c14573982b0aa87537ef8f857047"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="81c021654c657f6995e5e70ef02ee067d4bfedbd"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="4a962bdab532e18f53e9d2d114c349983262c6b7"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>

View File

@ -21,7 +21,7 @@
<!--
B2G repositories for all targets
-->
<project name="gaia" path="gaia" remote="mozillaorg" revision="16ebbfb6ce62c14573982b0aa87537ef8f857047"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="81c021654c657f6995e5e70ef02ee067d4bfedbd"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="4a962bdab532e18f53e9d2d114c349983262c6b7"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>

View File

@ -21,7 +21,7 @@
<!--
B2G repositories for all targets
-->
<project name="gaia" path="gaia" remote="mozillaorg" revision="16ebbfb6ce62c14573982b0aa87537ef8f857047"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="81c021654c657f6995e5e70ef02ee067d4bfedbd"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="4a962bdab532e18f53e9d2d114c349983262c6b7"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>

View File

@ -21,7 +21,7 @@
<!--
B2G repositories for all targets
-->
<project name="gaia" path="gaia" remote="mozillaorg" revision="16ebbfb6ce62c14573982b0aa87537ef8f857047"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="81c021654c657f6995e5e70ef02ee067d4bfedbd"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="4a962bdab532e18f53e9d2d114c349983262c6b7"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>

View File

@ -1,9 +1,9 @@
{
"git": {
"git_revision": "16ebbfb6ce62c14573982b0aa87537ef8f857047",
"git_revision": "81c021654c657f6995e5e70ef02ee067d4bfedbd",
"remote": "https://git.mozilla.org/releases/gaia.git",
"branch": ""
},
"revision": "8668ab0c480334a48e1935cce440e33dff23b33a",
"revision": "e651f5b571034436b7bc8eb8099033dff5623a20",
"repo_path": "integration/gaia-central"
}

View File

@ -21,7 +21,7 @@
<!--
B2G repositories for all targets
-->
<project name="gaia" path="gaia" remote="mozillaorg" revision="16ebbfb6ce62c14573982b0aa87537ef8f857047"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="81c021654c657f6995e5e70ef02ee067d4bfedbd"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="4a962bdab532e18f53e9d2d114c349983262c6b7"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>

View File

@ -21,7 +21,7 @@
<!--
B2G repositories for all targets
-->
<project name="gaia" path="gaia" remote="mozillaorg" revision="16ebbfb6ce62c14573982b0aa87537ef8f857047"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="81c021654c657f6995e5e70ef02ee067d4bfedbd"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="4a962bdab532e18f53e9d2d114c349983262c6b7"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>

View File

@ -21,7 +21,7 @@
<!--
B2G repositories for all targets
-->
<project name="gaia" path="gaia" remote="mozillaorg" revision="16ebbfb6ce62c14573982b0aa87537ef8f857047"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="81c021654c657f6995e5e70ef02ee067d4bfedbd"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="4a962bdab532e18f53e9d2d114c349983262c6b7"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>

View File

@ -37,7 +37,7 @@ var menuBuilder = {
let xulMenu = contextData.menu;
xulMenu.addEventListener("popuphidden", this);
this.xulMenu = xulMenu;
for (let [extension, root] of rootItems) {
for (let [, root] of rootItems) {
let rootElement = this.buildElementWithChildren(root, contextData);
if (!rootElement.childNodes.length) {
// If the root has no visible children, there is no reason to show
@ -52,7 +52,6 @@ var menuBuilder = {
},
buildElementWithChildren(item, contextData) {
let doc = contextData.menu.ownerDocument;
let element = this.buildSingleElement(item, contextData);
for (let child of item.children) {
if (child.enabledForContext(contextData)) {
@ -106,7 +105,7 @@ var menuBuilder = {
customizeElement(element, item, contextData) {
let label = item.title;
if (label) {
if (contextData.isTextSelected && label.indexOf('%s') > -1) {
if (contextData.isTextSelected && label.indexOf("%s") > -1) {
let selection = contextData.selectionText;
// The rendering engine will truncate the title if it's longer than 64 characters.
// But if it makes sense let's try truncate selection text only, to handle cases like
@ -125,12 +124,12 @@ var menuBuilder = {
element.setAttribute("disabled", true);
}
element.addEventListener("command", event => {
element.addEventListener("command", event => { // eslint-disable-line mozilla/balanced-listeners
item.tabManager.addActiveTabPermission();
if (item.onclick) {
let clickData = item.getClickData(contextData, event);
runSafe(item.extContext, item.onclick, clickData);
}
}
});
return element;
@ -237,7 +236,7 @@ MenuItem.prototype = {
type: "normal",
checked: "false",
contexts: ["all"],
enabled: "true"
enabled: "true",
});
},
@ -392,7 +391,7 @@ MenuItem.prototype = {
}
return true;
}
},
};
var extCount = 0;

View File

@ -546,11 +546,11 @@ extensions.registerSchemaAPI("tabs", null, (extension, context) => {
let destinationWindow = null;
if (moveProperties.windowId !== null) {
destinationWindow = WindowManager.getWindow(moveProperties.windowId);
// Ignore invalid window.
if (!destinationWindow) {
return;
}
destinationWindow = WindowManager.getWindow(moveProperties.windowId);
// Ignore invalid window.
if (!destinationWindow) {
return;
}
}
/*
@ -587,11 +587,12 @@ extensions.registerSchemaAPI("tabs", null, (extension, context) => {
if (WindowManager.getId(tab.ownerDocument.defaultView) !== windowId) {
// If the window we are moving the tab in is different, then move the tab
// to the new window.
let newTab = gBrowser.addTab('about:blank');
let newTab = gBrowser.addTab("about:blank");
let newBrowser = gBrowser.getBrowserForTab(newTab);
gBrowser.updateBrowserRemotenessByURL(newBrowser, tab.linkedBrowser.currentURI.spec);
newBrowser.stop();
newBrowser.docShell;
// This is necessary for getter side-effects.
void newBrowser.docShell;
if (tab.pinned) {
gBrowser.pinTab(newTab);

View File

@ -1,39 +1,17 @@
{
"extends": "../../.eslintrc",
"extends": "../../../../../testing/mochitest/browser.eslintrc",
"env": {
"webextensions": true,
},
"globals": {
// DOM window globals
"CustomEvent": false,
"document": false,
"ImageData": false,
"MouseEvent": false,
"setTimeout": false,
"window": false,
"XMLHttpRequest": false,
"gBrowser": false,
"sendAsyncMessage": false,
"NetUtil": true,
"XPCOMUtils": true,
"Task": true,
"browser": false,
// Test harness globals
"add_task": false,
"BrowserTestUtils": false,
"ContentTask": false,
"EventUtils": false,
"ExtensionTestUtils": false,
"info": false,
"is": false,
"ok": false,
"registerCleanupFunction": false,
"SimpleTest": false,
"SpecialPowers": false,
"waitForFocus": false,
"clickBrowserAction": true,
"clickPageAction": true,

View File

@ -28,26 +28,26 @@ add_task(function* () {
for (let i = 0; i < contexts.length; i++) {
let context = contexts[i];
let title = context;
var id = browser.contextMenus.create({ title: title, contexts: [context], id: "ext-" + context,
onclick: genericOnClick });
browser.contextMenus.create({ title: title, contexts: [context], id: "ext-" + context,
onclick: genericOnClick });
if (context == "selection") {
browser.contextMenus.update("ext-selection", {
title: "selection is: '%s'",
onclick: (info) => {
browser.contextMenus.removeAll();
genericOnClick(info);
}
},
});
}
}
var parent = browser.contextMenus.create({ title: "parent" });
let parent = browser.contextMenus.create({ title: "parent" });
browser.contextMenus.create(
{ title: "child1", parentId: parent, onclick: genericOnClick });
browser.contextMenus.create(
let child2 = browser.contextMenus.create(
{ title: "child2", parentId: parent, onclick: genericOnClick });
var parentToDel = browser.contextMenus.create({ title: "parentToDel" });
let parentToDel = browser.contextMenus.create({ title: "parentToDel" });
browser.contextMenus.create(
{ title: "child1", parentId: parentToDel, onclick: genericOnClick });
browser.contextMenus.create(
@ -57,7 +57,7 @@ add_task(function* () {
try {
browser.contextMenus.update(parent, { parentId: child2 });
browser.test.notifyFail();
} catch(e) {
} catch (e) {
browser.test.notifyPass();
}
},

View File

@ -6,26 +6,25 @@ add_task(function* () {
let tab1 = yield BrowserTestUtils.openNewForegroundTab(gBrowser, "about:robots");
let tab2 = yield BrowserTestUtils.openNewForegroundTab(gBrowser, "about:config");
gBrowser.selectedTab = tab1
gBrowser.selectedTab = tab1;
let extension = ExtensionTestUtils.loadExtension({
manifest: {
"permissions": ["tabs"]
"permissions": ["tabs"],
},
background: function() {
browser.tabs.query({
lastFocusedWindow: true,
}, function(tabs) {
var tab = tabs[0];
chrome.tabs.move(tab.id, {index: 0});
browser.tabs.query({
lastFocusedWindow: true,
}, function(tabs) {
let tab = tabs[0];
browser.tabs.move(tab.id, {index: 0});
browser.tabs.query(
{ lastFocusedWindow: true },
tabs => {
browser.test.assertEq(tabs[0].url, tab.url, "should be first tab");
browser.test.notifyPass("tabs.move.single");
});
});
});
},
});
@ -36,24 +35,24 @@ add_task(function* () {
extension = ExtensionTestUtils.loadExtension({
manifest: {
"permissions": ["tabs"]
"permissions": ["tabs"],
},
background: function() {
browser.tabs.query({
lastFocusedWindow: true,
}, function(tabs) {
browser.tabs.query(
{ lastFocusedWindow: true },
tabs => {
tabs.sort(function(a, b) { return a.url > b.url; });
chrome.tabs.move(tabs.map(tab => tab.id), {index: 0});
chrome.tabs.query({
lastFocusedWindow: true,
}, function(tabs) {
browser.tabs.move(tabs.map(tab => tab.id), {index: 0});
browser.tabs.query(
{ lastFocusedWindow: true },
tabs => {
browser.test.assertEq(tabs[0].url, "about:blank", "should be first tab");
browser.test.assertEq(tabs[1].url, "about:config", "should be second tab");
browser.test.assertEq(tabs[2].url, "about:robots", "should be third tab");
browser.test.notifyPass("tabs.move.multiple");
});
});
});
},
});
@ -63,23 +62,23 @@ add_task(function* () {
extension = ExtensionTestUtils.loadExtension({
manifest: {
"permissions": ["tabs"]
"permissions": ["tabs"],
},
background: function() {
browser.tabs.query({
lastFocusedWindow: true,
}, function(tabs) {
var tab = tabs[0];
browser.tabs.query(
{ lastFocusedWindow: true },
tabs => {
let tab = tabs[0];
// Assuming that tab.id of 12345 does not exist.
chrome.tabs.move([12345, tab.id], {index: 0});
chrome.tabs.query({
lastFocusedWindow: true,
}, function(tabs) {
browser.tabs.move([12345, tab.id], {index: 0});
browser.tabs.query(
{ lastFocusedWindow: true },
tabs => {
browser.test.assertEq(tabs[0].url, tab.url, "should be first tab");
browser.test.notifyPass("tabs.move.invalid");
});
});
});
},
});
@ -89,22 +88,22 @@ add_task(function* () {
extension = ExtensionTestUtils.loadExtension({
manifest: {
"permissions": ["tabs"]
"permissions": ["tabs"],
},
background: function() {
browser.tabs.query({
lastFocusedWindow: true,
}, function(tabs) {
var tab = tabs[0];
chrome.tabs.move(tab.id, {index: -1});
chrome.tabs.query({
lastFocusedWindow: true,
}, function(tabs) {
browser.tabs.query(
{ lastFocusedWindow: true },
tabs => {
let tab = tabs[0];
browser.tabs.move(tab.id, {index: -1});
browser.tabs.query(
{ lastFocusedWindow: true },
tabs => {
browser.test.assertEq(tabs[2].url, tab.url, "should be last tab");
browser.test.notifyPass("tabs.move.last");
});
});
});
},
});

View File

@ -3,31 +3,30 @@
"use strict";
add_task(function* () {
let tab0 = yield BrowserTestUtils.openNewForegroundTab(gBrowser, "http://example.net/");
yield BrowserTestUtils.openNewForegroundTab(gBrowser, "http://example.net/");
let window1 = yield BrowserTestUtils.openNewBrowserWindow();
let tab1 = yield BrowserTestUtils.openNewForegroundTab(window1.gBrowser, "http://example.com/");
yield BrowserTestUtils.openNewForegroundTab(window1.gBrowser, "http://example.com/");
let extension = ExtensionTestUtils.loadExtension({
manifest: {
"permissions": ["tabs"]
"permissions": ["tabs"],
},
background: function() {
chrome.tabs.query({
url: '<all_urls>',
browser.tabs.query({
url: "<all_urls>",
}, function(tabs) {
let destination = tabs[0];
let source = tabs[1]; // skip over about:blank in window1
chrome.tabs.move(source.id, {windowId: destination.windowId, index: 0});
chrome.tabs.query({
url: '<all_urls>',
}, function(tabs) {
browser.test.assertEq(tabs[0].url, "http://example.com/");
browser.test.assertEq(tabs[0].windowId, destination.windowId);
browser.test.notifyPass("tabs.move.window");
});
browser.tabs.move(source.id, {windowId: destination.windowId, index: 0});
browser.tabs.query(
{ url: "<all_urls>" },
tabs => {
browser.test.assertEq(tabs[0].url, "http://example.com/");
browser.test.assertEq(tabs[0].windowId, destination.windowId);
browser.test.notifyPass("tabs.move.window");
});
});
},
});
@ -43,31 +42,31 @@ add_task(function* () {
});
add_task(function* () {
let tab0 = yield BrowserTestUtils.openNewForegroundTab(gBrowser, "http://example.net/");
yield BrowserTestUtils.openNewForegroundTab(gBrowser, "http://example.net/");
let window1 = yield BrowserTestUtils.openNewBrowserWindow();
let tab1 = yield BrowserTestUtils.openNewForegroundTab(window1.gBrowser, "http://example.com/");
window1.gBrowser.pinTab(tab1);
let extension = ExtensionTestUtils.loadExtension({
manifest: {
"permissions": ["tabs"]
"permissions": ["tabs"],
},
background: function() {
chrome.tabs.query({
url: '<all_urls>',
}, function(tabs) {
let destination = tabs[0];
let source = tabs[1]; // remember, pinning moves it to the left.
chrome.tabs.move(source.id, {windowId: destination.windowId, index: 0});
browser.tabs.query(
{ url: "<all_urls>" },
tabs => {
let destination = tabs[0];
let source = tabs[1]; // remember, pinning moves it to the left.
browser.tabs.move(source.id, {windowId: destination.windowId, index: 0});
chrome.tabs.query({
url: '<all_urls>',
}, function(tabs) {
browser.test.assertEq(true, tabs[0].pinned);
browser.test.notifyPass("tabs.move.pin");
browser.tabs.query(
{ url: "<all_urls>" },
tabs => {
browser.test.assertEq(true, tabs[0].pinned);
browser.test.notifyPass("tabs.move.pin");
});
});
});
},
});
@ -83,32 +82,31 @@ add_task(function* () {
add_task(function* () {
let window1 = yield BrowserTestUtils.openNewBrowserWindow();
let tab0 = yield BrowserTestUtils.openNewForegroundTab(window.gBrowser, "http://example.net/");
let tab1 = yield BrowserTestUtils.openNewForegroundTab(window.gBrowser, "http://example.com/");
let tab2 = yield BrowserTestUtils.openNewForegroundTab(window1.gBrowser, "http://example.net/");
let tab3 = yield BrowserTestUtils.openNewForegroundTab(window1.gBrowser, "http://example.com/");
yield BrowserTestUtils.openNewForegroundTab(window.gBrowser, "http://example.net/");
yield BrowserTestUtils.openNewForegroundTab(window.gBrowser, "http://example.com/");
yield BrowserTestUtils.openNewForegroundTab(window1.gBrowser, "http://example.net/");
yield BrowserTestUtils.openNewForegroundTab(window1.gBrowser, "http://example.com/");
let extension = ExtensionTestUtils.loadExtension({
manifest: {
"permissions": ["tabs"]
"permissions": ["tabs"],
},
background: function() {
chrome.tabs.query({
url: '<all_urls>',
}, function(tabs) {
let move1 = tabs[1];
let move3 = tabs[3];
chrome.tabs.move([move1.id, move3.id], {index: 0});
chrome.tabs.query({
url: '<all_urls>',
}, function(tabs) {
browser.test.assertEq(tabs[0].url, move1.url);
browser.test.assertEq(tabs[2].url, move3.url);
browser.test.notifyPass("tabs.move.multiple");
browser.tabs.query(
{ url: "<all_urls>" },
tabs => {
let move1 = tabs[1];
let move3 = tabs[3];
browser.tabs.move([move1.id, move3.id], {index: 0});
browser.tabs.query(
{ url: "<all_urls>" },
tabs => {
browser.test.assertEq(tabs[0].url, move1.url);
browser.test.assertEq(tabs[2].url, move3.url);
browser.test.notifyPass("tabs.move.multiple");
});
});
});
},
});

View File

@ -52,7 +52,8 @@ const SHARING_ROOM_URL = {
COPY_FROM_PANEL: 0,
COPY_FROM_CONVERSATION: 1,
EMAIL_FROM_CALLFAILED: 2,
EMAIL_FROM_CONVERSATION: 3
EMAIL_FROM_CONVERSATION: 3,
FACEBOOK_FROM_CONVERSATION: 4
};
/**

View File

@ -85,6 +85,7 @@ loop.store = loop.store || {};
"deleteRoom",
"deleteRoomError",
"emailRoomUrl",
"facebookShareRoomUrl",
"getAllRooms",
"getAllRoomsError",
"openRoom",
@ -351,6 +352,29 @@ loop.store = loop.store || {};
["TelemetryAddValue", "LOOP_SHARING_ROOM_URL", bucket]);
},
/**
* Share a room url with Facebook
*
* @param {sharedActions.FacebookShareRoomUrl} actionData The action data.
*/
facebookShareRoomUrl: function(actionData) {
var encodedRoom = encodeURIComponent(actionData.roomUrl);
loop.request("GetLoopPref", "facebook.shareUrl")
.then(shareUrl => {
loop.request("OpenURL", shareUrl.replace("%ROOM_URL%", encodedRoom));
}).then(() => {
loop.request("NotifyUITour", "Loop:RoomURLShared");
});
var from = actionData.from;
var bucket = this._constants.SHARING_ROOM_URL["FACEBOOK_FROM_" + from.toUpperCase()];
if (typeof bucket === "undefined") {
console.error("No URL sharing type bucket found for '" + from + "'");
return;
}
loop.request("TelemetryAddValue", "LOOP_SHARING_ROOM_URL", bucket);
},
/**
* Share a room url.
*

View File

@ -280,6 +280,15 @@ loop.roomViews = (function(mozL10n) {
}));
},
handleFacebookButtonClick: function(event) {
event.preventDefault();
this.props.dispatcher.dispatch(new sharedActions.FacebookShareRoomUrl({
from: "conversation",
roomUrl: this.props.roomData.roomUrl
}));
},
handleCopyButtonClick: function(event) {
event.preventDefault();
@ -301,20 +310,6 @@ loop.roomViews = (function(mozL10n) {
}
},
handleShareButtonClick: function(event) {
event.preventDefault();
var providers = this.props.socialShareProviders;
// If there are no providers available currently, save a click by dispatching
// the 'AddSocialShareProvider' right away.
if (!providers || !providers.length) {
this.props.dispatcher.dispatch(new sharedActions.AddSocialShareProvider());
return;
}
this.toggleDropdownMenu();
},
handleEditContextClose: function() {
if (this.props.onEditContextClose) {
this.props.onEditContextClose();
@ -354,6 +349,12 @@ loop.roomViews = (function(mozL10n) {
onMouseOver: this.resetTriggeredButtons},
React.createElement("img", {src: "shared/img/glyph-email-16x16.svg"}),
React.createElement("p", null, mozL10n.get("invite_email_link_button"))
),
React.createElement("div", {className: "btn-facebook invite-button",
onClick: this.handleFacebookButtonClick,
onMouseOver: this.resetTriggeredButtons},
React.createElement("img", {src: "shared/img/glyph-facebook-16x16.svg"}),
React.createElement("p", null, mozL10n.get("invite_facebook_button3"))
)
),
React.createElement(SocialShareDropdown, {

View File

@ -280,6 +280,15 @@ loop.roomViews = (function(mozL10n) {
}));
},
handleFacebookButtonClick: function(event) {
event.preventDefault();
this.props.dispatcher.dispatch(new sharedActions.FacebookShareRoomUrl({
from: "conversation",
roomUrl: this.props.roomData.roomUrl
}));
},
handleCopyButtonClick: function(event) {
event.preventDefault();
@ -301,20 +310,6 @@ loop.roomViews = (function(mozL10n) {
}
},
handleShareButtonClick: function(event) {
event.preventDefault();
var providers = this.props.socialShareProviders;
// If there are no providers available currently, save a click by dispatching
// the 'AddSocialShareProvider' right away.
if (!providers || !providers.length) {
this.props.dispatcher.dispatch(new sharedActions.AddSocialShareProvider());
return;
}
this.toggleDropdownMenu();
},
handleEditContextClose: function() {
if (this.props.onEditContextClose) {
this.props.onEditContextClose();
@ -355,6 +350,12 @@ loop.roomViews = (function(mozL10n) {
<img src="shared/img/glyph-email-16x16.svg" />
<p>{mozL10n.get("invite_email_link_button")}</p>
</div>
<div className="btn-facebook invite-button"
onClick={this.handleFacebookButtonClick}
onMouseOver={this.resetTriggeredButtons}>
<img src="shared/img/glyph-facebook-16x16.svg" />
<p>{mozL10n.get("invite_facebook_button3")}</p>
</div>
</div>
<SocialShareDropdown
dispatcher={this.props.dispatcher}

View File

@ -3,6 +3,7 @@ pref("loop.textChat.enabled", true);
pref("loop.server", "https://loop.services.mozilla.com/v0");
pref("loop.linkClicker.url", "https://hello.firefox.com/");
pref("loop.gettingStarted.latestFTUVersion", 0);
pref("loop.facebook.shareUrl", "https://www.facebook.com/sharer/sharer.php?u=%ROOM_URL%");
pref("loop.gettingStarted.url", "https://www.mozilla.org/%LOCALE%/firefox/%VERSION%/hello/start/");
pref("loop.gettingStarted.resumeOnFirstJoin", false);
pref("loop.learnMoreUrl", "https://www.firefox.com/hello/");

View File

@ -219,6 +219,7 @@ html[dir="rtl"] .conversation-toolbar-btn-box.btn-edit-entry {
margin: .5rem 0 0;
position: absolute;
right: -10rem;
font-size: 0.8rem;
}
.call-action-group > .invite-button.triggered > p,
@ -554,7 +555,7 @@ body[platform="win"] .share-service-dropdown.overflow > .dropdown-menu-item {
.room-invitation-content,
.room-context-header {
color: #333;
font-size: 1.2rem;
font-size: 1rem;
font-weight: bold;
margin: 1rem auto;
}

View File

@ -344,6 +344,9 @@ loop.shared.actions = (function() {
/**
* Copy a room url into the user's clipboard.
* XXX: should move to some roomActions module - refs bug 1079284
* @from: where the invitation is shared from.
* Possible values ['panel', 'conversation']
* @roomUrl: the URL that is shared
*/
CopyRoomUrl: Action.define("copyRoomUrl", {
from: String,
@ -353,6 +356,9 @@ loop.shared.actions = (function() {
/**
* Email a room url.
* XXX: should move to some roomActions module - refs bug 1079284
* @from: where the invitation is shared from.
* Possible values ['panel', 'conversation']
* @roomUrl: the URL that is shared
*/
EmailRoomUrl: Action.define("emailRoomUrl", {
from: String,
@ -360,9 +366,23 @@ loop.shared.actions = (function() {
// roomDescription: String, Optional.
}),
/**
* Share a room url with Facebook.
* XXX: should move to some roomActions module - refs bug 1079284
* @from: where the invitation is shared from.
* Possible values ['panel', 'conversation']
* @roomUrl: the URL that is shared
*/
FacebookShareRoomUrl: Action.define("facebookShareRoomUrl", {
from: String,
roomUrl: String
}),
/**
* Share a room url via the Social API.
* XXX: should move to some roomActions module - refs bug 1079284
* @provider: one of the share-capable Social Providers included
* @roomUrl: the URL that is shared
*/
ShareRoomUrl: Action.define("shareRoomUrl", {
provider: Object,

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

View File

@ -9,6 +9,14 @@
<meta name="default_locale" content="en-US" />
<meta name="referrer" content="origin" />
<meta property="og:image" content="https://hello.firefox.com/img/invitation.png" />
<meta property="og:image:height" content="630" />
<meta property="og:image:width" content="1200" />
<meta property="og:site_name" content="Firefox Hello" />
<meta property="og:title" content="A friend has invited you to browse the Web together on Firefox Hello" />
<meta property="og:description" content="Click to connect" />
<link rel="shortcut icon" href="favicon.ico">
<link rel="stylesheet" type="text/css" href="shared/css/reset.css">

View File

@ -33,7 +33,8 @@ describe("loop.store.RoomStore", function() {
COPY_FROM_PANEL: 0,
COPY_FROM_CONVERSATION: 1,
EMAIL_FROM_PANEL: 2,
EMAIL_FROM_CONVERSATION: 3
EMAIL_FROM_CONVERSATION: 3,
FACEBOOK_FROM_CONVERSATION: 4
},
ROOM_CREATE: {
CREATE_SUCCESS: 0,
@ -56,6 +57,7 @@ describe("loop.store.RoomStore", function() {
}
},
NotifyUITour: function() {},
OpenURL: sinon.stub(),
"Rooms:Create": sinon.stub().returns({ roomToken: "fakeToken" }),
"Rooms:Delete": sinon.stub(),
"Rooms:GetAll": sinon.stub(),
@ -513,6 +515,43 @@ describe("loop.store.RoomStore", function() {
});
});
describe("#facebookShareRoomUrl", function() {
var getLoopPrefStub;
beforeEach(function() {
getLoopPrefStub = function() {
return "https://shared.site/?u=%ROOM_URL%";
};
LoopMochaUtils.stubLoopRequest({
GetLoopPref: getLoopPrefStub
});
});
it("should open the facebook url with room URL", function() {
store.facebookShareRoomUrl(new sharedActions.FacebookShareRoomUrl({
from: "conversation",
roomUrl: "http://invalid"
}));
sinon.assert.calledOnce(requestStubs.OpenURL);
sinon.assert.calledWithExactly(requestStubs.OpenURL, "https://shared.site/?u=http%3A%2F%2Finvalid");
});
it("should send a telemetry event for facebook share from conversation", function() {
store.facebookShareRoomUrl(new sharedActions.FacebookShareRoomUrl({
from: "conversation",
roomUrl: "http://invalid"
}));
sinon.assert.calledOnce(requestStubs.TelemetryAddValue);
sinon.assert.calledWithExactly(requestStubs.TelemetryAddValue,
"LOOP_SHARING_ROOM_URL", 4);
});
});
describe("#shareRoomUrl", function() {
var socialShareRoomStub;

View File

@ -246,6 +246,27 @@ describe("loop.roomViews", function() {
}));
});
it("should dispatch a FacebookShareRoomUrl action when the facebook button is clicked",
function() {
var url = "http://invalid";
view = mountTestComponent({
roomData: {
roomUrl: url
}
});
var facebookBtn = view.getDOMNode().querySelector(".btn-facebook");
React.addons.TestUtils.Simulate.click(facebookBtn);
sinon.assert.calledOnce(dispatcher.dispatch);
sinon.assert.calledWith(dispatcher.dispatch,
new sharedActions.FacebookShareRoomUrl({
from: "conversation",
roomUrl: url
}));
});
describe("Copy Button", function() {
beforeEach(function() {
view = mountTestComponent();

View File

@ -52,7 +52,7 @@ invite_header_text3=It takes two to use Firefox Hello, so send a friend a link t
invite_copy_link_button=Copy Link
invite_copied_link_button=Copied!
invite_email_link_button=Email Link
invite_facebook_button2=Share on Facebook
invite_facebook_button3=Facebook
invite_your_link=Your link:
# Status text

View File

@ -31,7 +31,7 @@
<link rel="stylesheet" href="chrome://global/skin/global.css" type="text/css"/>
<link rel="stylesheet" href="chrome://devtools/skin/common.css" type="text/css"/>
<link rel="stylesheet" href="chrome://devtools/skin/computedview.css" type="text/css"/>
<link rel="stylesheet" href="chrome://devtools/skin/computed.css" type="text/css"/>
<script type="application/javascript;version=1.8" src="chrome://devtools/content/shared/theme-switching.js"/>

View File

@ -0,0 +1,11 @@
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# 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/.
DevToolsModules(
'computed.js',
)
BROWSER_CHROME_MANIFESTS += ['test/browser.ini']

View File

@ -1,4 +1,4 @@
{
// Extend from the shared list of defined globals for mochitests.
"extends": "../../../.eslintrc.mochitests"
"extends": "../../../../.eslintrc.mochitests"
}

View File

@ -0,0 +1,32 @@
[DEFAULT]
tags = devtools
subsuite = devtools
support-files =
doc_matched_selectors.html
doc_media_queries.html
doc_pseudoelement.html
doc_sourcemaps.css
doc_sourcemaps.css.map
doc_sourcemaps.html
doc_sourcemaps.scss
head.js
[browser_computed_browser-styles.js]
[browser_computed_cycle_color.js]
[browser_computed_getNodeInfo.js]
[browser_computed_keybindings_01.js]
[browser_computed_keybindings_02.js]
[browser_computed_matched-selectors-toggle.js]
[browser_computed_matched-selectors_01.js]
[browser_computed_matched-selectors_02.js]
[browser_computed_media-queries.js]
[browser_computed_no-results-placeholder.js]
[browser_computed_original-source-link.js]
[browser_computed_pseudo-element_01.js]
[browser_computed_refresh-on-style-change_01.js]
[browser_computed_search-filter.js]
[browser_computed_search-filter_clear.js]
[browser_computed_search-filter_context-menu.js]
[browser_computed_search-filter_escape-keypress.js]
[browser_computed_select-and-copy-styles.js]
[browser_computed_style-editor-link.js]

View File

@ -6,7 +6,8 @@
// Checking selector counts, matched rules and titles in the computed-view.
const {PropertyView} = require("devtools/client/styleinspector/computed-view");
const {PropertyView} =
require("devtools/client/inspector/computed/computed");
const TEST_URI = TEST_URL_ROOT + "doc_matched_selectors.html";
add_task(function*() {

View File

@ -9,7 +9,7 @@
const TEST_URI = TEST_URL_ROOT + "doc_media_queries.html";
var {PropertyView} = require("devtools/client/styleinspector/computed-view");
var {PropertyView} = require("devtools/client/inspector/computed/computed");
var {CssLogic} = require("devtools/shared/styleinspector/css-logic");
add_task(function*() {

View File

@ -0,0 +1,610 @@
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
let Cu = Components.utils;
let {gDevTools} = Cu.import("resource://devtools/client/framework/gDevTools.jsm", {});
let {require} = Cu.import("resource://devtools/shared/Loader.jsm", {});
let {TargetFactory} = require("devtools/client/framework/target");
let {CssComputedView} =
require("devtools/client/inspector/computed/computed");
let DevToolsUtils = require("devtools/shared/DevToolsUtils");
let promise = require("promise");
let {console} =
Components.utils.import("resource://gre/modules/Console.jsm", {});
// All tests are asynchronous
waitForExplicitFinish();
const TEST_URL_ROOT =
"http://example.com/browser/devtools/client/inspector/computed/test/";
const TEST_URL_ROOT_SSL =
"https://example.com/browser/devtools/client/inspector/computed/test/";
const ROOT_TEST_DIR = getRootDirectory(gTestPath);
const FRAME_SCRIPT_URL = ROOT_TEST_DIR + "doc_frame_script.js";
// Auto clean-up when a test ends
registerCleanupFunction(function*() {
let target = TargetFactory.forTab(gBrowser.selectedTab);
yield gDevTools.closeToolbox(target);
while (gBrowser.tabs.length > 1) {
gBrowser.removeCurrentTab();
}
});
// Uncomment this pref to dump all devtools emitted events to the console.
// Services.prefs.setBoolPref("devtools.dump.emit", true);
// Set the testing flag on gDevTools and reset it when the test ends
DevToolsUtils.testing = true;
registerCleanupFunction(() => DevToolsUtils.testing = false);
// Clean-up all prefs that might have been changed during a test run
// (safer here because if the test fails, then the pref is never reverted)
registerCleanupFunction(() => {
Services.prefs.clearUserPref("devtools.inspector.activeSidebar");
Services.prefs.clearUserPref("devtools.dump.emit");
Services.prefs.clearUserPref("devtools.defaultColorUnit");
});
/**
* The functions found below are here to ease test development and maintenance.
* Most of these functions are stateless and will require some form of context
* (the instance of the current toolbox, or inspector panel for instance).
*
* Most of these functions are async too and return promises.
*
* All tests should follow the following pattern:
*
* add_task(function*() {
* yield addTab(TEST_URI);
* let {toolbox, inspector, view} = yield openComputedView();
*
* yield selectNode("#test", inspector);
* yield someAsyncTestFunction(view);
* });
*
* add_task is the way to define the testcase in the test file. It accepts
* a single generator-function argument.
* The generator function should yield any async call.
*
* There is no need to clean tabs up at the end of a test as this is done
* automatically.
*
* It is advised not to store any references on the global scope. There
* shouldn't be a need to anyway. Thanks to add_task, test steps, even
* though asynchronous, can be described in a nice flat way, and
* if/for/while/... control flow can be used as in sync code, making it
* possible to write the outline of the test case all in add_task, and delegate
* actual processing and assertions to other functions.
*/
/* *********************************************
* UTILS
* *********************************************
* General test utilities.
* Add new tabs, open the toolbox and switch to the various panels, select
* nodes, get node references, ...
*/
/**
* Add a new test tab in the browser and load the given url.
*
* @param {String} url
* The url to be loaded in the new tab
* @return a promise that resolves to the tab object when the url is loaded
*/
function addTab(url) {
info("Adding a new tab with URL: '" + url + "'");
let def = promise.defer();
window.focus();
let tab = window.gBrowser.selectedTab = window.gBrowser.addTab(url);
let browser = tab.linkedBrowser;
info("Loading the helper frame script " + FRAME_SCRIPT_URL);
browser.messageManager.loadFrameScript(FRAME_SCRIPT_URL, false);
browser.addEventListener("load", function onload() {
browser.removeEventListener("load", onload, true);
info("URL '" + url + "' loading complete");
def.resolve(tab);
}, true);
return def.promise;
}
/**
* Simple DOM node accesor function that takes either a node or a string css
* selector as argument and returns the corresponding node
*
* @param {String|DOMNode} nodeOrSelector
* @return {DOMNode|CPOW} Note that in e10s mode a CPOW object is returned which
* doesn't implement *all* of the DOMNode's properties
*/
function getNode(nodeOrSelector) {
info("Getting the node for '" + nodeOrSelector + "'");
return typeof nodeOrSelector === "string" ?
content.document.querySelector(nodeOrSelector) :
nodeOrSelector;
}
/**
* Get the NodeFront for a given css selector, via the protocol
*
* @param {String} selector
* @param {InspectorPanel} inspector
* The instance of InspectorPanel currently loaded in the toolbox
* @return {Promise} Resolves to the NodeFront instance
*/
function getNodeFront(selector, {walker}) {
return walker.querySelector(walker.rootNode, selector);
}
/*
* Set the inspector's current selection to a node or to the first match of the
* given css selector.
*
* @param {String|NodeFront} data
* The node to select
* @param {InspectorPanel} inspector
* The instance of InspectorPanel currently loaded in the toolbox
* @param {String} reason
* Defaults to "test" which instructs the inspector not
* to highlight the node upon selection
* @return {Promise} Resolves when the inspector is updated with the new node
*/
var selectNode = Task.async(function*(data, inspector, reason="test") {
info("Selecting the node for '" + data + "'");
let nodeFront = data;
if (!data._form) {
nodeFront = yield getNodeFront(data, inspector);
}
let updated = inspector.once("inspector-updated");
inspector.selection.setNodeFront(nodeFront, reason);
yield updated;
});
/**
* Open the toolbox, with the inspector tool visible.
*
* @return a promise that resolves when the inspector is ready
*/
var openInspector = Task.async(function*() {
info("Opening the inspector");
let target = TargetFactory.forTab(gBrowser.selectedTab);
let inspector, toolbox;
// Checking if the toolbox and the inspector are already loaded
// The inspector-updated event should only be waited for if the inspector
// isn't loaded yet
toolbox = gDevTools.getToolbox(target);
if (toolbox) {
inspector = toolbox.getPanel("inspector");
if (inspector) {
info("Toolbox and inspector already open");
return {
toolbox: toolbox,
inspector: inspector
};
}
}
info("Opening the toolbox");
toolbox = yield gDevTools.showToolbox(target, "inspector");
yield waitForToolboxFrameFocus(toolbox);
inspector = toolbox.getPanel("inspector");
info("Waiting for the inspector to update");
yield inspector.once("inspector-updated");
return {
toolbox: toolbox,
inspector: inspector
};
});
/**
* Wait for the toolbox frame to receive focus after it loads
*
* @param {Toolbox} toolbox
* @return a promise that resolves when focus has been received
*/
function waitForToolboxFrameFocus(toolbox) {
info("Making sure that the toolbox's frame is focused");
let def = promise.defer();
let win = toolbox.frame.contentWindow;
waitForFocus(def.resolve, win);
return def.promise;
}
/**
* Open the toolbox, with the inspector tool visible, and the sidebar that
* corresponds to the given id selected
*
* @return a promise that resolves when the inspector is ready and the sidebar
* view is visible and ready
*/
var openInspectorSideBar = Task.async(function*(id) {
let {toolbox, inspector} = yield openInspector();
if (!hasSideBarTab(inspector, id)) {
info("Waiting for the " + id + " sidebar to be ready");
yield inspector.sidebar.once(id + "-ready");
}
info("Selecting the " + id + " sidebar");
inspector.sidebar.select(id);
return {
toolbox: toolbox,
inspector: inspector,
view: inspector.sidebar.getWindowForTab(id)[id].view
};
});
/**
* Open the toolbox, with the inspector tool visible, and the computed-view
* sidebar tab selected.
*
* @return a promise that resolves when the inspector is ready and the computed
* view is visible and ready
*/
function openComputedView() {
return openInspectorSideBar("computedview");
}
/**
* Wait for eventName on target to be delivered a number of times.
*
* @param {Object} target
* An observable object that either supports on/off or
* addEventListener/removeEventListener
* @param {String} eventName
* @param {Number} numTimes
* Number of deliveries to wait for.
* @param {Boolean} useCapture
* Optional, for addEventListener/removeEventListener
* @return A promise that resolves when the event has been handled
*/
function waitForNEvents(target, eventName, numTimes, useCapture = false) {
info("Waiting for event: '" + eventName + "' on " + target + ".");
let deferred = promise.defer();
let count = 0;
for (let [add, remove] of [
["addEventListener", "removeEventListener"],
["addListener", "removeListener"],
["on", "off"]
]) {
if ((add in target) && (remove in target)) {
target[add](eventName, function onEvent(...aArgs) {
if (++count == numTimes) {
target[remove](eventName, onEvent, useCapture);
deferred.resolve.apply(deferred, aArgs);
}
}, useCapture);
break;
}
}
return deferred.promise;
}
/**
* Wait for eventName on target.
*
* @param {Object} target
* An observable object that either supports on/off or
* addEventListener/removeEventListener
* @param {String} eventName
* @param {Boolean} useCapture
* Optional, for addEventListener/removeEventListener
* @return A promise that resolves when the event has been handled
*/
function once(target, eventName, useCapture=false) {
return waitForNEvents(target, eventName, 1, useCapture);
}
/**
* This shouldn't be used in the tests, but is useful when writing new tests or
* debugging existing tests in order to introduce delays in the test steps
*
* @param {Number} ms
* The time to wait
* @return A promise that resolves when the time is passed
*/
function wait(ms) {
let def = promise.defer();
content.setTimeout(def.resolve, ms);
return def.promise;
}
/**
* Listen for a new tab to open and return a promise that resolves when one
* does and completes the load event.
*
* @return a promise that resolves to the tab object
*/
var waitForTab = Task.async(function*() {
info("Waiting for a tab to open");
yield once(gBrowser.tabContainer, "TabOpen");
let tab = gBrowser.selectedTab;
let browser = tab.linkedBrowser;
yield once(browser, "load", true);
info("The tab load completed");
return tab;
});
/**
* @see SimpleTest.waitForClipboard
*
* @param {Function} setup
* Function to execute before checking for the
* clipboard content
* @param {String|Boolean} expected
* An expected string or validator function
* @return a promise that resolves when the expected string has been found or
* the validator function has returned true, rejects otherwise.
*/
function waitForClipboard(setup, expected) {
let def = promise.defer();
SimpleTest.waitForClipboard(expected, setup, def.resolve, def.reject);
return def.promise;
}
/**
* Dispatch the copy event on the given element
*/
function fireCopyEvent(element) {
let evt = element.ownerDocument.createEvent("Event");
evt.initEvent("copy", true, true);
element.dispatchEvent(evt);
}
/**
* Checks whether the inspector's sidebar corresponding to the given id already
* exists
*
* @param {InspectorPanel}
* @param {String}
* @return {Boolean}
*/
function hasSideBarTab(inspector, id) {
return !!inspector.sidebar.getWindowForTab(id);
}
/**
* Simulate the key input for the given input in the window.
*
* @param {String} input
* The string value to input
* @param {Window} win
* The window containing the panel
*/
function synthesizeKeys(input, win) {
for (let key of input.split("")) {
EventUtils.synthesizeKey(key, {}, win);
}
}
/* *********************************************
* COMPUTED-VIEW
* *********************************************
* Computed-view related utility functions.
* Allows to get properties, links, expand properties, ...
*/
/**
* Get references to the name and value span nodes corresponding to a given
* property name in the computed-view
*
* @param {CssComputedView} view
* The instance of the computed view panel
* @param {String} name
* The name of the property to retrieve
* @return an object {nameSpan, valueSpan}
*/
function getComputedViewProperty(view, name) {
let prop;
for (let property of view.styleDocument.querySelectorAll(".property-view")) {
let nameSpan = property.querySelector(".property-name");
let valueSpan = property.querySelector(".property-value");
if (nameSpan.textContent === name) {
prop = {nameSpan: nameSpan, valueSpan: valueSpan};
break;
}
}
return prop;
}
/**
* Get an instance of PropertyView from the computed-view.
*
* @param {CssComputedView} view
* The instance of the computed view panel
* @param {String} name
* The name of the property to retrieve
* @return {PropertyView}
*/
function getComputedViewPropertyView(view, name) {
let propView;
for (let propertyView of view.propertyViews) {
if (propertyView._propertyInfo.name === name) {
propView = propertyView;
break;
}
}
return propView;
}
/**
* Get a reference to the property-content element for a given property name in
* the computed-view.
* A property-content element always follows (nextSibling) the property itself
* and is only shown when the twisty icon is expanded on the property.
* A property-content element contains matched rules, with selectors,
* properties, values and stylesheet links
*
* @param {CssComputedView} view
* The instance of the computed view panel
* @param {String} name
* The name of the property to retrieve
* @return {Promise} A promise that resolves to the property matched rules
* container
*/
var getComputedViewMatchedRules = Task.async(function*(view, name) {
let expander;
let propertyContent;
for (let property of view.styleDocument.querySelectorAll(".property-view")) {
let nameSpan = property.querySelector(".property-name");
if (nameSpan.textContent === name) {
expander = property.querySelector(".expandable");
propertyContent = property.nextSibling;
break;
}
}
if (!expander.hasAttribute("open")) {
// Need to expand the property
let onExpand = view.inspector.once("computed-view-property-expanded");
expander.click();
yield onExpand;
}
return propertyContent;
});
/**
* Get the text value of the property corresponding to a given name in the
* computed-view
*
* @param {CssComputedView} view
* The instance of the computed view panel
* @param {String} name
* The name of the property to retrieve
* @return {String} The property value
*/
function getComputedViewPropertyValue(view, name, propertyName) {
return getComputedViewProperty(view, name, propertyName)
.valueSpan.textContent;
}
/**
* Expand a given property, given its index in the current property list of
* the computed view
*
* @param {CssComputedView} view
* The instance of the computed view panel
* @param {Number} index
* The index of the property to be expanded
* @return a promise that resolves when the property has been expanded, or
* rejects if the property was not found
*/
function expandComputedViewPropertyByIndex(view, index) {
info("Expanding property " + index + " in the computed view");
let expandos = view.styleDocument.querySelectorAll(".expandable");
if (!expandos.length || !expandos[index]) {
return promise.reject();
}
let onExpand = view.inspector.once("computed-view-property-expanded");
expandos[index].click();
return onExpand;
}
/**
* Get a rule-link from the computed-view given its index
*
* @param {CssComputedView} view
* The instance of the computed view panel
* @param {Number} index
* The index of the link to be retrieved
* @return {DOMNode} The link at the given index, if one exists, null otherwise
*/
function getComputedViewLinkByIndex(view, index) {
let links = view.styleDocument.querySelectorAll(".rule-link .link");
return links[index];
}
/* *********************************************
* STYLE-EDITOR
* *********************************************
* Style-editor related utility functions.
*/
/**
* Wait for the toolbox to emit the styleeditor-selected event and when done
* wait for the stylesheet identified by href to be loaded in the stylesheet
* editor
*
* @param {Toolbox} toolbox
* @param {String} href
* Optional, if not provided, wait for the first editor to be ready
* @return a promise that resolves to the editor when the stylesheet editor is
* ready
*/
function waitForStyleEditor(toolbox, href) {
let def = promise.defer();
info("Waiting for the toolbox to switch to the styleeditor");
toolbox.once("styleeditor-selected").then(() => {
let panel = toolbox.getCurrentPanel();
ok(panel && panel.UI, "Styleeditor panel switched to front");
// A helper that resolves the promise once it receives an editor that
// matches the expected href. Returns false if the editor was not correct.
let gotEditor = (event, editor) => {
let currentHref = editor.styleSheet.href;
if (!href || (href && currentHref.endsWith(href))) {
info("Stylesheet editor selected");
panel.UI.off("editor-selected", gotEditor);
editor.getSourceEditor().then(sourceEditor => {
info("Stylesheet editor fully loaded");
def.resolve(sourceEditor);
});
return true;
}
info("The editor was incorrect. Waiting for editor-selected event.");
return false;
};
// The expected editor may already be selected. Check the if the currently
// selected editor is the expected one and if not wait for an
// editor-selected event.
if (!gotEditor("styleeditor-selected", panel.UI.selectedEditor)) {
// The expected editor is not selected (yet). Wait for it.
panel.UI.on("editor-selected", gotEditor);
}
});
return def.promise;
}
/**
* Reload the current page and wait for the inspector to be initialized after
* the navigation
*
* @param {InspectorPanel} inspector
* The instance of InspectorPanel currently loaded in the toolbox
* @return a promise that resolves after page reload and inspector
* initialization
*/
function reloadPage(inspector) {
let onNewRoot = inspector.once("new-root");
content.location.reload();
return onNewRoot.then(() => {
inspector.markup._waitForChildren();
});
}

View File

@ -11,13 +11,13 @@
<head>
<title>&title;</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<link rel="stylesheet" href="font-inspector.css" type="text/css"/>
<link rel="stylesheet" href="fonts.css" type="text/css"/>
<link rel="stylesheet" href="chrome://devtools/skin/common.css" type="text/css"/>
<link rel="stylesheet" href="chrome://devtools/skin/font-inspector.css" type="text/css"/>
<link rel="stylesheet" href="chrome://devtools/skin/fonts.css" type="text/css"/>
<script type="application/javascript;version=1.8" src="chrome://devtools/content/shared/theme-switching.js"/>
</head>
<body class="theme-sidebar devtools-monospace" role="application">
<script type="application/javascript;version=1.8" src="font-inspector.js"></script>
<script type="application/javascript;version=1.8" src="fonts.js"></script>
<div>
<div class="devtools-toolbar preview-input-toolbar">
<div class="devtools-searchbox">

View File

@ -4,5 +4,8 @@
# 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/.
BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
DevToolsModules(
'fonts.js',
)
BROWSER_CHROME_MANIFESTS += ['test/browser.ini']

View File

@ -1,4 +1,4 @@
{
// Extend from the shared list of defined globals for mochitests.
"extends": "../../../.eslintrc.mochitests"
"extends": "../../../../.eslintrc.mochitests"
}

View File

@ -2,12 +2,13 @@
/* 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";
// shared-head.js handles imports, constants, and utility functions
Services.scriptloader.loadSubScript("chrome://mochitests/content/browser/devtools/client/framework/test/shared-head.js", this);
const BASE_URI = "http://mochi.test:8888/browser/devtools/client/fontinspector/test/"
const BASE_URI = "http://mochi.test:8888/browser/devtools/client/inspector/fonts/test/";
/**
* Open the toolbox, with the inspector tool visible.

View File

@ -353,21 +353,21 @@ InspectorPanel.prototype = {
this.sidebar.on("select", this._setDefaultSidebar);
this.sidebar.addTab("ruleview",
"chrome://devtools/content/styleinspector/cssruleview.xhtml",
"chrome://devtools/content/inspector/rules/rules.xhtml",
"ruleview" == defaultTab);
this.sidebar.addTab("computedview",
"chrome://devtools/content/styleinspector/computedview.xhtml",
"chrome://devtools/content/inspector/computed/computed.xhtml",
"computedview" == defaultTab);
if (Services.prefs.getBoolPref("devtools.fontinspector.enabled") && this.canGetUsedFontFaces) {
this.sidebar.addTab("fontinspector",
"chrome://devtools/content/fontinspector/font-inspector.xhtml",
"chrome://devtools/content/inspector/fonts/fonts.xhtml",
"fontinspector" == defaultTab);
}
this.sidebar.addTab("layoutview",
"chrome://devtools/content/layoutview/view.xhtml",
"chrome://devtools/content/inspector/layout/layout.xhtml",
"layoutview" == defaultTab);
if (this.target.form.animationsActor) {

View File

@ -15,10 +15,10 @@
<script type="application/javascript;version=1.8"
src="chrome://devtools/content/shared/theme-switching.js"/>
<script type="application/javascript;version=1.8" src="view.js"></script>
<script type="application/javascript;version=1.8" src="layout.js"></script>
<link rel="stylesheet" href="chrome://devtools/skin/common.css" type="text/css"/>
<link rel="stylesheet" href="chrome://devtools/skin/layoutview.css" type="text/css"/>
<link rel="stylesheet" href="chrome://devtools/skin/layout.css" type="text/css"/>
</head>
<body class="theme-sidebar devtools-monospace">

View File

@ -0,0 +1,11 @@
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# 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/.
DevToolsModules(
'layout.js',
)
BROWSER_CHROME_MANIFESTS += ['test/browser.ini']

View File

@ -0,0 +1,4 @@
{
// Extend from the shared list of defined globals for mochitests.
"extends": "../../../../.eslintrc.mochitests"
}

View File

@ -0,0 +1,22 @@
[DEFAULT]
tags = devtools
skip-if = e10s # Bug ?????? - devtools tests disabled with e10s
subsuite = devtools
support-files =
doc_layout_iframe1.html
doc_layout_iframe2.html
head.js
[browser_layout.js]
[browser_layout_editablemodel.js]
# [browser_layout_editablemodel_allproperties.js]
# Disabled for too many intermittent failures (bug 1009322)
[browser_layout_editablemodel_border.js]
[browser_layout_editablemodel_stylerules.js]
[browser_layout_guides.js]
[browser_layout_rotate-labels-on-sides.js]
[browser_layout_tooltips.js]
[browser_layout_update-after-navigation.js]
[browser_layout_update-after-reload.js]
# [browser_layout_update-in-iframes.js]
# Bug 1020038 layout-view updates for iframe elements changes

View File

@ -8,7 +8,7 @@
// it also works after going back
add_task(function*() {
yield addTab(TEST_URL_ROOT + "doc_layoutview_iframe1.html");
yield addTab(TEST_URL_ROOT + "doc_layout_iframe1.html");
let {toolbox, inspector, view} = yield openLayoutView();
yield runTests(inspector, view);
});
@ -34,7 +34,7 @@ function*(inspector, view) {
addTest("Navigate to the second page",
function*(inspector, view) {
yield navigateTo(TEST_URL_ROOT + "doc_layoutview_iframe2.html");
yield navigateTo(TEST_URL_ROOT + "doc_layout_iframe2.html");
yield inspector.once("markuploaded");
});

View File

@ -7,7 +7,7 @@
// Test that the layout-view continues to work after the page is reloaded
add_task(function*() {
yield addTab(TEST_URL_ROOT + "doc_layoutview_iframe1.html");
yield addTab(TEST_URL_ROOT + "doc_layout_iframe1.html");
let {toolbox, inspector, view} = yield openLayoutView();
info("Test that the layout-view works on the first page");

View File

@ -8,7 +8,7 @@
// change
add_task(function*() {
yield addTab(TEST_URL_ROOT + "doc_layoutview_iframe1.html");
yield addTab(TEST_URL_ROOT + "doc_layout_iframe1.html");
let iframe2 = getNode("iframe").contentDocument.querySelector("iframe");
let {toolbox, inspector, view} = yield openLayoutView();

View File

@ -15,7 +15,8 @@ var DevToolsUtils = require("devtools/shared/DevToolsUtils");
// All test are asynchronous
waitForExplicitFinish();
const TEST_URL_ROOT = "http://example.com/browser/devtools/client/layoutview/test/";
const TEST_URL_ROOT =
"http://example.com/browser/devtools/client/inspector/layout/test/";
// Uncomment this pref to dump all devtools emitted events to the console.
// Services.prefs.setBoolPref("devtools.dump.emit", true);
@ -100,7 +101,6 @@ function selectAndHighlightNode(nodeOrSelector, inspector) {
let updated = inspector.toolbox.once("highlighter-ready");
inspector.selection.setNode(node, "test-highlight");
return updated;
}
/**
@ -115,7 +115,7 @@ function selectAndHighlightNode(nodeOrSelector, inspector) {
* @return a promise that resolves when the inspector is updated with the new
* node
*/
function selectNode(nodeOrSelector, inspector, reason="test") {
function selectNode(nodeOrSelector, inspector, reason = "test") {
info("Selecting the node " + nodeOrSelector);
let node = getNode(nodeOrSelector);
@ -139,10 +139,10 @@ var openInspector = Task.async(function*() {
function mockHighlighter({highlighter}) {
highlighter.showBoxModel = function(nodeFront, options) {
return promise.resolve();
}
};
highlighter.hideBoxModel = function() {
return promise.resolve();
}
};
}
// Checking if the toolbox and the inspector are already loaded
@ -247,7 +247,7 @@ function waitForUpdate(inspector) {
var TESTS = [];
function addTest(message, func) {
TESTS.push([message, Task.async(func)])
TESTS.push([message, Task.async(func)]);
}
var runTests = Task.async(function*(...args) {

View File

@ -2,6 +2,13 @@
# 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/.
DIRS += [
'computed',
'fonts',
'layout',
'rules'
]
DevToolsModules(
'breadcrumbs.js',
'inspector-commands.js',

View File

@ -4,4 +4,8 @@
# 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/.
DevToolsModules(
'rules.js',
)
BROWSER_CHROME_MANIFESTS += ['test/browser.ini']

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