mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge m-c to b-i
CLOSED TREE
This commit is contained in:
commit
c73dcc6e46
2
CLOBBER
2
CLOBBER
@ -18,4 +18,4 @@
|
||||
# Modifying this file will now automatically clobber the buildbot machines \o/
|
||||
#
|
||||
|
||||
Bug 922160 needs a clobber due to WebIDL binding dependency issues (bug 928195).
|
||||
Bug 914270 needs a clobber since moving variables to moz.build always requires a clobber (bug 852814)
|
||||
|
@ -11,7 +11,7 @@ interface nsIAccessible;
|
||||
/**
|
||||
* This interface gives access to an accessible's set of relations.
|
||||
*/
|
||||
[scriptable, uuid(9f85fc0d-2969-48e6-b822-68140f7e5770)]
|
||||
[scriptable, uuid(55b308c4-2ae4-46bc-b4cd-4d4370e0a660)]
|
||||
interface nsIAccessibleRelation : nsISupports
|
||||
{
|
||||
/**
|
||||
@ -109,6 +109,21 @@ interface nsIAccessibleRelation : nsISupports
|
||||
*/
|
||||
const unsigned long RELATION_DEFAULT_BUTTON = 0x10;
|
||||
|
||||
/**
|
||||
* The target object is the containing document object.
|
||||
*/
|
||||
const unsigned long RELATION_CONTAINING_DOCUMENT = 0x11;
|
||||
|
||||
/**
|
||||
* The target object is the topmost containing document object in the tab pane.
|
||||
*/
|
||||
const unsigned long RELATION_CONTAINING_TAB_PANE = 0x12;
|
||||
|
||||
/**
|
||||
* The target object is the containing application object.
|
||||
*/
|
||||
const unsigned long RELATION_CONTAINING_APPLICATION = 0x14;
|
||||
|
||||
/**
|
||||
* Returns the type of the relation.
|
||||
*/
|
||||
|
@ -109,7 +109,27 @@ MOZ_BEGIN_ENUM_CLASS(RelationType)
|
||||
*/
|
||||
DEFAULT_BUTTON = 0x10,
|
||||
|
||||
LAST = DEFAULT_BUTTON
|
||||
/**
|
||||
* The target object is the containing document object.
|
||||
*/
|
||||
CONTAINING_DOCUMENT = 0x11,
|
||||
|
||||
/**
|
||||
* The target object is the topmost containing document object in the tab pane.
|
||||
*/
|
||||
CONTAINING_TAB_PANE = 0x12,
|
||||
|
||||
/**
|
||||
* The target object is the containing window object.
|
||||
*/
|
||||
CONTAINING_WINDOW = 0x13,
|
||||
|
||||
/**
|
||||
* The target object is the containing application object.
|
||||
*/
|
||||
CONTAINING_APPLICATION = 0x14,
|
||||
|
||||
LAST = CONTAINING_APPLICATION
|
||||
|
||||
MOZ_END_ENUM_CLASS(RelationType)
|
||||
|
||||
|
@ -110,3 +110,21 @@ RELATIONTYPE(DEFAULT_BUTTON,
|
||||
ATK_RELATION_NULL,
|
||||
NAVRELATION_DEFAULT_BUTTON,
|
||||
IA2_RELATION_NULL)
|
||||
|
||||
RELATIONTYPE(CONTAINING_DOCUMENT,
|
||||
"containing document",
|
||||
ATK_RELATION_NULL,
|
||||
NAVRELATION_CONTAINING_DOCUMENT,
|
||||
IA2_RELATION_CONTAINING_DOCUMENT)
|
||||
|
||||
RELATIONTYPE(CONTAINING_TAB_PANE,
|
||||
"containing tab pane",
|
||||
ATK_RELATION_NULL,
|
||||
NAVRELATION_CONTAINING_TAB_PANE,
|
||||
IA2_RELATION_CONTAINING_TAB_PANE)
|
||||
|
||||
RELATIONTYPE(CONTAINING_APPLICATION,
|
||||
"containing application",
|
||||
ATK_RELATION_NULL,
|
||||
NAVRELATION_CONTAINING_APPLICATION,
|
||||
IA2_RELATION_CONTAINING_APPLICATION)
|
||||
|
@ -13,6 +13,8 @@
|
||||
#include "nsAccUtils.h"
|
||||
#include "nsAccessibleRelation.h"
|
||||
#include "nsAccessibilityService.h"
|
||||
#include "ApplicationAccessible.h"
|
||||
#include "nsCoreUtils.h"
|
||||
#include "nsIAccessibleRelation.h"
|
||||
#include "nsIAccessibleRole.h"
|
||||
#include "nsEventShell.h"
|
||||
@ -2180,6 +2182,33 @@ Accessible::RelationByType(RelationType aType)
|
||||
return Relation();
|
||||
}
|
||||
|
||||
case RelationType::CONTAINING_DOCUMENT:
|
||||
return Relation(mDoc);
|
||||
|
||||
case RelationType::CONTAINING_TAB_PANE: {
|
||||
nsCOMPtr<nsIDocShell> docShell =
|
||||
nsCoreUtils::GetDocShellFor(GetNode());
|
||||
if (docShell) {
|
||||
// Walk up the parent chain without crossing the boundary at which item
|
||||
// types change, preventing us from walking up out of tab content.
|
||||
nsCOMPtr<nsIDocShellTreeItem> root;
|
||||
docShell->GetSameTypeRootTreeItem(getter_AddRefs(root));
|
||||
if (root) {
|
||||
// If the item type is typeContent, we assume we are in browser tab
|
||||
// content. Note, this includes content such as about:addons,
|
||||
// for consistency.
|
||||
int32_t itemType = 0;
|
||||
root->GetItemType(&itemType);
|
||||
if (itemType == nsIDocShellTreeItem::typeContent)
|
||||
return Relation(nsAccUtils::GetDocAccessibleFor(root));
|
||||
}
|
||||
}
|
||||
return Relation();
|
||||
}
|
||||
|
||||
case RelationType::CONTAINING_APPLICATION:
|
||||
return Relation(ApplicationAcc());
|
||||
|
||||
default:
|
||||
return Relation();
|
||||
}
|
||||
@ -2214,7 +2243,10 @@ Accessible::GetRelations(nsIArray **aRelations)
|
||||
nsIAccessibleRelation::RELATION_EMBEDDED_BY,
|
||||
nsIAccessibleRelation::RELATION_POPUP_FOR,
|
||||
nsIAccessibleRelation::RELATION_PARENT_WINDOW_OF,
|
||||
nsIAccessibleRelation::RELATION_DEFAULT_BUTTON
|
||||
nsIAccessibleRelation::RELATION_DEFAULT_BUTTON,
|
||||
nsIAccessibleRelation::RELATION_CONTAINING_DOCUMENT,
|
||||
nsIAccessibleRelation::RELATION_CONTAINING_TAB_PANE,
|
||||
nsIAccessibleRelation::RELATION_CONTAINING_APPLICATION
|
||||
};
|
||||
|
||||
for (uint32_t idx = 0; idx < ArrayLength(relationTypes); idx++) {
|
||||
|
@ -202,7 +202,10 @@ protected:
|
||||
NAVRELATION_DEFAULT_BUTTON = 0x100d,
|
||||
NAVRELATION_DESCRIBED_BY = 0x100e,
|
||||
NAVRELATION_DESCRIPTION_FOR = 0x100f,
|
||||
NAVRELATION_NODE_PARENT_OF = 0x1010
|
||||
NAVRELATION_NODE_PARENT_OF = 0x1010,
|
||||
NAVRELATION_CONTAINING_DOCUMENT = 0x1011,
|
||||
NAVRELATION_CONTAINING_TAB_PANE = 0x1012,
|
||||
NAVRELATION_CONTAINING_APPLICATION = 0x1014
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "DocAccessible.h"
|
||||
#include "nsAccUtils.h"
|
||||
#include "nsCoreUtils.h"
|
||||
#include "Relation.h"
|
||||
#include "uiaRawElmProvider.h"
|
||||
|
||||
#include "mozilla/Preferences.h"
|
||||
@ -60,33 +61,12 @@ ServiceProvider::QueryService(REFGUID aGuidService, REFIID aIID,
|
||||
if (aIID != IID_IAccessible)
|
||||
return E_NOINTERFACE;
|
||||
|
||||
nsCOMPtr<nsIDocShell> docShell =
|
||||
nsCoreUtils::GetDocShellFor(mAccessible->GetNode());
|
||||
if (!docShell)
|
||||
return E_UNEXPECTED;
|
||||
|
||||
// Walk up the parent chain without crossing the boundary at which item
|
||||
// types change, preventing us from walking up out of tab content.
|
||||
nsCOMPtr<nsIDocShellTreeItem> root;
|
||||
docShell->GetSameTypeRootTreeItem(getter_AddRefs(root));
|
||||
if (!root)
|
||||
return E_UNEXPECTED;
|
||||
|
||||
|
||||
// If the item type is typeContent, we assume we are in browser tab content.
|
||||
// Note this includes content such as about:addons, for consistency.
|
||||
int32_t itemType;
|
||||
root->GetItemType(&itemType);
|
||||
if (itemType != nsIDocShellTreeItem::typeContent)
|
||||
Relation rel = mAccessible->RelationByType(RelationType::CONTAINING_TAB_PANE);
|
||||
AccessibleWrap* tabDoc = static_cast<AccessibleWrap*>(rel.Next());
|
||||
if (!tabDoc)
|
||||
return E_NOINTERFACE;
|
||||
|
||||
// Make sure this is a document.
|
||||
DocAccessible* docAcc = nsAccUtils::GetDocAccessibleFor(root);
|
||||
if (!docAcc)
|
||||
return E_UNEXPECTED;
|
||||
|
||||
*aInstancePtr = static_cast<IAccessible*>(docAcc);
|
||||
|
||||
*aInstancePtr = static_cast<IAccessible*>(tabDoc);
|
||||
(reinterpret_cast<IUnknown*>(*aInstancePtr))->AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
|
@ -18,6 +18,9 @@ const RELATION_NODE_PARENT_OF = nsIAccessibleRelation.RELATION_NODE_PARENT_OF;
|
||||
const RELATION_PARENT_WINDOW_OF = nsIAccessibleRelation.RELATION_PARENT_WINDOW_OF;
|
||||
const RELATION_POPUP_FOR = nsIAccessibleRelation.RELATION_POPUP_FOR;
|
||||
const RELATION_SUBWINDOW_OF = nsIAccessibleRelation.RELATION_SUBWINDOW_OF;
|
||||
const RELATION_CONTAINING_DOCUMENT = nsIAccessibleRelation.RELATION_CONTAINING_DOCUMENT;
|
||||
const RELATION_CONTAINING_TAB_PANE = nsIAccessibleRelation.RELATION_CONTAINING_TAB_PANE;
|
||||
const RELATION_CONTAINING_APPLICATION = nsIAccessibleRelation.RELATION_CONTAINING_APPLICATION;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// General
|
||||
|
@ -167,6 +167,11 @@
|
||||
testRelation("legend", RELATION_LABEL_FOR, "fieldset");
|
||||
testRelation("fieldset", RELATION_LABELLED_BY, "legend");
|
||||
|
||||
// containing relations
|
||||
testRelation("control1_1", RELATION_CONTAINING_DOCUMENT, document);
|
||||
testRelation("control1_1", RELATION_CONTAINING_TAB_PANE, getTabDocAccessible("control1_1"));
|
||||
testRelation("control1_1", RELATION_CONTAINING_APPLICATION, getApplicationAccessible());
|
||||
|
||||
// finish test
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
@ -78,6 +78,12 @@ support-files =
|
||||
title_test.svg
|
||||
video.ogg
|
||||
zoom_test.html
|
||||
test_no_mcb_on_http_site_img.html
|
||||
test_no_mcb_on_http_site_img.css
|
||||
test_no_mcb_on_http_site_font.html
|
||||
test_no_mcb_on_http_site_font.css
|
||||
test_no_mcb_on_http_site_font2.html
|
||||
test_no_mcb_on_http_site_font2.css
|
||||
|
||||
[browser_CTP_data_urls.js]
|
||||
[browser_CTP_drag_drop.js]
|
||||
@ -288,3 +294,4 @@ support-files =
|
||||
[browser_zbug569342.js]
|
||||
[browser_registerProtocolHandler_notification.js]
|
||||
[browser_registerProtocolHandler_notification.html]
|
||||
[browser_no_mcb_on_http_site.js]
|
||||
|
@ -179,18 +179,3 @@ function MixedTest6D() {
|
||||
ok(content.document.getElementById('f1').contentDocument.getElementById('p1').innerHTML == "hello","Mixed script didn't load in Test 6");
|
||||
MixedTestsCompleted();
|
||||
}
|
||||
|
||||
function waitForCondition(condition, nextTest, errorMsg) {
|
||||
var tries = 0;
|
||||
var interval = setInterval(function() {
|
||||
if (tries >= 30) {
|
||||
ok(false, errorMsg);
|
||||
moveOn();
|
||||
}
|
||||
if (condition()) {
|
||||
moveOn();
|
||||
}
|
||||
tries++;
|
||||
}, 100);
|
||||
var moveOn = function() { clearInterval(interval); nextTest(); };
|
||||
}
|
||||
|
@ -41,26 +41,6 @@ function cleanUpAfterTests() {
|
||||
window.focus();
|
||||
finish();
|
||||
}
|
||||
/*
|
||||
* Whenever we disable the Mixed Content Blocker of the page
|
||||
* we have to make sure that our condition is properly loaded.
|
||||
*/
|
||||
function waitForCondition(condition, nextTest, errorMsg) {
|
||||
var tries = 0;
|
||||
var interval = setInterval(function() {
|
||||
if (tries >= 30) {
|
||||
ok(false, errorMsg);
|
||||
moveOn();
|
||||
}
|
||||
if (condition()) {
|
||||
moveOn();
|
||||
}
|
||||
tries++;
|
||||
}, 100);
|
||||
var moveOn = function() {
|
||||
clearInterval(interval); nextTest();
|
||||
};
|
||||
}
|
||||
|
||||
//------------------------ Test 1 ------------------------------
|
||||
|
||||
|
138
browser/base/content/test/general/browser_no_mcb_on_http_site.js
Normal file
138
browser/base/content/test/general/browser_no_mcb_on_http_site.js
Normal file
@ -0,0 +1,138 @@
|
||||
/*
|
||||
* Description of the Tests for
|
||||
* - Bug 909920 - Mixed content warning should not show on a HTTP site
|
||||
*
|
||||
* Description of the tests:
|
||||
* Test 1:
|
||||
* 1) Load an http page
|
||||
* 2) The page includes a css file using https
|
||||
* 3) The css file loads an |IMAGE| << over http
|
||||
*
|
||||
* Test 2:
|
||||
* 1) Load an http page
|
||||
* 2) The page includes a css file using https
|
||||
* 3) The css file loads a |FONT| over http
|
||||
*
|
||||
* Test 3:
|
||||
* 1) Load an http page
|
||||
* 2) The page includes a css file using https
|
||||
* 3) The css file imports (@import) another css file using http
|
||||
* 3) The imported css file loads a |FONT| over http
|
||||
*
|
||||
* Since the top-domain is >> NOT << served using https, the MCB
|
||||
* should >> NOT << trigger a warning.
|
||||
*/
|
||||
|
||||
const PREF_ACTIVE = "security.mixed_content.block_active_content";
|
||||
const PREF_DISPLAY = "security.mixed_content.block_display_content";
|
||||
|
||||
const gHttpTestRoot = "http://example.com/browser/browser/base/content/test/general/";
|
||||
|
||||
var origBlockActive, origBlockDisplay;
|
||||
var gTestBrowser = null;
|
||||
|
||||
registerCleanupFunction(function() {
|
||||
// Set preferences back to their original values
|
||||
Services.prefs.setBoolPref(PREF_ACTIVE, origBlockActive);
|
||||
Services.prefs.setBoolPref(PREF_DISPLAY, origBlockDisplay);
|
||||
});
|
||||
|
||||
function cleanUpAfterTests() {
|
||||
gBrowser.removeCurrentTab();
|
||||
window.focus();
|
||||
finish();
|
||||
}
|
||||
|
||||
function waitForCondition(condition, nextTest, errorMsg, okMsg) {
|
||||
var tries = 0;
|
||||
var interval = setInterval(function() {
|
||||
if (tries >= 30) {
|
||||
ok(false, errorMsg);
|
||||
moveOn();
|
||||
}
|
||||
if (condition()) {
|
||||
ok(true, okMsg)
|
||||
moveOn();
|
||||
}
|
||||
tries++;
|
||||
}, 100);
|
||||
var moveOn = function() {
|
||||
clearInterval(interval); nextTest();
|
||||
};
|
||||
}
|
||||
|
||||
//------------- TEST 1 -----------------------------------------
|
||||
|
||||
function test1A() {
|
||||
gTestBrowser.removeEventListener("load", test1A, true);
|
||||
|
||||
var expected = "Verifying MCB does not trigger warning/error for an http page ";
|
||||
expected += "with https css that includes http image";
|
||||
waitForCondition(
|
||||
function() content.document.getElementById('testDiv').innerHTML == expected,
|
||||
test1B, "Error: Waited too long for status in Test 1!",
|
||||
"OK: Expected result in innerHTML!");
|
||||
}
|
||||
|
||||
function test1B() {
|
||||
// set up test 2
|
||||
gTestBrowser.addEventListener("load", test2A, true);
|
||||
var url = gHttpTestRoot + "test_no_mcb_on_http_site_font.html";
|
||||
gTestBrowser.contentWindow.location = url;
|
||||
}
|
||||
|
||||
//------------- TEST 2 -----------------------------------------
|
||||
|
||||
function test2A() {
|
||||
gTestBrowser.removeEventListener("load", test2A, true);
|
||||
|
||||
var expected = "Verifying MCB does not trigger warning/error for an http page ";
|
||||
expected += "with https css that includes http font";
|
||||
waitForCondition(
|
||||
function() content.document.getElementById('testDiv').innerHTML == expected,
|
||||
test2B, "Error: Waited too long for status in Test 2!",
|
||||
"OK: Expected result in innerHTML!");
|
||||
}
|
||||
|
||||
function test2B() {
|
||||
// set up test 3
|
||||
gTestBrowser.addEventListener("load", test3, true);
|
||||
var url = gHttpTestRoot + "test_no_mcb_on_http_site_font2.html";
|
||||
gTestBrowser.contentWindow.location = url;
|
||||
}
|
||||
|
||||
//------------- TEST 3 -----------------------------------------
|
||||
|
||||
function test3() {
|
||||
gTestBrowser.removeEventListener("load", test3, true);
|
||||
|
||||
var expected = "Verifying MCB does not trigger warning/error for an http page "
|
||||
expected += "with https css that imports another http css which includes http font";
|
||||
waitForCondition(
|
||||
function() content.document.getElementById('testDiv').innerHTML == expected,
|
||||
cleanUpAfterTests, "Error: Waited too long for status in Test 3!",
|
||||
"OK: Expected result in innerHTML!");
|
||||
}
|
||||
|
||||
//------------------------------------------------------
|
||||
|
||||
function test() {
|
||||
// Performing async calls, e.g. 'onload', we have to wait till all of them finished
|
||||
waitForExplicitFinish();
|
||||
|
||||
// Store original preferences so we can restore settings after testing
|
||||
origBlockActive = Services.prefs.getBoolPref(PREF_ACTIVE);
|
||||
origBlockDisplay = Services.prefs.getBoolPref(PREF_DISPLAY);
|
||||
|
||||
Services.prefs.setBoolPref(PREF_ACTIVE, true);
|
||||
Services.prefs.setBoolPref(PREF_DISPLAY, true);
|
||||
|
||||
var newTab = gBrowser.addTab();
|
||||
gBrowser.selectedTab = newTab;
|
||||
gTestBrowser = gBrowser.selectedBrowser;
|
||||
newTab.linkedBrowser.stop();
|
||||
|
||||
gTestBrowser.addEventListener("load", test1A, true);
|
||||
var url = gHttpTestRoot + "test_no_mcb_on_http_site_img.html";
|
||||
gTestBrowser.contentWindow.location = url;
|
||||
}
|
@ -89,7 +89,14 @@ function waitForCondition(condition, nextTest, errorMsg) {
|
||||
ok(false, errorMsg);
|
||||
moveOn();
|
||||
}
|
||||
if (condition()) {
|
||||
var conditionPassed;
|
||||
try {
|
||||
conditionPassed = condition();
|
||||
} catch (e) {
|
||||
ok(false, e + "\n" + e.stack);
|
||||
conditionPassed = false;
|
||||
}
|
||||
if (conditionPassed) {
|
||||
moveOn();
|
||||
}
|
||||
tries++;
|
||||
|
@ -0,0 +1,10 @@
|
||||
@font-face {
|
||||
font-family: testFont;
|
||||
src: url(http://example.com/browser/browser/devtools/fontinspector/test/browser_font.woff);
|
||||
}
|
||||
body {
|
||||
font-family: Arial;
|
||||
}
|
||||
div {
|
||||
font-family: testFont;
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
Test 2 for Bug 909920 - See file browser_no_mcb_on_http_site.js for description.
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=909920
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test 2 for Bug 909920</title>
|
||||
<link rel="stylesheet" type="text/css" href="https://example.com/browser/browser/base/content/test/general/test_no_mcb_on_http_site_font.css" />
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
|
||||
<script type="text/javascript">
|
||||
function checkLoadStates() {
|
||||
var ui = SpecialPowers.wrap(window)
|
||||
.QueryInterface(SpecialPowers.Ci.nsIInterfaceRequestor)
|
||||
.getInterface(SpecialPowers.Ci.nsIWebNavigation)
|
||||
.QueryInterface(SpecialPowers.Ci.nsIDocShell)
|
||||
.securityUI;
|
||||
|
||||
var loadedMixedActive = ui &&
|
||||
(ui.state & SpecialPowers.Ci.nsIWebProgressListener.STATE_LOADED_MIXED_ACTIVE_CONTENT);
|
||||
is(loadedMixedActive, false, "OK: Should not load mixed active content!");
|
||||
|
||||
var blockedMixedActive = ui &&
|
||||
(ui.state & SpecialPowers.Ci.nsIWebProgressListener.STATE_BLOCKED_MIXED_ACTIVE_CONTENT);
|
||||
is(blockedMixedActive, false, "OK: Should not block mixed active content!");
|
||||
|
||||
var loadedMixedDisplay = ui &&
|
||||
(ui.state & SpecialPowers.Ci.nsIWebProgressListener.STATE_LOADED_MIXED_DISPLAY_CONTENT);
|
||||
is(loadedMixedDisplay, false, "OK: Should not load mixed display content!");
|
||||
|
||||
var blockedMixedDisplay = ui &&
|
||||
(ui.state & SpecialPowers.Ci.nsIWebProgressListener.STATE_BLOCKED_MIXED_DISPLAY_CONTENT);
|
||||
is(blockedMixedDisplay, false, "OK: Should not block mixed display content!");
|
||||
|
||||
var newValue = "Verifying MCB does not trigger warning/error for an http page with https css that includes http font";
|
||||
document.getElementById("testDiv").innerHTML = newValue;
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body onload="checkLoadStates()">
|
||||
<div class="testDiv" id="testDiv">
|
||||
Testing MCB does not trigger warning/error for an http page with https css that includes http font
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1 @@
|
||||
@import url(http://example.com/browser/browser/base/content/test/general/test_no_mcb_on_http_site_font.css);
|
@ -0,0 +1,48 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
Test 3 for Bug 909920 - See file browser_no_mcb_on_http_site.js for description.
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=909920
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test 3 for Bug 909920</title>
|
||||
<link rel="stylesheet" type="text/css" href="https://example.com/browser/browser/base/content/test/general/test_no_mcb_on_http_site_font2.css" />
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
|
||||
<script type="text/javascript">
|
||||
function checkLoadStates() {
|
||||
var ui = SpecialPowers.wrap(window)
|
||||
.QueryInterface(SpecialPowers.Ci.nsIInterfaceRequestor)
|
||||
.getInterface(SpecialPowers.Ci.nsIWebNavigation)
|
||||
.QueryInterface(SpecialPowers.Ci.nsIDocShell)
|
||||
.securityUI;
|
||||
|
||||
var loadedMixedActive = ui &&
|
||||
(ui.state & SpecialPowers.Ci.nsIWebProgressListener.STATE_LOADED_MIXED_ACTIVE_CONTENT);
|
||||
is(loadedMixedActive, false, "OK: Should not load mixed active content!");
|
||||
|
||||
var blockedMixedActive = ui &&
|
||||
(ui.state & SpecialPowers.Ci.nsIWebProgressListener.STATE_BLOCKED_MIXED_ACTIVE_CONTENT);
|
||||
is(blockedMixedActive, false, "OK: Should not block mixed active content!");
|
||||
|
||||
var loadedMixedDisplay = ui &&
|
||||
(ui.state & SpecialPowers.Ci.nsIWebProgressListener.STATE_LOADED_MIXED_DISPLAY_CONTENT);
|
||||
is(loadedMixedDisplay, false, "OK: Should not load mixed display content!");
|
||||
|
||||
var blockedMixedDisplay = ui &&
|
||||
(ui.state & SpecialPowers.Ci.nsIWebProgressListener.STATE_BLOCKED_MIXED_DISPLAY_CONTENT);
|
||||
is(blockedMixedDisplay, false, "OK: Should not block mixed display content!");
|
||||
|
||||
var newValue = "Verifying MCB does not trigger warning/error for an http page ";
|
||||
newValue += "with https css that imports another http css which includes http font";
|
||||
document.getElementById("testDiv").innerHTML = newValue;
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body onload="checkLoadStates()">
|
||||
<div class="testDiv" id="testDiv">
|
||||
Testing MCB does not trigger warning/error for an http page with https css that imports another http css which includes http font
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,3 @@
|
||||
#testDiv {
|
||||
background: url(http://example.com/tests/image/test/mochitest/blue.png)
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
Test 1 for Bug 909920 - See file browser_no_mcb_on_http_site.js for description.
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=909920
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test 1 for Bug 909920</title>
|
||||
<link rel="stylesheet" type="text/css" href="https://example.com/browser/browser/base/content/test/general/test_no_mcb_on_http_site_img.css" />
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
|
||||
<script type="text/javascript">
|
||||
function checkLoadStates() {
|
||||
var ui = SpecialPowers.wrap(window)
|
||||
.QueryInterface(SpecialPowers.Ci.nsIInterfaceRequestor)
|
||||
.getInterface(SpecialPowers.Ci.nsIWebNavigation)
|
||||
.QueryInterface(SpecialPowers.Ci.nsIDocShell)
|
||||
.securityUI;
|
||||
|
||||
var loadedMixedActive = ui &&
|
||||
(ui.state & SpecialPowers.Ci.nsIWebProgressListener.STATE_LOADED_MIXED_ACTIVE_CONTENT);
|
||||
is(loadedMixedActive, false, "OK: Should not load mixed active content!");
|
||||
|
||||
var blockedMixedActive = ui &&
|
||||
(ui.state & SpecialPowers.Ci.nsIWebProgressListener.STATE_BLOCKED_MIXED_ACTIVE_CONTENT);
|
||||
is(blockedMixedActive, false, "OK: Should not block mixed active content!");
|
||||
|
||||
var loadedMixedDisplay = ui &&
|
||||
(ui.state & SpecialPowers.Ci.nsIWebProgressListener.STATE_LOADED_MIXED_DISPLAY_CONTENT);
|
||||
is(loadedMixedDisplay, false, "OK: Should not load mixed display content!");
|
||||
|
||||
var blockedMixedDisplay = ui &&
|
||||
(ui.state & SpecialPowers.Ci.nsIWebProgressListener.STATE_BLOCKED_MIXED_DISPLAY_CONTENT);
|
||||
is(blockedMixedDisplay, false, "OK: Should not block mixed display content!");
|
||||
|
||||
var newValue = "Verifying MCB does not trigger warning/error for an http page with https css that includes http image";
|
||||
document.getElementById("testDiv").innerHTML = newValue;
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body onload="checkLoadStates()">
|
||||
<div class="testDiv" id="testDiv">
|
||||
Testing MCB does not trigger warning/error for an http page with https css that includes http image
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -18,7 +18,14 @@ function waitForCondition(condition, nextTest, errorMsg) {
|
||||
ok(false, errorMsg);
|
||||
moveOn();
|
||||
}
|
||||
if (condition()) {
|
||||
var conditionPassed;
|
||||
try {
|
||||
conditionPassed = condition();
|
||||
} catch (e) {
|
||||
ok(false, e + "\n" + e.stack);
|
||||
conditionPassed = false;
|
||||
}
|
||||
if (conditionPassed) {
|
||||
moveOn();
|
||||
}
|
||||
tries++;
|
||||
|
@ -2,7 +2,6 @@
|
||||
# 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/.
|
||||
|
||||
FORCE_STATIC_LIB = 1
|
||||
USE_STATIC_LIBS = 1
|
||||
|
||||
LOCAL_INCLUDES = -I$(srcdir)/../build
|
||||
|
@ -16,3 +16,4 @@ SOURCES += [
|
||||
|
||||
LIBRARY_NAME = 'browserabout_s'
|
||||
|
||||
FORCE_STATIC_LIB = True
|
||||
|
@ -2,7 +2,6 @@
|
||||
# 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/.
|
||||
|
||||
FORCE_STATIC_LIB = 1
|
||||
USE_STATIC_LIBS = 1
|
||||
|
||||
LOCAL_INCLUDES = -I$(srcdir)/../build
|
||||
|
@ -19,3 +19,5 @@ LIBRARY_NAME = 'browserdir_s'
|
||||
XPCSHELL_TESTS_MANIFESTS += [
|
||||
'tests/unit/xpcshell.ini',
|
||||
]
|
||||
|
||||
FORCE_STATIC_LIB = True
|
||||
|
@ -2,7 +2,6 @@
|
||||
# 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/.
|
||||
|
||||
FORCE_STATIC_LIB = 1
|
||||
USE_STATIC_LIBS = 1
|
||||
|
||||
DEFINES += \
|
||||
|
@ -22,3 +22,4 @@ EXTRA_PP_COMPONENTS += [
|
||||
|
||||
LIBRARY_NAME = 'browser_feeds_s'
|
||||
|
||||
FORCE_STATIC_LIB = True
|
||||
|
@ -2,7 +2,6 @@
|
||||
# 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/.
|
||||
|
||||
FORCE_STATIC_LIB = 1
|
||||
USE_STATIC_LIBS = 1
|
||||
|
||||
|
||||
|
@ -42,3 +42,4 @@ EXTRA_PP_JS_MODULES += [
|
||||
'MigrationUtils.jsm',
|
||||
]
|
||||
|
||||
FORCE_STATIC_LIB = True
|
||||
|
@ -3,7 +3,6 @@
|
||||
# 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/.
|
||||
|
||||
FORCE_STATIC_LIB = 1
|
||||
USE_STATIC_LIBS = 1
|
||||
|
||||
|
||||
|
@ -26,3 +26,5 @@ EXTRA_COMPONENTS += [
|
||||
'nsSetDefaultBrowser.js',
|
||||
'nsSetDefaultBrowser.manifest',
|
||||
]
|
||||
|
||||
FORCE_STATIC_LIB = True
|
||||
|
@ -102,6 +102,7 @@
|
||||
<button class="action-primary" onclick="UI.installSimulator()" title="&connection.installOneSimulatorTooltip;">&connection.installOneSimulator;</button>
|
||||
</div>
|
||||
<div class="found-simulator">
|
||||
<span>&connection.startRegisteredSimulator;</span>
|
||||
<span template-loop='{"arrayPath":"simulators.versions","childSelector":"#simulator-item-template"}'></span>
|
||||
<button class="action-primary" onclick="UI.installSimulator()" title="&connection.installAnotherSimulatorTooltip;">&connection.installAnotherSimulator;</button>
|
||||
</div>
|
||||
@ -124,7 +125,7 @@
|
||||
|
||||
<template id="simulator-item-template">
|
||||
<span>
|
||||
<button class="simulator-item" onclick="UI.startSimulator(this.dataset.version)" template='{"type":"attribute","path":"version","name":"data-version"}' title="&connection.startSimulatorTooltip;">
|
||||
<button class="simulator-item action-primary" onclick="UI.startSimulator(this.dataset.version)" template='{"type":"attribute","path":"version","name":"data-version"}' title="&connection.startSimulatorTooltip;">
|
||||
<span template='{"type":"textContent", "path":"version"}'></span>
|
||||
</button>
|
||||
</span>
|
||||
|
@ -21,6 +21,7 @@ const {gDevTools} = Cu.import("resource:///modules/devtools/gDevTools.jsm", {});
|
||||
const {HTMLEditor} = require("devtools/markupview/html-editor");
|
||||
const {OutputParser} = require("devtools/output-parser");
|
||||
const promise = require("sdk/core/promise");
|
||||
const {Tooltip} = require("devtools/shared/widgets/Tooltip");
|
||||
|
||||
Cu.import("resource://gre/modules/devtools/LayoutHelpers.jsm");
|
||||
Cu.import("resource://gre/modules/devtools/Templater.jsm");
|
||||
@ -374,7 +375,7 @@ MarkupView.prototype = {
|
||||
this._elt.appendChild(container.elt);
|
||||
this._rootNode = aNode;
|
||||
} else {
|
||||
var container = new MarkupContainer(this, aNode);
|
||||
var container = new MarkupContainer(this, aNode, this._inspector);
|
||||
if (aFlashNode) {
|
||||
container.flashMutation();
|
||||
}
|
||||
@ -1046,12 +1047,15 @@ MarkupView.prototype = {
|
||||
* The markup view that owns this container.
|
||||
* @param DOMNode aNode
|
||||
* The node to display.
|
||||
* @param Inspector aInspector
|
||||
* The inspector tool container the markup-view
|
||||
*/
|
||||
function MarkupContainer(aMarkupView, aNode) {
|
||||
function MarkupContainer(aMarkupView, aNode, aInspector) {
|
||||
this.markup = aMarkupView;
|
||||
this.doc = this.markup.doc;
|
||||
this.undo = this.markup.undo;
|
||||
this.node = aNode;
|
||||
this._inspector = aInspector;
|
||||
|
||||
if (aNode.nodeType == Ci.nsIDOMNode.TEXT_NODE) {
|
||||
this.editor = new TextEditor(this, aNode, "text");
|
||||
@ -1094,6 +1098,9 @@ function MarkupContainer(aMarkupView, aNode) {
|
||||
|
||||
this._onMouseDown = this._onMouseDown.bind(this);
|
||||
this.elt.addEventListener("mousedown", this._onMouseDown, false);
|
||||
|
||||
this.tooltip = null;
|
||||
this._attachTooltipIfNeeded();
|
||||
}
|
||||
|
||||
MarkupContainer.prototype = {
|
||||
@ -1101,6 +1108,39 @@ MarkupContainer.prototype = {
|
||||
return "[MarkupContainer for " + this.node + "]";
|
||||
},
|
||||
|
||||
_attachTooltipIfNeeded: function() {
|
||||
if (this.node.tagName) {
|
||||
let tagName = this.node.tagName.toLowerCase();
|
||||
let isImage = tagName === "img" &&
|
||||
this.editor.getAttributeElement("src");
|
||||
let isCanvas = tagName && tagName === "canvas";
|
||||
|
||||
// Get the image data for later so that when the user actually hovers over
|
||||
// the element, the tooltip does contain the image
|
||||
if (isImage || isCanvas) {
|
||||
this.tooltip = new Tooltip(this._inspector.panelDoc);
|
||||
|
||||
this.node.getImageData().then(data => {
|
||||
if (data) {
|
||||
data.string().then(str => {
|
||||
this.tooltip.setImageContent(str);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// If it's an image, show the tooltip on the src attribute
|
||||
if (isImage) {
|
||||
this.tooltip.startTogglingOnHover(this.editor.getAttributeElement("src"));
|
||||
}
|
||||
|
||||
// If it's a canvas, show it on the tag
|
||||
if (isCanvas) {
|
||||
this.tooltip.startTogglingOnHover(this.editor.tag);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* True if the current node has children. The MarkupView
|
||||
* will set this attribute for the MarkupContainer.
|
||||
@ -1335,6 +1375,12 @@ MarkupContainer.prototype = {
|
||||
|
||||
// Destroy my editor
|
||||
this.editor.destroy();
|
||||
|
||||
// Destroy the tooltip if any
|
||||
if (this.tooltip) {
|
||||
this.tooltip.destroy();
|
||||
this.tooltip = null;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -1348,7 +1394,7 @@ function RootContainer(aMarkupView, aNode) {
|
||||
this.elt.container = this;
|
||||
this.children = this.elt;
|
||||
this.node = aNode;
|
||||
this.toString = function() { return "[root container]"}
|
||||
this.toString = () => "[root container]";
|
||||
}
|
||||
|
||||
RootContainer.prototype = {
|
||||
@ -1578,6 +1624,16 @@ ElementEditor.prototype = {
|
||||
return this.node.startModifyingAttributes();
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the element used for one of the attributes of this element
|
||||
* @param string attrName The name of the attribute to get the element for
|
||||
* @return DOMElement
|
||||
*/
|
||||
getAttributeElement: function(attrName) {
|
||||
return this.attrList.querySelector(
|
||||
".attreditor[data-attr=" + attrName + "] .attr-value");
|
||||
},
|
||||
|
||||
_createAttribute: function(aAttr, aBefore = null) {
|
||||
// Create the template editor, which will save some variables here.
|
||||
let data = {
|
||||
|
@ -15,3 +15,5 @@ skip-if = true
|
||||
[browser_inspector_markup_navigation.js]
|
||||
[browser_inspector_markup_subset.html]
|
||||
[browser_inspector_markup_subset.js]
|
||||
[browser_inspector_markup_765105_tooltip.js]
|
||||
[browser_inspector_markup_765105_tooltip.png]
|
||||
|
@ -0,0 +1,137 @@
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
let {PanelFactory} = devtools.require("devtools/shared/widgets/Tooltip");
|
||||
|
||||
let contentDoc;
|
||||
let inspector;
|
||||
let markup;
|
||||
|
||||
const PAGE_CONTENT = [
|
||||
'<img class="local" src="chrome://branding/content/about-logo.png" />',
|
||||
'<img class="data" src="data:image/png;base64,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" />',
|
||||
'<img class="remote" src="http://mochi.test:8888/browser/browser/devtools/markupview/test/browser_inspector_markup_765105_tooltip.png" />',
|
||||
'<canvas class="canvas" width="600" height="600"></canvas>'
|
||||
].join("\n");
|
||||
|
||||
const TEST_NODES = [
|
||||
"img.local",
|
||||
"img.data",
|
||||
"img.remote",
|
||||
".canvas"
|
||||
];
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
gBrowser.selectedTab = gBrowser.addTab();
|
||||
gBrowser.selectedBrowser.addEventListener("load", function(evt) {
|
||||
gBrowser.selectedBrowser.removeEventListener(evt.type, arguments.callee, true);
|
||||
contentDoc = content.document;
|
||||
waitForFocus(createDocument, content);
|
||||
}, true);
|
||||
|
||||
content.location = "data:text/html,markup view tooltip test";
|
||||
}
|
||||
|
||||
function createDocument() {
|
||||
contentDoc.body.innerHTML = PAGE_CONTENT;
|
||||
|
||||
var target = TargetFactory.forTab(gBrowser.selectedTab);
|
||||
gDevTools.showToolbox(target, "inspector").then(function(toolbox) {
|
||||
inspector = toolbox.getCurrentPanel();
|
||||
markup = inspector.markup;
|
||||
startTests();
|
||||
});
|
||||
}
|
||||
|
||||
function startTests() {
|
||||
// Draw something in the canvas :)
|
||||
let doc = content.document;
|
||||
let context = doc.querySelector(".canvas").getContext("2d");
|
||||
|
||||
context.beginPath();
|
||||
context.moveTo(300, 0);
|
||||
context.lineTo(600, 600);
|
||||
context.lineTo(0, 600);
|
||||
context.closePath();
|
||||
context.fillStyle = "#ffc821";
|
||||
context.fill();
|
||||
|
||||
// Actually start testing
|
||||
inspector.selection.setNode(contentDoc.querySelector("img"));
|
||||
inspector.once("inspector-updated", () => {
|
||||
testImageTooltip(0);
|
||||
});
|
||||
}
|
||||
|
||||
function endTests() {
|
||||
contentDoc = inspector = markup = null;
|
||||
gBrowser.removeCurrentTab();
|
||||
finish();
|
||||
}
|
||||
|
||||
function testImageTooltip(index) {
|
||||
if (index === TEST_NODES.length) {
|
||||
return endTests();
|
||||
}
|
||||
|
||||
let node = contentDoc.querySelector(TEST_NODES[index]);
|
||||
ok(node, "We have the [" + TEST_NODES[index] + "] image node to test for tooltip");
|
||||
let isImg = node.tagName.toLowerCase() === "img";
|
||||
|
||||
let container = getContainerForRawNode(markup, node);
|
||||
|
||||
let target = container.editor.tag;
|
||||
if (isImg) {
|
||||
target = container.editor.getAttributeElement("src");
|
||||
}
|
||||
|
||||
assertTooltipShownOn(container.tooltip, target, () => {
|
||||
let images = container.tooltip.panel.getElementsByTagName("image");
|
||||
is(images.length, 1, "Tooltip for [" + TEST_NODES[index] + "] contains an image");
|
||||
if (isImg) {
|
||||
compareImageData(node, images[0].src);
|
||||
}
|
||||
|
||||
container.tooltip.hide();
|
||||
|
||||
testImageTooltip(index + 1);
|
||||
});
|
||||
}
|
||||
|
||||
function compareImageData(img, imgData) {
|
||||
let canvas = content.document.createElement("canvas");
|
||||
canvas.width = img.naturalWidth;
|
||||
canvas.height = img.naturalHeight;
|
||||
let ctx = canvas.getContext("2d");
|
||||
let data = "";
|
||||
try {
|
||||
ctx.drawImage(img, 0, 0);
|
||||
data = canvas.toDataURL("image/png");
|
||||
} catch (e) {}
|
||||
|
||||
is(data, imgData, "Tooltip image has the right content");
|
||||
}
|
||||
|
||||
function assertTooltipShownOn(tooltip, element, cb) {
|
||||
// If there is indeed a show-on-hover on element, the xul panel will be shown
|
||||
tooltip.panel.addEventListener("popupshown", function shown() {
|
||||
tooltip.panel.removeEventListener("popupshown", shown, true);
|
||||
|
||||
// Poll until the image gets loaded in the tooltip. This is required because
|
||||
// markup containers only load images in their associated tooltips when
|
||||
// the image data comes back from the server. However, this test is executed
|
||||
// synchronously as soon as "inspector-updated" is fired, which is before
|
||||
// the data for images is known.
|
||||
let hasImage = () => tooltip.panel.getElementsByTagName("image").length;
|
||||
let poll = setInterval(() => {
|
||||
if (hasImage()) {
|
||||
clearInterval(poll);
|
||||
cb();
|
||||
}
|
||||
}, 200);
|
||||
}, true);
|
||||
tooltip._showOnHover(element);
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 1.1 KiB |
@ -9,3 +9,4 @@ libs::
|
||||
$(NSINSTALL) $(srcdir)/*.jsm $(FINAL_TARGET)/modules/devtools
|
||||
$(NSINSTALL) $(srcdir)/widgets/*.jsm $(FINAL_TARGET)/modules/devtools
|
||||
$(NSINSTALL) $(srcdir)/*.js $(FINAL_TARGET)/modules/devtools/shared
|
||||
$(NSINSTALL) $(srcdir)/widgets/*.js $(FINAL_TARGET)/modules/devtools/shared/widgets
|
||||
|
420
browser/devtools/shared/widgets/Tooltip.js
Normal file
420
browser/devtools/shared/widgets/Tooltip.js
Normal file
@ -0,0 +1,420 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const {Cc, Cu, Ci} = require("chrome");
|
||||
const promise = require("sdk/core/promise");
|
||||
const IOService = Cc["@mozilla.org/network/io-service;1"]
|
||||
.getService(Ci.nsIIOService);
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource:///modules/devtools/ViewHelpers.jsm");
|
||||
|
||||
const GRADIENT_RE = /\b(repeating-)?(linear|radial)-gradient\(((rgb|hsl)a?\(.+?\)|[^\)])+\)/gi;
|
||||
const BORDERCOLOR_RE = /^border-[-a-z]*color$/ig;
|
||||
const BORDER_RE = /^border(-(top|bottom|left|right))?$/ig;
|
||||
const BACKGROUND_IMAGE_RE = /url\([\'\"]?(.*?)[\'\"]?\)/;
|
||||
|
||||
/**
|
||||
* Tooltip widget.
|
||||
*
|
||||
* This widget is intended at any tool that may need to show rich content in the
|
||||
* form of floating panels.
|
||||
* A common use case is image previewing in the CSS rule view, but more complex
|
||||
* use cases may include color pickers, object inspection, etc...
|
||||
*
|
||||
* Tooltips are based on XUL (namely XUL arrow-type <panel>s), and therefore
|
||||
* need a XUL Document to live in.
|
||||
* This is pretty much the only requirement they have on their environment.
|
||||
*
|
||||
* The way to use a tooltip is simply by instantiating a tooltip yourself and
|
||||
* attaching some content in it, or using one of the ready-made content types.
|
||||
*
|
||||
* A convenient `startTogglingOnHover` method may avoid having to register event
|
||||
* handlers yourself if the tooltip has to be shown when hovering over a
|
||||
* specific element or group of elements (which is usually the most common case)
|
||||
*/
|
||||
|
||||
/**
|
||||
* The low level structure of a tooltip is a XUL element (a <panel>, although
|
||||
* <tooltip> is supported too, it won't have the nice arrow shape).
|
||||
*/
|
||||
let PanelFactory = {
|
||||
get: function(doc, xulTag="panel") {
|
||||
// Create the tooltip
|
||||
let panel = doc.createElement(xulTag);
|
||||
panel.setAttribute("hidden", true);
|
||||
|
||||
if (xulTag === "panel") {
|
||||
// Prevent the click used to close the panel from being consumed
|
||||
panel.setAttribute("consumeoutsideclicks", false);
|
||||
panel.setAttribute("type", "arrow");
|
||||
panel.setAttribute("level", "top");
|
||||
}
|
||||
|
||||
panel.setAttribute("class", "devtools-tooltip devtools-tooltip-" + xulTag);
|
||||
doc.querySelector("window").appendChild(panel);
|
||||
|
||||
return panel;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Tooltip class.
|
||||
*
|
||||
* Basic usage:
|
||||
* let t = new Tooltip(xulDoc);
|
||||
* t.content = someXulContent;
|
||||
* t.show();
|
||||
* t.hide();
|
||||
* t.destroy();
|
||||
*
|
||||
* Better usage:
|
||||
* let t = new Tooltip(xulDoc);
|
||||
* t.startTogglingOnHover(container, target => {
|
||||
* if (<condition based on target>) {
|
||||
* t.setImageContent("http://image.png");
|
||||
* return true;
|
||||
* }
|
||||
* });
|
||||
* t.destroy();
|
||||
*
|
||||
* @param XULDocument doc
|
||||
* The XUL document hosting this tooltip
|
||||
*/
|
||||
function Tooltip(doc) {
|
||||
this.doc = doc;
|
||||
this.panel = PanelFactory.get(doc);
|
||||
|
||||
// Used for namedTimeouts in the mouseover handling
|
||||
this.uid = "tooltip-" + Date.now();
|
||||
}
|
||||
|
||||
module.exports.Tooltip = Tooltip;
|
||||
|
||||
Tooltip.prototype = {
|
||||
/**
|
||||
* Show the tooltip. It might be wise to append some content first if you
|
||||
* don't want the tooltip to be empty. You may access the content of the
|
||||
* tooltip by setting a XUL node to t.tooltip.content.
|
||||
* @param {node} anchor
|
||||
* Which node should the tooltip be shown on
|
||||
* @param {string} position
|
||||
* https://developer.mozilla.org/en-US/docs/XUL/PopupGuide/Positioning
|
||||
* Defaults to before_start
|
||||
*/
|
||||
show: function(anchor, position="before_start") {
|
||||
this.panel.hidden = false;
|
||||
this.panel.openPopup(anchor, position);
|
||||
},
|
||||
|
||||
/**
|
||||
* Hide the tooltip
|
||||
*/
|
||||
hide: function() {
|
||||
this.panel.hidden = true;
|
||||
this.panel.hidePopup();
|
||||
},
|
||||
|
||||
/**
|
||||
* Empty the tooltip's content
|
||||
*/
|
||||
empty: function() {
|
||||
while (this.panel.hasChildNodes()) {
|
||||
this.panel.removeChild(this.panel.firstChild);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Get rid of references and event listeners
|
||||
*/
|
||||
destroy: function () {
|
||||
this.hide();
|
||||
this.content = null;
|
||||
|
||||
this.doc = null;
|
||||
|
||||
this.panel.parentNode.removeChild(this.panel);
|
||||
this.panel = null;
|
||||
|
||||
if (this._basedNode) {
|
||||
this.stopTogglingOnHover();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Show/hide the tooltip when the mouse hovers over particular nodes.
|
||||
*
|
||||
* 2 Ways to make this work:
|
||||
* - Provide a single node to attach the tooltip to, as the baseNode, and
|
||||
* omit the second targetNodeCb argument
|
||||
* - Provide a baseNode that is the container of possibly numerous children
|
||||
* elements that may receive a tooltip. In this case, provide the second
|
||||
* targetNodeCb argument to decide wether or not a child should receive
|
||||
* a tooltip.
|
||||
*
|
||||
* This works by tracking mouse movements on a base container node (baseNode)
|
||||
* and showing the tooltip when the mouse stops moving. The targetNodeCb
|
||||
* callback is used to know whether or not the particular element being
|
||||
* hovered over should indeed receive the tooltip. If you don't provide it
|
||||
* it's equivalent to a function that always returns true.
|
||||
*
|
||||
* Note that if you call this function a second time, it will itself call
|
||||
* stopTogglingOnHover before adding mouse tracking listeners again.
|
||||
*
|
||||
* @param {node} baseNode
|
||||
* The container for all target nodes
|
||||
* @param {Function} targetNodeCb
|
||||
* A function that accepts a node argument and returns true or false
|
||||
* to signify if the tooltip should be shown on that node or not.
|
||||
* Additionally, the function receives a second argument which is the
|
||||
* tooltip instance itself, to be used to add/modify the content of the
|
||||
* tooltip if needed. If omitted, the tooltip will be shown everytime.
|
||||
* @param {Number} showDelay
|
||||
* An optional delay that will be observed before showing the tooltip.
|
||||
* Defaults to 750ms
|
||||
*/
|
||||
startTogglingOnHover: function(baseNode, targetNodeCb, showDelay = 750) {
|
||||
if (this._basedNode) {
|
||||
this.stopTogglingOnHover();
|
||||
}
|
||||
|
||||
this._basedNode = baseNode;
|
||||
this._showDelay = showDelay;
|
||||
this._targetNodeCb = targetNodeCb || (() => true);
|
||||
|
||||
this._onBaseNodeMouseMove = this._onBaseNodeMouseMove.bind(this);
|
||||
this._onBaseNodeMouseLeave = this._onBaseNodeMouseLeave.bind(this);
|
||||
|
||||
baseNode.addEventListener("mousemove", this._onBaseNodeMouseMove, false);
|
||||
baseNode.addEventListener("mouseleave", this._onBaseNodeMouseLeave, false);
|
||||
},
|
||||
|
||||
/**
|
||||
* If the startTogglingOnHover function has been used previously, and you want
|
||||
* to get rid of this behavior, then call this function to remove the mouse
|
||||
* movement tracking
|
||||
*/
|
||||
stopTogglingOnHover: function() {
|
||||
clearNamedTimeout(this.uid);
|
||||
|
||||
this._basedNode.removeEventListener("mousemove",
|
||||
this._onBaseNodeMouseMove, false);
|
||||
this._basedNode.removeEventListener("mouseleave",
|
||||
this._onBaseNodeMouseLeave, false);
|
||||
|
||||
this._basedNode = null;
|
||||
this._targetNodeCb = null;
|
||||
this._lastHovered = null;
|
||||
},
|
||||
|
||||
_onBaseNodeMouseMove: function(event) {
|
||||
if (event.target !== this._lastHovered) {
|
||||
this.hide();
|
||||
this._lastHovered = null;
|
||||
setNamedTimeout(this.uid, this._showDelay, () => {
|
||||
this._showOnHover(event.target);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
_showOnHover: function(target) {
|
||||
if (this._targetNodeCb && this._targetNodeCb(target, this)) {
|
||||
this.show(target);
|
||||
this._lastHovered = target;
|
||||
}
|
||||
},
|
||||
|
||||
_onBaseNodeMouseLeave: function() {
|
||||
clearNamedTimeout(this.uid);
|
||||
this._lastHovered = null;
|
||||
},
|
||||
|
||||
/**
|
||||
* Set the content of this tooltip. Will first empty the tooltip and then
|
||||
* append the new content element.
|
||||
* Consider using one of the set<type>Content() functions instead.
|
||||
* @param {node} content
|
||||
* A node that can be appended in the tooltip XUL element
|
||||
*/
|
||||
set content(content) {
|
||||
this.empty();
|
||||
if (content) {
|
||||
this.panel.appendChild(content);
|
||||
}
|
||||
},
|
||||
|
||||
get content() {
|
||||
return this.panel.firstChild;
|
||||
},
|
||||
|
||||
/**
|
||||
* Fill the tooltip with an image, displayed over a tiled background useful
|
||||
* for transparent images.
|
||||
* Also adds the image dimension as a label at the bottom.
|
||||
*/
|
||||
setImageContent: function(imageUrl, maxDim=400) {
|
||||
// Main container
|
||||
let vbox = this.doc.createElement("vbox");
|
||||
vbox.setAttribute("align", "center")
|
||||
|
||||
// Transparency tiles (image will go in there)
|
||||
let tiles = createTransparencyTiles(this.doc, vbox);
|
||||
|
||||
// Temporary label during image load
|
||||
let label = this.doc.createElement("label");
|
||||
label.classList.add("devtools-tooltip-caption");
|
||||
label.textContent = l10n.strings.GetStringFromName("previewTooltip.image.brokenImage");
|
||||
vbox.appendChild(label);
|
||||
|
||||
// Display the image
|
||||
let image = this.doc.createElement("image");
|
||||
image.setAttribute("src", imageUrl);
|
||||
if (maxDim) {
|
||||
image.style.maxWidth = maxDim + "px";
|
||||
image.style.maxHeight = maxDim + "px";
|
||||
}
|
||||
tiles.appendChild(image);
|
||||
|
||||
this.content = vbox;
|
||||
|
||||
// Load the image to get dimensions and display it when done
|
||||
let imgObj = new this.doc.defaultView.Image();
|
||||
imgObj.src = imageUrl;
|
||||
imgObj.onload = () => {
|
||||
imgObj.onload = null;
|
||||
|
||||
// Display dimensions
|
||||
label.textContent = imgObj.naturalWidth + " x " + imgObj.naturalHeight;
|
||||
if (imgObj.naturalWidth > maxDim ||
|
||||
imgObj.naturalHeight > maxDim) {
|
||||
label.textContent += " *";
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Exactly the same as the `image` function but takes a css background image
|
||||
* value instead : url(....)
|
||||
*/
|
||||
setCssBackgroundImageContent: function(cssBackground, sheetHref, maxDim=400) {
|
||||
let uri = getBackgroundImageUri(cssBackground, sheetHref);
|
||||
if (uri) {
|
||||
this.setImageContent(uri, maxDim);
|
||||
}
|
||||
},
|
||||
|
||||
setCssGradientContent: function(cssGradient) {
|
||||
let tiles = createTransparencyTiles(this.doc);
|
||||
|
||||
let gradientBox = this.doc.createElement("box");
|
||||
gradientBox.width = "100";
|
||||
gradientBox.height = "100";
|
||||
gradientBox.style.background = this.cssGradient;
|
||||
gradientBox.style.borderRadius = "2px";
|
||||
gradientBox.style.boxShadow = "inset 0 0 4px #333";
|
||||
|
||||
tiles.appendChild(gradientBox)
|
||||
|
||||
this.content = tiles;
|
||||
},
|
||||
|
||||
_setSimpleCssPropertiesContent: function(properties, width, height) {
|
||||
let tiles = createTransparencyTiles(this.doc);
|
||||
|
||||
let box = this.doc.createElement("box");
|
||||
box.width = width + "";
|
||||
box.height = height + "";
|
||||
properties.forEach(({name, value}) => {
|
||||
box.style[name] = value;
|
||||
});
|
||||
tiles.appendChild(box);
|
||||
|
||||
this.content = tiles;
|
||||
},
|
||||
|
||||
setCssColorContent: function(cssColor) {
|
||||
this._setSimpleCssPropertiesContent([
|
||||
{name: "background", value: cssColor},
|
||||
{name: "borderRadius", value: "2px"},
|
||||
{name: "boxShadow", value: "inset 0 0 4px #333"},
|
||||
], 50, 50);
|
||||
},
|
||||
|
||||
setCssBoxShadowContent: function(cssBoxShadow) {
|
||||
this._setSimpleCssPropertiesContent([
|
||||
{name: "background", value: "white"},
|
||||
{name: "boxShadow", value: cssBoxShadow}
|
||||
], 80, 80);
|
||||
},
|
||||
|
||||
setCssBorderContent: function(cssBorder) {
|
||||
this._setSimpleCssPropertiesContent([
|
||||
{name: "background", value: "white"},
|
||||
{name: "border", value: cssBorder}
|
||||
], 80, 80);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Internal utility function that creates a tiled background useful for
|
||||
* displaying semi-transparent images
|
||||
*/
|
||||
function createTransparencyTiles(doc, parentEl) {
|
||||
let tiles = doc.createElement("box");
|
||||
tiles.classList.add("devtools-tooltip-tiles");
|
||||
if (parentEl) {
|
||||
parentEl.appendChild(tiles);
|
||||
}
|
||||
return tiles;
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal util, checks whether a css declaration is a gradient
|
||||
*/
|
||||
function isGradientRule(property, value) {
|
||||
return (property === "background" || property === "background-image") &&
|
||||
value.match(GRADIENT_RE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal util, checks whether a css declaration is a color
|
||||
*/
|
||||
function isColorOnly(property, value) {
|
||||
return property === "background-color" ||
|
||||
property === "color" ||
|
||||
property.match(BORDERCOLOR_RE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal util, returns the background image uri if any
|
||||
*/
|
||||
function getBackgroundImageUri(value, sheetHref) {
|
||||
let uriMatch = BACKGROUND_IMAGE_RE.exec(value);
|
||||
let uri = null;
|
||||
|
||||
if (uriMatch && uriMatch[1]) {
|
||||
uri = uriMatch[1];
|
||||
if (sheetHref) {
|
||||
let sheetUri = IOService.newURI(sheetHref, null, null);
|
||||
uri = sheetUri.resolve(uri);
|
||||
}
|
||||
}
|
||||
|
||||
return uri;
|
||||
}
|
||||
|
||||
/**
|
||||
* L10N utility class
|
||||
*/
|
||||
function L10N() {}
|
||||
L10N.prototype = {};
|
||||
|
||||
let l10n = new L10N();
|
||||
|
||||
loader.lazyGetter(L10N.prototype, "strings", () => {
|
||||
return Services.strings.createBundle(
|
||||
"chrome://browser/locale/devtools/inspector.properties");
|
||||
});
|
@ -11,8 +11,8 @@ let {CssLogic} = require("devtools/styleinspector/css-logic");
|
||||
let {ELEMENT_STYLE} = require("devtools/server/actors/styles");
|
||||
let promise = require("sdk/core/promise");
|
||||
let {EventEmitter} = require("devtools/shared/event-emitter");
|
||||
|
||||
const {OutputParser} = require("devtools/output-parser");
|
||||
const {Tooltip} = require("devtools/shared/widgets/Tooltip");
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/PluralForm.jsm");
|
||||
@ -169,6 +169,11 @@ function CssHtmlTree(aStyleInspector, aPageStyle)
|
||||
// The element that we're inspecting, and the document that it comes from.
|
||||
this.viewedElement = null;
|
||||
|
||||
// Properties preview tooltip
|
||||
this.tooltip = new Tooltip(this.styleInspector.inspector.panelDoc);
|
||||
this.tooltip.startTogglingOnHover(this.propertyContainer,
|
||||
this._buildTooltipContent.bind(this));
|
||||
|
||||
this._buildContextMenu();
|
||||
this.createStyleViews();
|
||||
}
|
||||
@ -490,6 +495,29 @@ CssHtmlTree.prototype = {
|
||||
win.focus();
|
||||
},
|
||||
|
||||
/**
|
||||
* Verify that target is indeed a css value we want a tooltip on, and if yes
|
||||
* prepare some content for the tooltip
|
||||
*/
|
||||
_buildTooltipContent: function(target)
|
||||
{
|
||||
// If the hovered element is not a property view and is not a background
|
||||
// image, then don't show a tooltip
|
||||
let isPropertyValue = target.classList.contains("property-value");
|
||||
if (!isPropertyValue) {
|
||||
return false;
|
||||
}
|
||||
let propName = target.parentNode.querySelector(".property-name");
|
||||
let isBackgroundImage = propName.textContent === "background-image";
|
||||
if (!isBackgroundImage) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Fill some content
|
||||
this.tooltip.setCssBackgroundImageContent(target.textContent);
|
||||
return true;
|
||||
},
|
||||
|
||||
/**
|
||||
* Create a context menu.
|
||||
*/
|
||||
@ -648,6 +676,9 @@ CssHtmlTree.prototype = {
|
||||
this._contextmenu = null;
|
||||
}
|
||||
|
||||
this.tooltip.stopTogglingOnHover(this.propertyContainer);
|
||||
this.tooltip.destroy();
|
||||
|
||||
// Remove bound listeners
|
||||
this.styleDocument.removeEventListener("contextmenu", this._onContextMenu);
|
||||
this.styleDocument.removeEventListener("copy", this._onCopy);
|
||||
@ -831,9 +862,8 @@ PropertyView.prototype = {
|
||||
{
|
||||
let doc = this.tree.styleDocument;
|
||||
|
||||
this.onMatchedToggle = this.onMatchedToggle.bind(this);
|
||||
|
||||
// Build the container element
|
||||
this.onMatchedToggle = this.onMatchedToggle.bind(this);
|
||||
this.element = doc.createElementNS(HTML_NS, "div");
|
||||
this.element.setAttribute("class", this.propertyHeaderClassName);
|
||||
this.element.addEventListener("dblclick", this.onMatchedToggle, false);
|
||||
@ -858,6 +888,8 @@ PropertyView.prototype = {
|
||||
this.matchedExpander.addEventListener("click", this.onMatchedToggle, false);
|
||||
this.element.appendChild(this.matchedExpander);
|
||||
|
||||
this.focusElement = () => this.element.focus();
|
||||
|
||||
// Build the style name element
|
||||
this.nameNode = doc.createElementNS(HTML_NS, "div");
|
||||
this.nameNode.setAttribute("class", "property-name theme-fg-color5");
|
||||
@ -1034,7 +1066,7 @@ PropertyView.prototype = {
|
||||
};
|
||||
|
||||
/**
|
||||
* A container to view us easy access to display data from a CssRule
|
||||
* A container to give us easy access to display data from a CssRule
|
||||
* @param CssHtmlTree aTree, the owning CssHtmlTree
|
||||
* @param aSelectorInfo
|
||||
*/
|
||||
|
@ -13,6 +13,7 @@ let {CssLogic} = require("devtools/styleinspector/css-logic");
|
||||
let {InplaceEditor, editableField, editableItem} = require("devtools/shared/inplace-editor");
|
||||
let {ELEMENT_STYLE, PSEUDO_ELEMENTS} = require("devtools/server/actors/styles");
|
||||
let {gDevTools} = Cu.import("resource:///modules/devtools/gDevTools.jsm", {});
|
||||
let {Tooltip} = require("devtools/shared/widgets/Tooltip");
|
||||
|
||||
const {OutputParser} = require("devtools/output-parser");
|
||||
|
||||
@ -1029,6 +1030,7 @@ TextProperty.prototype = {
|
||||
* apply to a given element. After construction, the 'element'
|
||||
* property will be available with the user interface.
|
||||
*
|
||||
* @param {Inspector} aInspector
|
||||
* @param {Document} aDoc
|
||||
* The document that will contain the rule view.
|
||||
* @param {object} aStore
|
||||
@ -1039,8 +1041,9 @@ TextProperty.prototype = {
|
||||
* The PageStyleFront for communicating with the remote server.
|
||||
* @constructor
|
||||
*/
|
||||
function CssRuleView(aDoc, aStore, aPageStyle)
|
||||
function CssRuleView(aInspector, aDoc, aStore, aPageStyle)
|
||||
{
|
||||
this.inspector = aInspector;
|
||||
this.doc = aDoc;
|
||||
this.store = aStore || {};
|
||||
this.pageStyle = aPageStyle;
|
||||
@ -1067,6 +1070,9 @@ function CssRuleView(aDoc, aStore, aPageStyle)
|
||||
};
|
||||
this.popup = new AutocompletePopup(aDoc.defaultView.parent.document, options);
|
||||
|
||||
this.tooltip = new Tooltip(this.inspector.panelDoc);
|
||||
this.tooltip.startTogglingOnHover(this.element, this._buildTooltipContent.bind(this));
|
||||
|
||||
this._buildContextMenu();
|
||||
this._showEmpty();
|
||||
}
|
||||
@ -1107,6 +1113,37 @@ CssRuleView.prototype = {
|
||||
popupset.appendChild(this._contextmenu);
|
||||
},
|
||||
|
||||
/**
|
||||
* Verify that target is indeed a css value we want a tooltip on, and if yes
|
||||
* prepare some content for the tooltip
|
||||
*/
|
||||
_buildTooltipContent: function(target) {
|
||||
let isValueWithImage = target.classList.contains("ruleview-propertyvalue") &&
|
||||
target.querySelector(".theme-link");
|
||||
|
||||
let isImageHref = target.classList.contains("theme-link") &&
|
||||
target.parentNode.classList.contains("ruleview-propertyvalue");
|
||||
if (isImageHref) {
|
||||
target = target.parentNode;
|
||||
}
|
||||
|
||||
let isEditing = this.isEditing;
|
||||
|
||||
// If the inplace-editor is visible or if this is not a background image
|
||||
// don't show the tooltip
|
||||
if (this.isEditing || (!isImageHref && !isValueWithImage)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Retrieve the TextProperty for the hovered element
|
||||
let property = target.textProperty;
|
||||
let href = property.rule.domRule.href;
|
||||
|
||||
// Fill some content
|
||||
this.tooltip.setCssBackgroundImageContent(property.value, href);
|
||||
return true;
|
||||
},
|
||||
|
||||
/**
|
||||
* Update the context menu. This means enabling or disabling menuitems as
|
||||
* appropriate.
|
||||
@ -1240,6 +1277,9 @@ CssRuleView.prototype = {
|
||||
// We manage the popupNode ourselves so we also need to destroy it.
|
||||
this.doc.popupNode = null;
|
||||
|
||||
this.tooltip.stopTogglingOnHover(this.element);
|
||||
this.tooltip.destroy();
|
||||
|
||||
if (this.element.parentNode) {
|
||||
this.element.parentNode.removeChild(this.element);
|
||||
}
|
||||
@ -1307,7 +1347,6 @@ CssRuleView.prototype = {
|
||||
}
|
||||
this._createEditors();
|
||||
|
||||
|
||||
// Notify anyone that cares that we refreshed.
|
||||
var evt = this.doc.createEvent("Events");
|
||||
evt.initEvent("CssRuleViewRefreshed", true, false);
|
||||
@ -1853,6 +1892,10 @@ TextPropertyEditor.prototype = {
|
||||
tabindex: "0",
|
||||
});
|
||||
|
||||
// Storing the TextProperty on the valuespan for easy access
|
||||
// (for instance by the tooltip)
|
||||
this.valueSpan.textProperty = this.prop;
|
||||
|
||||
// Save the initial value as the last committed value,
|
||||
// for restoring after pressing escape.
|
||||
this.committed = { name: this.prop.name,
|
||||
@ -1971,7 +2014,6 @@ TextPropertyEditor.prototype = {
|
||||
});
|
||||
|
||||
a.addEventListener("click", (aEvent) => {
|
||||
|
||||
// Clicks within the link shouldn't trigger editing.
|
||||
aEvent.stopPropagation();
|
||||
aEvent.preventDefault();
|
||||
@ -2133,6 +2175,7 @@ TextPropertyEditor.prototype = {
|
||||
{
|
||||
this.element.parentNode.removeChild(this.element);
|
||||
this.ruleEditor.rule.editClosestTextProperty(this.prop);
|
||||
this.valueSpan.textProperty = null;
|
||||
this.prop.remove();
|
||||
},
|
||||
|
||||
|
@ -25,7 +25,7 @@ function RuleViewTool(aInspector, aWindow, aIFrame)
|
||||
this.doc = aWindow.document;
|
||||
this.outerIFrame = aIFrame;
|
||||
|
||||
this.view = new RuleView.CssRuleView(this.doc);
|
||||
this.view = new RuleView.CssRuleView(aInspector, this.doc);
|
||||
this.doc.documentElement.appendChild(this.view.element);
|
||||
|
||||
this._changeHandler = () => {
|
||||
|
@ -38,6 +38,7 @@ MOCHITEST_BROWSER_FILES = \
|
||||
browser_ruleview_pseudoelement.js \
|
||||
browser_computedview_bug835808_keyboard_nav.js \
|
||||
browser_bug913014_matched_expand.js \
|
||||
browser_bug765105_background_image_tooltip.js \
|
||||
head.js \
|
||||
$(NULL)
|
||||
|
||||
|
@ -0,0 +1,162 @@
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
let contentDoc;
|
||||
let inspector;
|
||||
let ruleView;
|
||||
let computedView;
|
||||
|
||||
const PAGE_CONTENT = [
|
||||
'<style type="text/css">',
|
||||
' body {',
|
||||
' padding: 1em;',
|
||||
' background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAADI5JREFUeNrsWwuQFNUVPf1m5z87szv7HWSWj8CigBFMEFZKiQsB1PgJwUAZg1HBpIQsKmokEhNjWUnFVPnDWBT+KolJYbRMoqUVq0yCClpqiX8sCchPWFwVlt2db7+X93pez7zu6Vn2NxsVWh8987p7pu+9555z7+tZjTGGY3kjOMa34w447oBjfKsY7i/UNM3Y8eFSAkD50Plgw03K5P9gvGv7U5ieeR3PszeREiPNX3/0DL4hjslzhm8THh+OITfXk3dhiv4GDtGPVzCaeJmPLYzuu5qJuWfuw2QTlcN1X9pwQU7LhdZ/ZAseD45cOh9hHvDkc/yAF/DNhdb5Mrr3PvBMaAYW8fMSIi2G497IMEK/YutGtAYr6+ej+nxu/NN8Ks3N7AR6HgcLz0Eg1Ljg1UcxZzi5qewIkMYLRweTr2Kzp+nmyXAd5pS3XQDd+N/4h4zgu9FI7brlXf90nMEnuwQxlvv+hosE3TuexmWeysmT4W+WxkMaLzf9Y8ATgjcUn7T9H1gqrpFq8eV1gMn6t16NhngjfoX6q4DUP032Rd4LJgpSLwJ1yzFqBG69eRkah0MVyo0Acfe+yy9AG4nMiYCkeM53KKFXncBLAXqEm+wCqZwaueq7WCmuLTcKSJmj737ol2hurA9eq9VdyiO8yWa3NNyog+SB5CZodSsQq/dfu34tJpYbBaTMzvVddDZu16q5smXf4G8zEvqm4cyaAmJPuTJk3oJWdS4WzcVtfMZbThSQckb/pYfRGgo3zNOqZnEHbJPGK4abaDCQIIsT8V/qTaBqHkLh6LzXH8XZQhbLhYKyyCC/WeHYcNdmvOgfe8skzbWL270/T3wf7tSx/lGCbTu8xlzzmCSWLc5iwmgikcCHi3Mga0Ry913vBFvQwg90l6M4ImWKfsWOp7DSWxmfpPlCFuPFfsNfKrCnPYpQKIRgqBK7D0SxYaNHwkEiJMtl0ReDp3Lc5D3PGoTo/sKngCl7a5chFqvBatKwjBd7WwqIlzB/78NcoUcp5VSgGxm+7b8eqQRGnHMO634epO4S1EZww09/iFg5UmGoESDuznP1xVhTUX1WWHPzjpd25wyH0hRxI3LGM75nxmuNEEUVpAN0XgxmPoKralakbQnWlIMQyVBD/w+3orkq4lvualjKyWwzt4MaxqspQHVhPOWG64bxYuhZXSFGWhipbSDVragOu5Y9eAsmDDUKyBA703vemVhHoueD6e9wAzJK1WfmN0Umk5GGM4kEMZcuIECqgjm0nldAqmbjwtm4VxZH5AvlADP6mx9Eqy9Q0+KqW8Ch+47FaMMYmnNGfY1iPMshoC6qFxme4wQ+0p+ARE6H3+9veWEDWgUhDhUKyFARn4jM5BNxT0XsMg7bfymGK1ov3wtjDfhL4w0HVGUVBEjDaaE+QNdrcNWch1PG4W6xrjBUXECGivg++Cva3JUT4iQUz3V2RsSVaKLwOuDT89A3HdBQoxhNC+fnVm74ual2EG893P6G+PuP4SfiO4cCBWQooL9qCWKNXPbcI37Aa/lnlZxXRt4RFONGwSDCPAHqOuqjWct1QiEMw5mChM5X4K47FyNqcd3aK9AwFH0CGYLoe1ctxk2eWi57rg5JfGp9rzC6ggCdFlAgHBDw5Yxlcg6G8SyHCjMlsgmDD9zhSeHlF+JnAgWDTQUy2NxfdwOao1UVV3pi3+bE97YSbWpLAbn6zefHNQkp1PMpIBwwvslKgIYTKM2nEpNzrGcH3FXTEal0L38kJ4uDQgEZbO4vnI173LXf5NHZaiUxtaCxyZuo/rK6LpUg54yg3zTWRAArvDcRIPZ6BqzrQ1REpmL+DNw32OKIDCb3X1qPVn8wNNMT4w2bvs+q4bAZrqBh2skaL3yyhhIIZ4i6oHkUK0RckcB8GigEyRIH4A6Mgc8fatl0/+BkkQxC9gIT4ljna1rIZW9rEdNbjJcNjsnoYj7LHWCUwpITzEgzRQKZ3XAFHbTzA3hrz8TEUUZxFBhoKpABQt/97p+w0hMZG68I8R6FtlsJT3FELndZntjM+VMnylKYq8GJI3UZaRMpquGSGFVOEfv0YZBMNzz+uvjbfzS6xQERIhlI9FcvQWNdFVb7x1zCb+QNK8vb9NsiifmI5hBgVoOCBC1sb0ab5RomqENxLO3eA1/0NDRU47q2RQNbRCUDIb7lF2CNL3ZGxEV4n08TVvZWYG4pZyV0zUdS45tyCBByOHWiyvZmxFXDCyRo1ge5+Sy0TA+8lWMiP/6O0S32exGV9Jf4fr8azdUR3zL/CZz4MtvzdX5uOYs6NDOmpkuj5Huh+7qUQSYl0ThHzw0YQzcGo6bhzEqoYq5rN3yRiYiG3Vfe2Ybm/qKA9NNZ3nNm4F7/yDkg9AN+U1mHiBcXP8zuDN76jj8hg1QyiWQigalj02BJPhK8I0zxijAjhp5zhlpLUDvS+BCy2HMAvvB4XDgL9/SXC0g/ou/5+6/xLX8w0uJrOIkXfPvyhY0F6gr7M8H0KWFYikcqAXakB+xwD9CdREBLoau7Gz3cAdSIdLFxFtJTCqRChSjnutvhDcREtzjz2Tswtz+yeNRFUeXZXtWux7C1fuoVcbd3J//ipDX3uZZDLGrwweS+UBLL5TDliVBnF8P7H+XI8aRRGsIBJg/Zlslt1+W+D1JWoSyi+kD9jfhs78t7mhZhSl+fLfY1Bdyv3I8V/qpY3B1McgN7ZFT5/vNO0I5DPLLdPBIJA8qc4h2I0QplYfDpJwHT+aj0246r5S8rToG8OjCle8wk4OLvvYGa+Ovr84uo2qBSwJS9G5egoZFLTfiEqWDtbwGfHgKOdPHcS+ai7XDzMPW/FJRLGGcxnBbK4YJC2K+h+T6Bdu5CqHqCWERd3bawb7JI+iJ735+LNaHaprBLLHBm08U3XxShEsdt+f3eTh3v7aC95Dct4RCWL5OZWh/oXBZThxAIxyOXLzBk8aiEWJID8rK3CpPOmeHaGpvCS+7EHv5FujVHUSJPLXvIFeHcNc+9xrB2gws9KZdxuLFax/WLM5gzzSm/lTXF/OdAcapyvjxPqxqHjr2v4ckX2bS2dRBrc5lSdpKjEJ9/9tdwX2WMd53ZQ2IVo3RES+UwVSpCPvYepNx4gmTGDUKIMQ4eduPnD7mx9xOn/KZKOlFbStjONxHTtR+BYAPmnoZ1Zp8wkBRwP/EL3u0F/C2hGl7vpz7vW37T3vP7if8wroKuoh8ribknX9BK5rcF+mo1qKaKyRPJTgTDjbzY8szcuLb3bpH00u35T47j7prRpwDJTxzyG0dHgxPp5bPG8VdkpfPbUg3SgoOo2mwVukb98D5EqpswZTTulCggTk4gpYhv0++wIhCJxr0+Hq1sondis0SE2oxQe3qWXwWyO4DSQg9gJ8Iiw1VFcGqXxet0N9xE4ygIxv/9W6wo9WyROEX/R+eiobYSq2vHTOR631Eiv2lRfh9dvxkumkXh92Qsx8XrAJ+7YGbWuhxOi/U+31NQmzyqNYG8N/3wfo6CRtRHcN01FzkvojohwLu0VVvDa56IS/xcj2b7nN+O+m0jqpE1wMPXZxAN9iCVThtDvH7gmiRGRpU8Lspv1Uhq4wIVdQoyuGSLNYPKUCS8+CzNURbzMmjK3i8u0U793lmuV0ef9nWQ5MGC/DiUqEUSaCtXna9RJEspZS1lrXINK/pcq+SpT50t98QKMq1FRmDfx3vxty102k0PM4ssEnvuz5+G26Ij4yDpz6z9fV8bkyIkqBFkhej0Ib+ZQ34XJK9AfozaiimqIoX3Jp3tiISrcfYpuN2+iFph/02P36PNC9fVcCnp6H9jYouKyfaWufz5Tp9tVxcUniw7IohZv4dZz81/ns67z3AYPrc2n0+Ix2q8k0PWjgBy88XaibnfK9A+5LdDY2Ivhy36fbT8Zv3Lb1U1qLqUxorXEEXIs0mjjrtxoTZWtdvigNs2sgPiujTv6DIZLld6b/V5742JZV3fUsUVFy5gdsNtKWFzUCEVbNepD1MkSMVbsb6SZm7jI3/zODtQKgUMsOw8wDZ63t5xcV1TnaEAxoc6wrqY+Fj+N4DsqOnhOIdicrQSm1MPYCPlIqHn5bbHg8/bj2D3QfZnCX3mpAICDZV8jH5kpbZqTD0W+DxaA74CWzLN2nd14OlL72J38Lf7+TjC7dadZFDoZJQPrtaIKL/G0L6ktptPZVJ8fMqHYPZOKYPMyQGadIJfDvdXwAFiZOTvDBPydf5vk4rWA+RfdhBlaF/yDDBRoMu9pfnSjv/p7DG+HXfAcQcc49v/BBgAcFAO4DmB2GQAAAAASUVORK5CYII=);',
|
||||
' background-repeat: repeat-y;',
|
||||
' background-position: right top;',
|
||||
' }',
|
||||
' .test-element {',
|
||||
' font-family: verdana;',
|
||||
' color: #333;',
|
||||
' background: url(chrome://global/skin/icons/warning-64.png) no-repeat left center;',
|
||||
' padding-left: 70px;',
|
||||
' }',
|
||||
'</style>',
|
||||
'<div class="test-element">test element</div>',
|
||||
'<div class="test-element-2">test element 2</div>'
|
||||
].join("\n");
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
gBrowser.selectedTab = gBrowser.addTab();
|
||||
gBrowser.selectedBrowser.addEventListener("load", function(evt) {
|
||||
gBrowser.selectedBrowser.removeEventListener(evt.type, arguments.callee, true);
|
||||
contentDoc = content.document;
|
||||
waitForFocus(createDocument, content);
|
||||
}, true);
|
||||
|
||||
content.location = "data:text/html,rule view tooltip test";
|
||||
}
|
||||
|
||||
function createDocument() {
|
||||
contentDoc.body.innerHTML = PAGE_CONTENT;
|
||||
|
||||
openRuleView((aInspector, aRuleView) => {
|
||||
inspector = aInspector;
|
||||
ruleView = aRuleView;
|
||||
startTests();
|
||||
});
|
||||
}
|
||||
|
||||
function startTests() {
|
||||
// let testElement = contentDoc.querySelector(".test-element");
|
||||
|
||||
inspector.selection.setNode(contentDoc.body);
|
||||
inspector.once("inspector-updated", testBodyRuleView);
|
||||
}
|
||||
|
||||
function endTests() {
|
||||
contentDoc = inspector = ruleView = computedView = null;
|
||||
gBrowser.removeCurrentTab();
|
||||
finish();
|
||||
}
|
||||
|
||||
function assertTooltipShownOn(tooltip, element, cb) {
|
||||
// If there is indeed a show-on-hover on element, the xul panel will be shown
|
||||
tooltip.panel.addEventListener("popupshown", function shown() {
|
||||
tooltip.panel.removeEventListener("popupshown", shown, true);
|
||||
cb();
|
||||
}, true);
|
||||
tooltip._showOnHover(element);
|
||||
}
|
||||
|
||||
function testBodyRuleView() {
|
||||
info("Testing tooltips in the rule view");
|
||||
|
||||
let panel = ruleView.tooltip.panel;
|
||||
|
||||
// Check that the rule view has a tooltip and that a XUL panel has been created
|
||||
ok(ruleView.tooltip, "Tooltip instance exists");
|
||||
ok(panel, "XUL panel exists");
|
||||
|
||||
// Get the background-image property inside the rule view
|
||||
let {nameSpan, valueSpan} = getRuleViewProperty("background-image");
|
||||
// And verify that the tooltip gets shown on this property
|
||||
assertTooltipShownOn(ruleView.tooltip, valueSpan, () => {
|
||||
let images = panel.getElementsByTagName("image");
|
||||
is(images.length, 1, "Tooltip contains an image");
|
||||
ok(images[0].src.indexOf("iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHe") !== -1, "The image URL seems fine");
|
||||
|
||||
ruleView.tooltip.hide();
|
||||
|
||||
inspector.selection.setNode(contentDoc.querySelector(".test-element"));
|
||||
inspector.once("inspector-updated", testDivRuleView);
|
||||
});
|
||||
}
|
||||
|
||||
function testDivRuleView() {
|
||||
let panel = ruleView.tooltip.panel;
|
||||
|
||||
// Get the background property inside the rule view
|
||||
let {nameSpan, valueSpan} = getRuleViewProperty("background");
|
||||
let uriSpan = valueSpan.querySelector(".theme-link");
|
||||
|
||||
// And verify that the tooltip gets shown on this property
|
||||
assertTooltipShownOn(ruleView.tooltip, uriSpan, () => {
|
||||
let images = panel.getElementsByTagName("image");
|
||||
is(images.length, 1, "Tooltip contains an image");
|
||||
ok(images[0].src === "chrome://global/skin/icons/warning-64.png");
|
||||
|
||||
ruleView.tooltip.hide();
|
||||
|
||||
testComputedView();
|
||||
});
|
||||
}
|
||||
|
||||
function testComputedView() {
|
||||
info("Testing tooltips in the computed view");
|
||||
|
||||
inspector.sidebar.select("computedview");
|
||||
computedView = inspector.sidebar.getWindowForTab("computedview").computedview.view;
|
||||
let doc = computedView.styleDocument;
|
||||
|
||||
let panel = computedView.tooltip.panel;
|
||||
let {nameSpan, valueSpan} = getComputedViewProperty("background-image");
|
||||
|
||||
assertTooltipShownOn(computedView.tooltip, valueSpan, () => {
|
||||
let images = panel.getElementsByTagName("image");
|
||||
is(images.length, 1, "Tooltip contains an image");
|
||||
ok(images[0].src === "chrome://global/skin/icons/warning-64.png");
|
||||
|
||||
computedView.tooltip.hide();
|
||||
|
||||
endTests();
|
||||
});
|
||||
}
|
||||
|
||||
function getRuleViewProperty(name) {
|
||||
let prop = null;
|
||||
[].forEach.call(ruleView.doc.querySelectorAll(".ruleview-property"), property => {
|
||||
let nameSpan = property.querySelector(".ruleview-propertyname");
|
||||
let valueSpan = property.querySelector(".ruleview-propertyvalue");
|
||||
|
||||
if (nameSpan.textContent === name) {
|
||||
prop = {nameSpan: nameSpan, valueSpan: valueSpan};
|
||||
}
|
||||
});
|
||||
return prop;
|
||||
}
|
||||
|
||||
function getComputedViewProperty(name) {
|
||||
let prop = null;
|
||||
[].forEach.call(computedView.styleDocument.querySelectorAll(".property-view"), property => {
|
||||
let nameSpan = property.querySelector(".property-name");
|
||||
let valueSpan = property.querySelector(".property-value");
|
||||
|
||||
if (nameSpan.textContent === name) {
|
||||
prop = {nameSpan: nameSpan, valueSpan: valueSpan};
|
||||
}
|
||||
});
|
||||
return prop;
|
||||
}
|
@ -57,6 +57,7 @@
|
||||
<!ENTITY connection.installOneSimulatorTooltip "Install a version of the Simulator by downloading the relevant add-on.">
|
||||
<!ENTITY connection.installAnotherSimulator "Add">
|
||||
<!ENTITY connection.installAnotherSimulatorTooltip "Install an additional version of the Simulator by downloading the relevant add-on.">
|
||||
<!ENTITY connection.startRegisteredSimulator "Start:">
|
||||
|
||||
<!ENTITY projects.localApps "Local Apps">
|
||||
<!ENTITY projects.addApp "Add">
|
||||
|
@ -31,7 +31,6 @@ debuggerPausedWarning.message=Debugger is paused. Some features like mouse selec
|
||||
# the node is selected.
|
||||
nodeMenu.tooltiptext=Node operations
|
||||
|
||||
|
||||
# LOCALIZATION NOTE (inspector.*)
|
||||
# Used for the menuitem in the tool menu
|
||||
inspector.label=Inspector
|
||||
@ -44,3 +43,6 @@ inspector.accesskey=I
|
||||
markupView.more.showing=Some nodes were hidden.
|
||||
markupView.more.showAll=Show All %S Nodes
|
||||
inspector.tooltip=DOM and Style Inspector
|
||||
|
||||
#LOCALIZATION NOTE: Used in the image preview tooltip when the image could not be loaded
|
||||
previewTooltip.image.brokenImage=Could not load the image
|
||||
|
@ -17,6 +17,13 @@
|
||||
-moz-border-start-color: transparent;
|
||||
}
|
||||
|
||||
/* Sources toolbar */
|
||||
|
||||
#sources-toolbar {
|
||||
border: none; /* Remove the devtools-toolbar's black bottom border. */
|
||||
-moz-border-end: 1px solid #222426; /* Match the sources list's dark margin. */
|
||||
}
|
||||
|
||||
#pretty-print {
|
||||
min-width: 0;
|
||||
font-weight: bold;
|
||||
@ -435,3 +442,8 @@
|
||||
#body[layout=vertical] .side-menu-widget-item-arrow {
|
||||
background-image: none !important;
|
||||
}
|
||||
|
||||
#body[layout=vertical] .side-menu-widget-group,
|
||||
#body[layout=vertical] .side-menu-widget-item {
|
||||
-moz-margin-end: 0;
|
||||
}
|
||||
|
@ -279,6 +279,8 @@
|
||||
color: #000;
|
||||
}
|
||||
|
||||
/* SideMenuWidget container */
|
||||
|
||||
.side-menu-widget-container[with-arrows=true]:-moz-locale-dir(ltr) {
|
||||
box-shadow: inset -1px 0 0 #222426;
|
||||
}
|
||||
@ -287,6 +289,18 @@
|
||||
box-shadow: inset 1px 0 0 #222426;
|
||||
}
|
||||
|
||||
.side-menu-widget-container[with-arrows=true] .side-menu-widget-group {
|
||||
/* To allow visibility of the dark margin shadow. */
|
||||
-moz-margin-end: 1px;
|
||||
}
|
||||
|
||||
.side-menu-widget-container[with-arrows=true] .side-menu-widget-item {
|
||||
/* To compensate for the arrow image's dark margin. */
|
||||
-moz-margin-end: -1px;
|
||||
}
|
||||
|
||||
/* SideMenuWidget groups */
|
||||
|
||||
.side-menu-widget-group-title {
|
||||
padding: 4px;
|
||||
}
|
||||
@ -308,6 +322,8 @@
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/* SideMenuWidget items */
|
||||
|
||||
.side-menu-widget-item[theme="dark"] {
|
||||
border-top: 1px solid hsla(210,8%,5%,.25);
|
||||
border-bottom: 1px solid hsla(210,16%,76%,.1);
|
||||
@ -343,15 +359,17 @@
|
||||
}
|
||||
|
||||
.side-menu-widget-item.selected > .side-menu-widget-item-arrow:-moz-locale-dir(ltr) {
|
||||
background-image: url(itemArrow-ltr.png), linear-gradient(to right, black, black);
|
||||
background-image: url(itemArrow-ltr.png), linear-gradient(to right, #222426, #222426);
|
||||
background-position: center right, top right;
|
||||
}
|
||||
|
||||
.side-menu-widget-item.selected > .side-menu-widget-item-arrow:-moz-locale-dir(rtl) {
|
||||
background-image: url(itemArrow-rtl.png), linear-gradient(to right, black, black);
|
||||
background-image: url(itemArrow-rtl.png), linear-gradient(to right, #222426, #222426);
|
||||
background-position: center left, top left;
|
||||
}
|
||||
|
||||
/* SideMenuWidget items contents */
|
||||
|
||||
.side-menu-widget-item-label {
|
||||
padding: 4px 0px;
|
||||
}
|
||||
@ -385,6 +403,8 @@
|
||||
text-shadow: 0 1px 1px #111;
|
||||
}
|
||||
|
||||
/* SideMenuWidget misc */
|
||||
|
||||
.side-menu-widget-empty-notice-container {
|
||||
padding: 12px;
|
||||
}
|
||||
|
@ -19,6 +19,13 @@
|
||||
-moz-border-start-color: transparent;
|
||||
}
|
||||
|
||||
/* Sources toolbar */
|
||||
|
||||
#sources-toolbar {
|
||||
border: none; /* Remove the devtools-toolbar's black bottom border. */
|
||||
-moz-border-end: 1px solid #222426; /* Match the sources list's dark margin. */
|
||||
}
|
||||
|
||||
#pretty-print {
|
||||
min-width: 0;
|
||||
font-weight: bold;
|
||||
@ -437,3 +444,8 @@
|
||||
#body[layout=vertical] .side-menu-widget-item-arrow {
|
||||
background-image: none !important;
|
||||
}
|
||||
|
||||
#body[layout=vertical] .side-menu-widget-group,
|
||||
#body[layout=vertical] .side-menu-widget-item {
|
||||
-moz-margin-end: 0;
|
||||
}
|
||||
|
@ -279,6 +279,8 @@
|
||||
color: #000;
|
||||
}
|
||||
|
||||
/* SideMenuWidget container */
|
||||
|
||||
.side-menu-widget-container[with-arrows=true]:-moz-locale-dir(ltr) {
|
||||
box-shadow: inset -1px 0 0 #222426;
|
||||
}
|
||||
@ -287,6 +289,18 @@
|
||||
box-shadow: inset 1px 0 0 #222426;
|
||||
}
|
||||
|
||||
.side-menu-widget-container[with-arrows=true] .side-menu-widget-group {
|
||||
/* To allow visibility of the dark margin shadow. */
|
||||
-moz-margin-end: 1px;
|
||||
}
|
||||
|
||||
.side-menu-widget-container[with-arrows=true] .side-menu-widget-item {
|
||||
/* To compensate for the arrow image's dark margin. */
|
||||
-moz-margin-end: -1px;
|
||||
}
|
||||
|
||||
/* SideMenuWidget groups */
|
||||
|
||||
.side-menu-widget-group-title {
|
||||
padding: 4px;
|
||||
}
|
||||
@ -308,6 +322,8 @@
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/* SideMenuWidget items */
|
||||
|
||||
.side-menu-widget-item[theme="dark"] {
|
||||
border-top: 1px solid hsla(210,8%,5%,.25);
|
||||
border-bottom: 1px solid hsla(210,16%,76%,.1);
|
||||
@ -343,15 +359,17 @@
|
||||
}
|
||||
|
||||
.side-menu-widget-item.selected > .side-menu-widget-item-arrow:-moz-locale-dir(ltr) {
|
||||
background-image: url(itemArrow-ltr.png), linear-gradient(to right, black, black);
|
||||
background-image: url(itemArrow-ltr.png), linear-gradient(to right, #222426, #222426);
|
||||
background-position: center right, top right;
|
||||
}
|
||||
|
||||
.side-menu-widget-item.selected > .side-menu-widget-item-arrow:-moz-locale-dir(rtl) {
|
||||
background-image: url(itemArrow-rtl.png), linear-gradient(to right, black, black);
|
||||
background-image: url(itemArrow-rtl.png), linear-gradient(to right, #222426, #222426);
|
||||
background-position: center left, top left;
|
||||
}
|
||||
|
||||
/* SideMenuWidget items contents */
|
||||
|
||||
.side-menu-widget-item-label {
|
||||
padding: 4px 0px;
|
||||
}
|
||||
@ -385,6 +403,8 @@
|
||||
text-shadow: 0 1px 1px #111;
|
||||
}
|
||||
|
||||
/* SideMenuWidget misc */
|
||||
|
||||
.side-menu-widget-empty-notice-container {
|
||||
padding: 12px;
|
||||
}
|
||||
|
@ -111,3 +111,25 @@
|
||||
max-height: 75vh;
|
||||
}
|
||||
}
|
||||
|
||||
/* Tooltip widget (see browser/devtools/shared/widgets/Tooltip.js) */
|
||||
|
||||
.devtools-tooltip.devtools-tooltip-tooltip {
|
||||
/* If the tooltip uses a <tooltip> XUL element */
|
||||
-moz-appearance: none;
|
||||
padding: 4px;
|
||||
background: #eee;
|
||||
border-radius: 3px;
|
||||
}
|
||||
.devtools-tooltip.devtools-tooltip-panel .panel-arrowcontent {
|
||||
/* If the tooltip uses a <panel> XUL element instead */
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
.devtools-tooltip-tiles {
|
||||
background-color: #eee;
|
||||
background-image: linear-gradient(45deg, #ccc 25%, transparent 25%, transparent 75%, #ccc 75%, #ccc),
|
||||
linear-gradient(45deg, #ccc 25%, transparent 25%, transparent 75%, #ccc 75%, #ccc);
|
||||
background-size: 20px 20px;
|
||||
background-position: 0 0, 10px 10px;
|
||||
}
|
||||
|
@ -17,6 +17,13 @@
|
||||
-moz-border-start-color: transparent;
|
||||
}
|
||||
|
||||
/* Sources toolbar */
|
||||
|
||||
#sources-toolbar {
|
||||
border: none; /* Remove the devtools-toolbar's black bottom border. */
|
||||
-moz-border-end: 1px solid #222426; /* Match the sources list's dark margin. */
|
||||
}
|
||||
|
||||
#pretty-print {
|
||||
min-width: 0;
|
||||
font-weight: bold;
|
||||
@ -440,3 +447,8 @@
|
||||
#body[layout=vertical] .side-menu-widget-item-arrow {
|
||||
background-image: none !important;
|
||||
}
|
||||
|
||||
#body[layout=vertical] .side-menu-widget-group,
|
||||
#body[layout=vertical] .side-menu-widget-item {
|
||||
-moz-margin-end: 0;
|
||||
}
|
||||
|
@ -283,6 +283,8 @@
|
||||
color: #000;
|
||||
}
|
||||
|
||||
/* SideMenuWidget container */
|
||||
|
||||
.side-menu-widget-container[with-arrows=true]:-moz-locale-dir(ltr) {
|
||||
box-shadow: inset -1px 0 0 #222426;
|
||||
}
|
||||
@ -291,6 +293,18 @@
|
||||
box-shadow: inset 1px 0 0 #222426;
|
||||
}
|
||||
|
||||
.side-menu-widget-container[with-arrows=true] .side-menu-widget-group {
|
||||
/* To allow visibility of the dark margin shadow. */
|
||||
-moz-margin-end: 1px;
|
||||
}
|
||||
|
||||
.side-menu-widget-container[with-arrows=true] .side-menu-widget-item {
|
||||
/* To compensate for the arrow image's dark margin. */
|
||||
-moz-margin-end: -1px;
|
||||
}
|
||||
|
||||
/* SideMenuWidget groups */
|
||||
|
||||
.side-menu-widget-group-title {
|
||||
padding: 4px;
|
||||
}
|
||||
@ -312,6 +326,8 @@
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/* SideMenuWidget items */
|
||||
|
||||
.side-menu-widget-item[theme="dark"] {
|
||||
border-top: 1px solid hsla(210,8%,5%,.25);
|
||||
border-bottom: 1px solid hsla(210,16%,76%,.1);
|
||||
@ -347,15 +363,17 @@
|
||||
}
|
||||
|
||||
.side-menu-widget-item.selected > .side-menu-widget-item-arrow:-moz-locale-dir(ltr) {
|
||||
background-image: url(itemArrow-ltr.png), linear-gradient(to right, black, black);
|
||||
background-image: url(itemArrow-ltr.png), linear-gradient(to right, #222426, #222426);
|
||||
background-position: center right, top right;
|
||||
}
|
||||
|
||||
.side-menu-widget-item.selected > .side-menu-widget-item-arrow:-moz-locale-dir(rtl) {
|
||||
background-image: url(itemArrow-rtl.png), linear-gradient(to right, black, black);
|
||||
background-image: url(itemArrow-rtl.png), linear-gradient(to right, #222426, #222426);
|
||||
background-position: center left, top left;
|
||||
}
|
||||
|
||||
/* SideMenuWidget items contents */
|
||||
|
||||
.side-menu-widget-item-label {
|
||||
padding: 4px 0px;
|
||||
}
|
||||
@ -388,6 +406,8 @@
|
||||
color: #f5f7fa;
|
||||
}
|
||||
|
||||
/* SideMenuWidget misc */
|
||||
|
||||
.side-menu-widget-empty-notice-container {
|
||||
padding: 12px;
|
||||
}
|
||||
|
@ -2,19 +2,6 @@
|
||||
# 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/.
|
||||
|
||||
JAVA_JAR_TARGETS += annotationProcessors
|
||||
annotationProcessors_DEST := annotationProcessors.jar
|
||||
annotationProcessors_JAVAFILES := \
|
||||
AnnotationProcessor.java \
|
||||
CodeGenerator.java \
|
||||
MethodWithAnnotationInfo.java \
|
||||
classloader/IterableJarLoadingURLClassLoader.java \
|
||||
classloader/JarClassIterator.java \
|
||||
utils/AlphabeticMethodComparator.java \
|
||||
utils/GeneratableEntryPointIterator.java \
|
||||
utils/Utils.java \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
JAVA_CLASSPATH := $(ANDROID_SDK)/android.jar
|
||||
|
@ -3,3 +3,15 @@
|
||||
# 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/.
|
||||
|
||||
jar = add_java_jar('annotationProcessors')
|
||||
jar.sources += [
|
||||
'AnnotationProcessor.java',
|
||||
'CodeGenerator.java',
|
||||
'MethodWithAnnotationInfo.java',
|
||||
'classloader/IterableJarLoadingURLClassLoader.java',
|
||||
'classloader/JarClassIterator.java',
|
||||
'utils/AlphabeticMethodComparator.java',
|
||||
'utils/GeneratableEntryPointIterator.java',
|
||||
'utils/Utils.java',
|
||||
]
|
||||
|
@ -3,7 +3,6 @@
|
||||
# You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
MODULES = stlport
|
||||
FORCE_STATIC_LIB = 1
|
||||
STL_FLAGS =
|
||||
|
||||
# Force to build a static library, instead of a fake library, without
|
||||
|
@ -6,3 +6,4 @@
|
||||
|
||||
LIBRARY_NAME = 'stlport_static'
|
||||
|
||||
FORCE_STATIC_LIB = True
|
||||
|
@ -2,7 +2,6 @@
|
||||
# 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/.
|
||||
|
||||
FORCE_STATIC_LIB= 1
|
||||
STL_FLAGS =
|
||||
NO_EXPAND_LIBS = 1
|
||||
NO_PROFILE_GUIDED_OPTIMIZE = 1
|
||||
|
@ -16,3 +16,4 @@ if CONFIG['MOZ_LIBSTDCXX_HOST_VERSION']:
|
||||
'stdc++compat.cpp',
|
||||
]
|
||||
|
||||
FORCE_STATIC_LIB = True
|
||||
|
@ -41,12 +41,14 @@ _MOZBUILD_EXTERNAL_VARIABLES := \
|
||||
DIRS \
|
||||
EXTRA_PP_COMPONENTS \
|
||||
EXTRA_PP_JS_MODULES \
|
||||
FORCE_STATIC_LIB \
|
||||
GTEST_CMMSRCS \
|
||||
GTEST_CPPSRCS \
|
||||
GTEST_CSRCS \
|
||||
HOST_CSRCS \
|
||||
HOST_LIBRARY_NAME \
|
||||
IS_COMPONENT \
|
||||
JAVA_JAR_TARGETS \
|
||||
JS_MODULES_PATH \
|
||||
LIBRARY_NAME \
|
||||
LIBXUL_LIBRARY \
|
||||
|
@ -986,7 +986,6 @@ CSPSourceList.fromString = function(aStr, aCSPRep, self, enforceSelfChecks) {
|
||||
// if a source is a *, then we can permit all sources
|
||||
if (src.permitAll) {
|
||||
slObj._permitAllSources = true;
|
||||
return slObj;
|
||||
} else {
|
||||
slObj._sources.push(src);
|
||||
}
|
||||
|
@ -343,54 +343,85 @@ nsMixedContentBlocker::ShouldLoad(uint32_t aContentType,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// We need aRequestingLocation to pull out the scheme. If it isn't passed
|
||||
// in, get it from the aRequestingPricipal
|
||||
if (!aRequestingLocation) {
|
||||
if (!aRequestPrincipal) {
|
||||
// If we don't have aRequestPrincipal, try getting it from the
|
||||
// DOM node using aRequestingContext
|
||||
nsCOMPtr<nsINode> node = do_QueryInterface(aRequestingContext);
|
||||
if (node) {
|
||||
aRequestPrincipal = node->NodePrincipal();
|
||||
} else {
|
||||
// Try using the window's script object principal if it's not a node.
|
||||
nsCOMPtr<nsIScriptObjectPrincipal> scriptObjPrin = do_QueryInterface(aRequestingContext);
|
||||
if (scriptObjPrin) {
|
||||
aRequestPrincipal = scriptObjPrin->GetPrincipal();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (aRequestPrincipal) {
|
||||
nsCOMPtr<nsIURI> principalUri;
|
||||
nsresult rvalue = aRequestPrincipal->GetURI(getter_AddRefs(principalUri));
|
||||
if (NS_SUCCEEDED(rvalue)) {
|
||||
aRequestingLocation = principalUri;
|
||||
}
|
||||
}
|
||||
// Since there are cases where aRequestingLocation and aRequestPrincipal are
|
||||
// definitely not the owning document, we try to ignore them by extracting the
|
||||
// requestingLocation in the following order:
|
||||
// 1) from the aRequestingContext, either extracting
|
||||
// a) the node's principal, or the
|
||||
// b) script object's principal.
|
||||
// 2) if aRequestingContext yields a principal but no location, we check
|
||||
// if its the system principal. If it is, allow the load.
|
||||
// 3) Special case handling for:
|
||||
// a) speculative loads, where shouldLoad is called twice (bug 839235)
|
||||
// and the first speculative load does not include a context.
|
||||
// In this case we use aRequestingLocation to set requestingLocation.
|
||||
// b) TYPE_CSP_REPORT which does not provide a context. In this case we
|
||||
// use aRequestingLocation to set requestingLocation.
|
||||
// c) content scripts from addon code that do not provide aRequestingContext
|
||||
// or aRequestingLocation, but do provide aRequestPrincipal.
|
||||
// If aRequestPrincipal is an expanded principal, we allow the load.
|
||||
// 4) If we still end up not having a requestingLocation, we reject the load.
|
||||
|
||||
if (!aRequestingLocation) {
|
||||
// If content scripts from an addon are causing this load, they have an
|
||||
// ExpandedPrincipal instead of a Principal. This is pseudo-privileged code, so allow
|
||||
// the load. Or if this is system principal, allow the load.
|
||||
nsCOMPtr<nsIExpandedPrincipal> expanded = do_QueryInterface(aRequestPrincipal);
|
||||
if (expanded || (aRequestPrincipal && nsContentUtils::IsSystemPrincipal(aRequestPrincipal))) {
|
||||
*aDecision = ACCEPT;
|
||||
return NS_OK;
|
||||
} else {
|
||||
// We still don't have a requesting location and there is no Expanded Principal.
|
||||
// We can't tell if this is a mixed content load. Deny to be safe.
|
||||
*aDecision = REJECT_REQUEST;
|
||||
return NS_OK;
|
||||
}
|
||||
nsCOMPtr<nsIPrincipal> principal;
|
||||
// 1a) Try to get the principal if aRequestingContext is a node.
|
||||
nsCOMPtr<nsINode> node = do_QueryInterface(aRequestingContext);
|
||||
if (node) {
|
||||
principal = node->NodePrincipal();
|
||||
}
|
||||
|
||||
// 1b) Try using the window's script object principal if it's not a node.
|
||||
if (!principal) {
|
||||
nsCOMPtr<nsIScriptObjectPrincipal> scriptObjPrin = do_QueryInterface(aRequestingContext);
|
||||
if (scriptObjPrin) {
|
||||
principal = scriptObjPrin->GetPrincipal();
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIURI> requestingLocation;
|
||||
if (principal) {
|
||||
principal->GetURI(getter_AddRefs(requestingLocation));
|
||||
}
|
||||
|
||||
// 2) if aRequestingContext yields a principal but no location, we check if its a system principal.
|
||||
if (principal && !requestingLocation) {
|
||||
if (nsContentUtils::IsSystemPrincipal(principal)) {
|
||||
*aDecision = ACCEPT;
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
// 3a,b) Special case handling for speculative loads and TYPE_CSP_REPORT. In
|
||||
// such cases, aRequestingContext doesn't exist, so we use aRequestingLocation.
|
||||
// Unfortunately we can not distinguish between speculative and normal loads here,
|
||||
// otherwise we could special case this assignment.
|
||||
if (!requestingLocation) {
|
||||
requestingLocation = aRequestingLocation;
|
||||
}
|
||||
|
||||
// 3c) Special case handling for content scripts from addons code, which only
|
||||
// provide a aRequestPrincipal; aRequestingContext and aRequestingLocation are
|
||||
// both null; if the aRequestPrincipal is an expandedPrincipal, we allow the load.
|
||||
if (!principal && !requestingLocation && aRequestPrincipal) {
|
||||
nsCOMPtr<nsIExpandedPrincipal> expanded = do_QueryInterface(aRequestPrincipal);
|
||||
if (expanded) {
|
||||
*aDecision = ACCEPT;
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
// 4) Giving up. We still don't have a requesting location, therefore we can't tell
|
||||
// if this is a mixed content load. Deny to be safe.
|
||||
if (!requestingLocation) {
|
||||
*aDecision = REJECT_REQUEST;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Check the parent scheme. If it is not an HTTPS page then mixed content
|
||||
// restrictions do not apply.
|
||||
bool parentIsHttps;
|
||||
nsresult rv = aRequestingLocation->SchemeIs("https", &parentIsHttps);
|
||||
nsresult rv = requestingLocation->SchemeIs("https", &parentIsHttps);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_ERROR("aRequestingLocation->SchemeIs failed");
|
||||
NS_ERROR("requestingLocation->SchemeIs failed");
|
||||
*aDecision = REJECT_REQUEST;
|
||||
return NS_OK;
|
||||
}
|
||||
|
20
content/base/test/csp/file_CSP_bug909029_none.html
Normal file
20
content/base/test/csp/file_CSP_bug909029_none.html
Normal file
@ -0,0 +1,20 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<!-- file_CSP.sjs mocks a resource load -->
|
||||
<link rel='stylesheet' type='text/css'
|
||||
href='file_CSP.sjs?testid=noneExternalStylesBlocked&type=text/css' />
|
||||
</head>
|
||||
<body>
|
||||
<p id="inline-style">This should be green</p>
|
||||
<p id="inline-script">This should be black</p>
|
||||
<style>
|
||||
p#inline-style { color:rgb(0, 128, 0); }
|
||||
</style>
|
||||
<script>
|
||||
// Use inline script to set a style attribute
|
||||
document.getElementById("inline-script").style.color = "rgb(0, 128, 0)";
|
||||
</script>
|
||||
<img src="file_CSP.sjs?testid=noneExternalImgLoaded&type=img/png" />
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1 @@
|
||||
Content-Security-Policy: default-src * ; style-src 'none' 'unsafe-inline';
|
19
content/base/test/csp/file_CSP_bug909029_star.html
Normal file
19
content/base/test/csp/file_CSP_bug909029_star.html
Normal file
@ -0,0 +1,19 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<link rel='stylesheet' type='text/css'
|
||||
href='file_CSP.sjs?testid=starExternalStylesLoaded&type=text/css' />
|
||||
</head>
|
||||
<body>
|
||||
<p id="inline-style">This should be green</p>
|
||||
<p id="inline-script">This should be black</p>
|
||||
<style>
|
||||
p#inline-style { color:rgb(0, 128, 0); }
|
||||
</style>
|
||||
<script>
|
||||
// Use inline script to set a style attribute
|
||||
document.getElementById("inline-script").style.color = "rgb(0, 128, 0)";
|
||||
</script>
|
||||
<img src="file_CSP.sjs?testid=starExternalImgLoaded&type=img/png" />
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1 @@
|
||||
Content-Security-Policy: default-src *; style-src * 'unsafe-inline';
|
@ -78,6 +78,10 @@ support-files =
|
||||
file_CSP_bug910139.sjs
|
||||
file_CSP_bug910139.xml
|
||||
file_CSP_bug910139.xsl
|
||||
file_CSP_bug909029_star.html
|
||||
file_CSP_bug909029_star.html^headers^
|
||||
file_CSP_bug909029_none.html
|
||||
file_CSP_bug909029_none.html^headers^
|
||||
|
||||
[test_CSP.html]
|
||||
[test_CSP_bug663567.html]
|
||||
@ -94,3 +98,4 @@ support-files =
|
||||
[test_bug836922_npolicies.html]
|
||||
[test_csp_redirects.html]
|
||||
[test_CSP_bug910139.html]
|
||||
[test_CSP_bug909029.html]
|
||||
|
140
content/base/test/csp/test_CSP_bug909029.html
Normal file
140
content/base/test/csp/test_CSP_bug909029.html
Normal file
@ -0,0 +1,140 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Bug 909029 - CSP source-lists ignore some source expressions like 'unsafe-inline' when * or 'none' are used (e.g., style-src, script-src)</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div id=content style="visibility:hidden">
|
||||
<iframe id=testframe1></iframe>
|
||||
<iframe id=testframe2></iframe>
|
||||
</div>
|
||||
<script class="testbody" type="text/javascript">
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
window.tests = {
|
||||
starExternalStylesLoaded: -1,
|
||||
starExternalImgLoaded: -1,
|
||||
noneExternalStylesBlocked: -1,
|
||||
noneExternalImgLoaded: -1,
|
||||
starInlineStyleAllowed: -1,
|
||||
starInlineScriptBlocked: -1,
|
||||
noneInlineStyleAllowed: -1,
|
||||
noneInlineScriptBlocked: -1
|
||||
}
|
||||
|
||||
function examiner() {
|
||||
SpecialPowers.addObserver(this, "csp-on-violate-policy", false);
|
||||
SpecialPowers.addObserver(this, "http-on-modify-request", false);
|
||||
}
|
||||
examiner.prototype = {
|
||||
observe: function(subject, topic, data) {
|
||||
// subject should be an nsURI, and should be either allowed or blocked.
|
||||
if (!SpecialPowers.can_QI(subject))
|
||||
return;
|
||||
|
||||
var testpat = new RegExp("testid=([a-zA-Z]+)");
|
||||
|
||||
if (topic === "http-on-modify-request") {
|
||||
//these things were allowed by CSP
|
||||
var asciiSpec = SpecialPowers.getPrivilegedProps(SpecialPowers.do_QueryInterface(subject, "nsIHttpChannel"), "URI.asciiSpec");
|
||||
if (!testpat.test(asciiSpec))
|
||||
return;
|
||||
var testid = testpat.exec(asciiSpec)[1];
|
||||
window.testResult(testid,
|
||||
/Loaded/.test(testid),
|
||||
"resource loaded");
|
||||
}
|
||||
|
||||
if(topic === "csp-on-violate-policy") {
|
||||
// these were blocked... record that they were blocked
|
||||
// try because the subject could be an nsIURI or an nsISupportsCString
|
||||
try {
|
||||
var asciiSpec = SpecialPowers.getPrivilegedProps(SpecialPowers.do_QueryInterface(subject, "nsIURI"), "asciiSpec");
|
||||
if (!testpat.test(asciiSpec)) return;
|
||||
var testid = testpat.exec(asciiSpec)[1];
|
||||
window.testResult(testid,
|
||||
/Blocked/.test(testid),
|
||||
"resource blocked by CSP");
|
||||
} catch(e) {
|
||||
// if that fails, the subject is probably a string. Strings are only
|
||||
// reported for inline and eval violations. Since we are testing those
|
||||
// via the observed effects of script on CSSOM, we can simply ignore
|
||||
// these subjects.
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// must eventually call this to remove the listener,
|
||||
// or mochitests might get borked.
|
||||
remove: function() {
|
||||
SpecialPowers.removeObserver(this, "csp-on-violate-policy");
|
||||
SpecialPowers.removeObserver(this, "http-on-modify-request");
|
||||
}
|
||||
}
|
||||
|
||||
window.examiner = new examiner();
|
||||
|
||||
window.testResult = function(testname, result, msg) {
|
||||
//dump("in testResult: testname = " + testname + "\n");
|
||||
|
||||
//test already complete.... forget it... remember the first result.
|
||||
if (window.tests[testname] != -1)
|
||||
return;
|
||||
|
||||
window.tests[testname] = result;
|
||||
is(result, true, testname + ' test: ' + msg);
|
||||
|
||||
// if any test is incomplete, keep waiting
|
||||
for (var v in window.tests)
|
||||
if(tests[v] == -1)
|
||||
return;
|
||||
|
||||
// ... otherwise, finish
|
||||
window.examiner.remove();
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
// Helpers for inline script/style checks
|
||||
var black = 'rgb(0, 0, 0)';
|
||||
var green = 'rgb(0, 128, 0)';
|
||||
function getElementColorById(doc, id) {
|
||||
return window.getComputedStyle(doc.contentDocument.getElementById(id)).color;
|
||||
}
|
||||
|
||||
function checkInlineWithStar() {
|
||||
var testframe = document.getElementById('testframe1');
|
||||
window.testResult("starInlineStyleAllowed",
|
||||
getElementColorById(testframe, 'inline-style') === green,
|
||||
"Inline styles should be allowed (style-src 'unsafe-inline' with star)");
|
||||
window.testResult("starInlineScriptBlocked",
|
||||
getElementColorById(testframe, 'inline-script') === black,
|
||||
"Inline scripts should be blocked (style-src 'unsafe-inline' with star)");
|
||||
}
|
||||
|
||||
function checkInlineWithNone() {
|
||||
// If a directive has 'none' in addition to other sources, 'none' is ignored
|
||||
// and the other sources are used. 'none' is only a valid source if it is
|
||||
// used by itself.
|
||||
var testframe = document.getElementById('testframe2');
|
||||
window.testResult("noneInlineStyleAllowed",
|
||||
getElementColorById(testframe, 'inline-style') === green,
|
||||
"Inline styles should be allowed (style-src 'unsafe-inline' with none)");
|
||||
window.testResult("noneInlineScriptBlocked",
|
||||
getElementColorById(testframe, 'inline-script') === black,
|
||||
"Inline scripts should be blocked (style-src 'unsafe-inline' with none)");
|
||||
}
|
||||
|
||||
SpecialPowers.pushPrefEnv(
|
||||
{'set':[["security.csp.speccompliant", true]]},
|
||||
function () {
|
||||
document.getElementById('testframe1').src = 'file_CSP_bug909029_star.html';
|
||||
document.getElementById('testframe1').addEventListener('load', checkInlineWithStar, false);
|
||||
document.getElementById('testframe2').src = 'file_CSP_bug909029_none.html';
|
||||
document.getElementById('testframe2').addEventListener('load', checkInlineWithNone, false);
|
||||
}
|
||||
);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -2,8 +2,6 @@
|
||||
# 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/.
|
||||
|
||||
FORCE_STATIC_LIB = 1
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
INCLUDES += \
|
||||
|
@ -18,3 +18,4 @@ LIBRARY_NAME = 'mediaresourcemanager'
|
||||
|
||||
include('/ipc/chromium/chromium-config.mozbuild')
|
||||
|
||||
FORCE_STATIC_LIB = True
|
||||
|
@ -4,9 +4,7 @@
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
SHORT_LIBNAME = mozsqlt3
|
||||
ifdef MOZ_FOLD_LIBS
|
||||
FORCE_STATIC_LIB = 1
|
||||
else
|
||||
ifndef MOZ_FOLD_LIBS
|
||||
FORCE_SHARED_LIB = 1
|
||||
endif
|
||||
VISIBILITY_FLAGS =
|
||||
|
@ -16,3 +16,5 @@ SOURCES += [
|
||||
'sqlite3.c',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_FOLD_LIBS']:
|
||||
FORCE_STATIC_LIB = True
|
||||
|
@ -717,6 +717,7 @@ _cairo_win32_printing_surface_paint_image_pattern (cairo_win32_surface_t *surf
|
||||
assert (status == CAIRO_STATUS_SUCCESS);
|
||||
|
||||
cairo_matrix_multiply (&m, &m, &surface->gdi_ctm);
|
||||
cairo_matrix_multiply(&m, &m, &surface->ctm);
|
||||
SaveDC (surface->dc);
|
||||
_cairo_matrix_to_win32_xform (&m, &xform);
|
||||
|
||||
|
@ -17,7 +17,6 @@ include $(srcdir)/files.mk
|
||||
# on Windows, we're going to link graphite with gkmedias instead of libxul
|
||||
ifeq (WINNT,$(OS_TARGET))
|
||||
VISIBILITY_FLAGS =
|
||||
FORCE_STATIC_LIB = 1
|
||||
endif
|
||||
|
||||
ifeq (WINNT,$(OS_TARGET))
|
||||
|
@ -6,11 +6,10 @@
|
||||
|
||||
MODULE = 'graphite2'
|
||||
|
||||
if CONFIG['OS_TARGET'] != 'WINNT':
|
||||
LIBXUL_LIBRARY = True
|
||||
if CONFIG['OS_TARGET'] == 'WINNT':
|
||||
FORCE_STATIC_LIB = True
|
||||
else:
|
||||
# FORCE_STATIC_LIB = True
|
||||
pass
|
||||
LIBXUL_LIBRARY = True
|
||||
|
||||
# This should contain all of the _PUBLIC_HEADERS from files.mk
|
||||
EXPORTS.graphite2 += [
|
||||
|
@ -24,11 +24,6 @@
|
||||
# Mozilla author(s): Jonathan Kew
|
||||
#
|
||||
|
||||
|
||||
ifeq ($(OS_ARCH),WINNT)
|
||||
FORCE_STATIC_LIB = 1
|
||||
endif
|
||||
|
||||
LOCAL_INCLUDES += -I$(srcdir)
|
||||
|
||||
|
||||
|
@ -6,11 +6,10 @@
|
||||
|
||||
MODULE = 'harfbuzz'
|
||||
|
||||
if CONFIG['OS_ARCH'] != 'WINNT':
|
||||
LIBXUL_LIBRARY = True
|
||||
if CONFIG['OS_ARCH'] == 'WINNT':
|
||||
FORCE_STATIC_LIB = True
|
||||
else:
|
||||
# FORCE_STATIC_LIB = True
|
||||
pass
|
||||
LIBXUL_LIBRARY = True
|
||||
|
||||
EXPORTS.harfbuzz += [
|
||||
'hb-blob.h',
|
||||
|
@ -27,7 +27,6 @@
|
||||
|
||||
ifeq (WINNT,$(OS_TARGET))
|
||||
VISIBILITY_FLAGS =
|
||||
FORCE_STATIC_LIB = 1
|
||||
endif
|
||||
|
||||
CSRCS = \
|
||||
|
@ -6,11 +6,10 @@
|
||||
|
||||
MODULE = 'ots'
|
||||
|
||||
if CONFIG['OS_TARGET'] != 'WINNT':
|
||||
LIBXUL_LIBRARY = True
|
||||
if CONFIG['OS_TARGET'] == 'WINNT':
|
||||
FORCE_STATIC_LIB = True
|
||||
else:
|
||||
# FORCE_STATIC_LIB = True
|
||||
pass
|
||||
LIBXUL_LIBRARY = True
|
||||
|
||||
EXPORTS += [
|
||||
'../include/opentype-sanitiser.h',
|
||||
|
@ -125,7 +125,7 @@ gfxWindowsSurface::CreateSimilarSurface(gfxContentType aContent,
|
||||
}
|
||||
|
||||
cairo_surface_t *surface;
|
||||
if (GetContentType() == GFX_CONTENT_COLOR_ALPHA) {
|
||||
if (!mForPrinting && GetContentType() == GFX_CONTENT_COLOR_ALPHA) {
|
||||
// When creating a similar surface to a transparent surface, ensure
|
||||
// the new surface uses a DIB. cairo_surface_create_similar won't
|
||||
// use a DIB for a GFX_CONTENT_COLOR surface if this surface doesn't
|
||||
|
@ -10,7 +10,6 @@
|
||||
DIST_INSTALL = 1
|
||||
SDK_LIBRARY = $(LIBRARY)
|
||||
|
||||
FORCE_STATIC_LIB = 1
|
||||
USE_STATIC_LIBS = 1
|
||||
|
||||
LOCAL_INCLUDES += -I$(srcdir)/../src
|
||||
|
@ -13,6 +13,4 @@ MOZILLA_INTERNAL_API = 1
|
||||
LOCAL_INCLUDES += -I$(srcdir)/.. \
|
||||
-I$(srcdir)/../../src
|
||||
|
||||
FORCE_STATIC_LIB = 1
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
@ -14,3 +14,4 @@ LIBRARY_NAME = 'unicharutil_s'
|
||||
|
||||
EXPORT_LIBRARY = True
|
||||
|
||||
FORCE_STATIC_LIB = True
|
||||
|
@ -21,3 +21,5 @@ include('objs.mozbuild')
|
||||
SOURCES += intl_unicharutil_util_cppsrcs
|
||||
|
||||
LIBRARY_NAME = 'unicharutil_external_s'
|
||||
|
||||
FORCE_STATIC_LIB = True
|
||||
|
@ -31,7 +31,6 @@ LIBS = $(NSPR_LIBS)
|
||||
ifdef JS_SHARED_LIBRARY
|
||||
FORCE_SHARED_LIB = 1
|
||||
endif
|
||||
FORCE_STATIC_LIB = 1
|
||||
DIST_INSTALL = 1
|
||||
|
||||
###############################################
|
||||
|
@ -41,12 +41,14 @@ _MOZBUILD_EXTERNAL_VARIABLES := \
|
||||
DIRS \
|
||||
EXTRA_PP_COMPONENTS \
|
||||
EXTRA_PP_JS_MODULES \
|
||||
FORCE_STATIC_LIB \
|
||||
GTEST_CMMSRCS \
|
||||
GTEST_CPPSRCS \
|
||||
GTEST_CSRCS \
|
||||
HOST_CSRCS \
|
||||
HOST_LIBRARY_NAME \
|
||||
IS_COMPONENT \
|
||||
JAVA_JAR_TARGETS \
|
||||
JS_MODULES_PATH \
|
||||
LIBRARY_NAME \
|
||||
LIBXUL_LIBRARY \
|
||||
|
@ -4,7 +4,5 @@
|
||||
# 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/.
|
||||
|
||||
FORCE_STATIC_LIB = 1
|
||||
|
||||
DEFINES += -DANSI_ARROWS -DHAVE_TCGETATTR -DHIDE -DUSE_DIRENT -DSYS_UNIX \
|
||||
-DHAVE_STDLIB -DUNIQUE_HISTORY
|
||||
|
@ -11,3 +11,4 @@ SOURCES += [
|
||||
'sysunix.c',
|
||||
]
|
||||
|
||||
FORCE_STATIC_LIB = True
|
||||
|
@ -2358,8 +2358,13 @@ CodeGenerator::visitCallDirectEval(LCallDirectEval *lir)
|
||||
static const uint32_t EntryTempMask = Registers::TempMask & ~(1 << OsrFrameReg.code());
|
||||
|
||||
bool
|
||||
CodeGenerator::generateArgumentsChecks()
|
||||
CodeGenerator::generateArgumentsChecks(bool bailout)
|
||||
{
|
||||
// This function can be used the normal way to check the argument types,
|
||||
// before entering the function and bailout when arguments don't match.
|
||||
// For debug purpose, this is can also be used to force/check that the
|
||||
// arguments are correct. Upon fail it will hit a breakpoint.
|
||||
|
||||
MIRGraph &mir = gen->graph();
|
||||
MResumePoint *rp = mir.entryResumePoint();
|
||||
|
||||
@ -2389,8 +2394,18 @@ CodeGenerator::generateArgumentsChecks()
|
||||
masm.guardTypeSet(Address(StackPointer, offset), types, temp, &miss);
|
||||
}
|
||||
|
||||
if (miss.used() && !bailoutFrom(&miss, graph.entrySnapshot()))
|
||||
return false;
|
||||
if (miss.used()) {
|
||||
if (bailout) {
|
||||
if (!bailoutFrom(&miss, graph.entrySnapshot()))
|
||||
return false;
|
||||
} else {
|
||||
Label success;
|
||||
masm.jump(&success);
|
||||
masm.bind(&miss);
|
||||
masm.breakpoint();
|
||||
masm.bind(&success);
|
||||
}
|
||||
}
|
||||
|
||||
masm.freeStack(frameSize());
|
||||
|
||||
@ -5679,6 +5694,12 @@ CodeGenerator::generate()
|
||||
masm.bind(&skip);
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
// Assert that the argument types are correct.
|
||||
if (!generateArgumentsChecks(/* bailout = */ false))
|
||||
return false;
|
||||
#endif
|
||||
|
||||
if (!generatePrologue())
|
||||
return false;
|
||||
if (!generateBody())
|
||||
|
@ -43,7 +43,7 @@ class OutOfLineCallPostWriteBarrier;
|
||||
|
||||
class CodeGenerator : public CodeGeneratorSpecific
|
||||
{
|
||||
bool generateArgumentsChecks();
|
||||
bool generateArgumentsChecks(bool bailout = true);
|
||||
bool generateBody();
|
||||
|
||||
public:
|
||||
|
@ -160,6 +160,14 @@ MacroAssembler::guardObjectType(Register obj, const TypeSet *types,
|
||||
}
|
||||
|
||||
if (hasTypeObjects) {
|
||||
// We are possibly going to overwrite the obj register. So already
|
||||
// emit the branch, since branch depends on previous value of obj
|
||||
// register and there is definitely a branch following. So no need
|
||||
// to invert the condition.
|
||||
if (lastBranch.isInitialized())
|
||||
lastBranch.emit(*this);
|
||||
lastBranch = BranchGCPtr();
|
||||
|
||||
// Note: Some platforms give the same register for obj and scratch.
|
||||
// Make sure when writing to scratch, the obj register isn't used anymore!
|
||||
loadPtr(Address(obj, JSObject::offsetOfType()), scratch);
|
||||
|
@ -2857,8 +2857,6 @@ class MToFloat32
|
||||
}
|
||||
|
||||
void computeRange();
|
||||
bool truncate();
|
||||
bool isOperandTruncated(size_t index) const;
|
||||
|
||||
bool canConsumeFloat32() const { return true; }
|
||||
bool canProduceFloat32() const { return true; }
|
||||
|
@ -2095,20 +2095,6 @@ MToDouble::truncate()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
MToFloat32::truncate()
|
||||
{
|
||||
JS_ASSERT(type() == MIRType_Float32);
|
||||
|
||||
// We use the return type to flag that this MToFloat32 sould be replaced by a
|
||||
// MTruncateToInt32 when modifying the graph.
|
||||
setResultType(MIRType_Int32);
|
||||
if (range())
|
||||
range()->wrapAroundToInt32();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
MLoadTypedArrayElementStatic::truncate()
|
||||
{
|
||||
@ -2160,14 +2146,6 @@ MToDouble::isOperandTruncated(size_t index) const
|
||||
return type() == MIRType_Int32;
|
||||
}
|
||||
|
||||
bool
|
||||
MToFloat32::isOperandTruncated(size_t index) const
|
||||
{
|
||||
// The return type is used to flag that we are replacing this Float32 by a
|
||||
// Truncate of its operand if needed.
|
||||
return type() == MIRType_Int32;
|
||||
}
|
||||
|
||||
bool
|
||||
MStoreTypedArrayElement::isOperandTruncated(size_t index) const
|
||||
{
|
||||
|
@ -658,9 +658,9 @@ WorkerThread::handleAsmJSWorkload(WorkerThreadState &state)
|
||||
|
||||
// On failure, signal parent for harvesting in CancelOutstandingJobs().
|
||||
if (!success) {
|
||||
asmData = nullptr;
|
||||
state.noteAsmJSFailure(asmData->func);
|
||||
state.notifyAll(WorkerThreadState::CONSUMER);
|
||||
asmData = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -354,3 +354,5 @@ HOST_SOURCES += [
|
||||
'jskwgen.cpp',
|
||||
'jsoplengen.cpp',
|
||||
]
|
||||
|
||||
FORCE_STATIC_LIB = True
|
||||
|
@ -538,7 +538,7 @@ ArrayBufferObject::prepareForAsmJS(JSContext *cx, Handle<ArrayBufferObject*> buf
|
||||
if (buffer->isAsmJSArrayBuffer())
|
||||
return true;
|
||||
|
||||
if (!buffer->copyData(cx))
|
||||
if (!buffer->ensureNonInline(cx))
|
||||
return false;
|
||||
JS_ASSERT(buffer->hasDynamicElements());
|
||||
|
||||
|
@ -1,4 +1,10 @@
|
||||
function f(stdlib, foreign, buffer) {
|
||||
function f1() { "use asm"; function g() {} return g }
|
||||
if (this.jsFuns) {
|
||||
ok(jsFuns.isAsmJSModule(f1), "f1 is an asm.js module");
|
||||
ok(jsFuns.isAsmJSFunction(f1()), "f1.g is an asm.js function");
|
||||
}
|
||||
|
||||
function f2(stdlib, foreign, buffer) {
|
||||
"use asm";
|
||||
var i32 = new stdlib.Int32Array(buffer);
|
||||
function main(n) {
|
||||
@ -10,17 +16,56 @@ function f(stdlib, foreign, buffer) {
|
||||
}
|
||||
return main;
|
||||
}
|
||||
|
||||
var i32 = new Int32Array(4096/4);
|
||||
for (var i = 0; i < 100; i++)
|
||||
if (this.jsFuns)
|
||||
ok(jsFuns.isAsmJSModule(f2), "f2 is an asm.js module");
|
||||
var i32 = new Int32Array(1024);
|
||||
for (var i = 0; i < i32.length; i++)
|
||||
i32[i] = i;
|
||||
var f2Main = f2(this, null, i32.buffer);
|
||||
if (this.jsFuns)
|
||||
ok(jsFuns.isAsmJSFunction(f2Main), "f2.main is an asm.js function");
|
||||
if (f2Main(4) !== 6)
|
||||
throw "f2Main(4)";
|
||||
if (f2Main(100) !== 4950)
|
||||
throw "f2.main(100)";
|
||||
var sum = (((i32.length - 1) * i32.length) / 2);
|
||||
if (f2Main(i32.length) !== sum)
|
||||
throw "f2.main(" + i32.length + ")";
|
||||
if (f2Main(i32.length + 100) !== sum)
|
||||
throw "f2.main(" + i32.length + ")";
|
||||
|
||||
var fMain = f(this, null, i32.buffer);
|
||||
if (fMain(4) !== 6)
|
||||
throw "f.main(4)";
|
||||
if (fMain(100) !== 4950)
|
||||
throw "f.main(100)";
|
||||
if (fMain(5000) !== 4950)
|
||||
throw "f.main(5000)";
|
||||
function f3(stdlib, foreign, buffer) {
|
||||
"use asm";
|
||||
var done = foreign.done;
|
||||
var i32 = new stdlib.Int32Array(buffer);
|
||||
function main() {
|
||||
var i = 0, sum = 0;
|
||||
while (1) {
|
||||
for (i = 0; (i|0) < 1000; i=(i+1)|0)
|
||||
sum = (sum + i)|0;
|
||||
if (done(sum|0)|0)
|
||||
break;
|
||||
}
|
||||
return sum|0;
|
||||
}
|
||||
return main;
|
||||
}
|
||||
var begin;
|
||||
var lastSum;
|
||||
function done(sum) {
|
||||
if (sum !== ((lastSum + 499500)|0))
|
||||
throw "bad sum: " + sum + ", " + lastSum + ", " + ((lastSum + 499500)|0);
|
||||
lastSum = sum;
|
||||
return (Date.now() - begin) > 3000;
|
||||
}
|
||||
var f3Main = f3(this, {done:done}, i32.buffer);
|
||||
if (this.jsFuns)
|
||||
ok(jsFuns.isAsmJSFunction(f3Main), "f3.main is an asm.js function");
|
||||
|
||||
postMessage("ok");
|
||||
begin = Date.now();
|
||||
lastSum = 0;
|
||||
if (f3Main() !== lastSum)
|
||||
throw "f3.main()";
|
||||
|
||||
if (!this.jsFuns)
|
||||
postMessage("ok");
|
||||
|
@ -10,70 +10,27 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=854209
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=854209">asm.js browser tests</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=854209">asm.js browser tests</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
<pre id="test"></pre>
|
||||
|
||||
var jsFuns = SpecialPowers.Cu.getJSTestingFunctions();
|
||||
<script>
|
||||
var jsFuns = SpecialPowers.Cu.getJSTestingFunctions();
|
||||
ok(jsFuns.isAsmJSCompilationAvailable());
|
||||
</script>
|
||||
|
||||
ok(jsFuns.isAsmJSCompilationAvailable());
|
||||
<script src="http://mochi.test:8888/tests/js/xpconnect/tests/mochitest/file_asmjs.js"></script>
|
||||
|
||||
function f1() { "use asm"; function g() {} return g }
|
||||
ok(jsFuns.isAsmJSModule(f1), "f1 is an asm.js module");
|
||||
ok(jsFuns.isAsmJSFunction(f1()), "f1.g is an asm.js function");
|
||||
<script>
|
||||
var w = new Worker('http://mochi.test:8888/tests/js/xpconnect/tests/mochitest/file_asmjs.js');
|
||||
w.onmessage = function(e) {
|
||||
ok(e.data === "ok", "Worker asm.js tests");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function f2(stdlib, foreign, buffer) {
|
||||
"use asm";
|
||||
var i32 = new stdlib.Int32Array(buffer);
|
||||
function main(n) {
|
||||
n = n|0;
|
||||
var i = 0, sum = 0;
|
||||
for (; (i|0) < (n|0); i=(i+1)|0)
|
||||
sum = (sum + (i32[(i<<2)>>2]|0))|0;
|
||||
return sum|0;
|
||||
}
|
||||
return main;
|
||||
}
|
||||
ok(jsFuns.isAsmJSModule(f2), "f2 is an asm.js module");
|
||||
var i32 = new Int32Array(4096/4);
|
||||
for (var i = 0; i < 100; i++)
|
||||
i32[i] = i;
|
||||
var f2Main = f2(this, null, i32.buffer);
|
||||
ok(jsFuns.isAsmJSFunction(f2Main), "f2.main is an asm.js function");
|
||||
ok(f2Main(4) == 6, "f2.main(4)");
|
||||
ok(f2Main(100) == 4950, "f2.main(100)");
|
||||
ok(f2Main(5000) == 4950, "f2.main(5000)");
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
</script>
|
||||
|
||||
function f3(stdlib, foreign, buffer) {
|
||||
"use asm";
|
||||
var i32 = new stdlib.Int32Array(buffer);
|
||||
function main(n,o) {
|
||||
n = n|0;
|
||||
o = o|0;
|
||||
var i = 0, j = 0, sum = 0;
|
||||
for (i = 0; (i|0) < (n|0); i=(i+1)|0)
|
||||
for (j = 0; (j|0) < (o|0); j=(j+1)|0)
|
||||
sum = (sum + (i32[(j<<2)>>2]|0))|0;
|
||||
return sum|0;
|
||||
}
|
||||
return main;
|
||||
}
|
||||
var f3Main = f3(this, null, i32.buffer);
|
||||
ok(jsFuns.isAsmJSFunction(f3Main), "f3.main is an asm.js function");
|
||||
ok(f3Main(200000, 1000) == ((4950*200000)|0), "f3.main(200000, 1000)");
|
||||
|
||||
var w = new Worker('http://mochi.test:8888/tests/js/xpconnect/tests/mochitest/file_asmjs.js');
|
||||
w.onmessage = function(e) {
|
||||
ok(e.data === "ok", "Worker asm.js tests");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -2,7 +2,6 @@
|
||||
# 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/.
|
||||
|
||||
FORCE_STATIC_LIB= 1
|
||||
ifeq ($(OS_TARGET),WINNT)
|
||||
VISIBILITY_FLAGS =
|
||||
endif
|
||||
|
@ -51,3 +51,4 @@ LIBRARY_NAME = 'cubeb'
|
||||
|
||||
MSVC_ENABLE_PGO = True
|
||||
|
||||
FORCE_STATIC_LIB = True
|
||||
|
@ -16,9 +16,6 @@ ifeq ($(AS),yasm)
|
||||
AS_DASH_C_FLAG=
|
||||
endif
|
||||
|
||||
# need static lib for some of the libimg componentry to link properly
|
||||
FORCE_STATIC_LIB = 1
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
jpeg_nbits_table.h: $(srcdir)/genTables.py
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user