зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to mozilla-inbound
This commit is contained in:
Коммит
ba00ae5790
|
@ -9053,7 +9053,14 @@ XPCOMUtils.defineLazyGetter(Scratchpad, "ScratchpadManager", function() {
|
||||||
|
|
||||||
var StyleEditor = {
|
var StyleEditor = {
|
||||||
prefEnabledName: "devtools.styleeditor.enabled",
|
prefEnabledName: "devtools.styleeditor.enabled",
|
||||||
openChrome: function SE_openChrome()
|
/**
|
||||||
|
* Opens the style editor. If the UI is already open, it will be focused.
|
||||||
|
*
|
||||||
|
* @param {CSSStyleSheet} [aSelectedStyleSheet] default Stylesheet.
|
||||||
|
* @param {Number} [aLine] Line to which the caret should be moved (one-indexed).
|
||||||
|
* @param {Number} [aCol] Column to which the caret should be moved (one-indexed).
|
||||||
|
*/
|
||||||
|
openChrome: function SE_openChrome(aSelectedStyleSheet, aLine, aCol)
|
||||||
{
|
{
|
||||||
const CHROME_URL = "chrome://browser/content/styleeditor.xul";
|
const CHROME_URL = "chrome://browser/content/styleeditor.xul";
|
||||||
const CHROME_WINDOW_TYPE = "Tools:StyleEditor";
|
const CHROME_WINDOW_TYPE = "Tools:StyleEditor";
|
||||||
|
@ -9067,14 +9074,23 @@ var StyleEditor = {
|
||||||
while (enumerator.hasMoreElements()) {
|
while (enumerator.hasMoreElements()) {
|
||||||
var win = enumerator.getNext();
|
var win = enumerator.getNext();
|
||||||
if (win.styleEditorChrome.contentWindowID == contentWindowID) {
|
if (win.styleEditorChrome.contentWindowID == contentWindowID) {
|
||||||
|
if (aSelectedStyleSheet) {
|
||||||
|
win.styleEditorChrome.selectStyleSheet(aSelectedStyleSheet, aLine, aCol);
|
||||||
|
}
|
||||||
win.focus();
|
win.focus();
|
||||||
return win;
|
return win;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let args = {
|
||||||
|
contentWindow: contentWindow,
|
||||||
|
selectedStyleSheet: aSelectedStyleSheet,
|
||||||
|
line: aLine,
|
||||||
|
col: aCol
|
||||||
|
};
|
||||||
|
args.wrappedJSObject = args;
|
||||||
let chromeWindow = Services.ww.openWindow(null, CHROME_URL, "_blank",
|
let chromeWindow = Services.ww.openWindow(null, CHROME_URL, "_blank",
|
||||||
CHROME_WINDOW_FLAGS,
|
CHROME_WINDOW_FLAGS, args);
|
||||||
contentWindow);
|
|
||||||
chromeWindow.focus();
|
chromeWindow.focus();
|
||||||
return chromeWindow;
|
return chromeWindow;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1371,7 +1371,8 @@
|
||||||
|
|
||||||
// pretend the user typed this so it'll be available till
|
// pretend the user typed this so it'll be available till
|
||||||
// the document successfully loads
|
// the document successfully loads
|
||||||
b.userTypedValue = aURI;
|
if (!isBlankPageURL(aURI))
|
||||||
|
b.userTypedValue = aURI;
|
||||||
|
|
||||||
let flags = Ci.nsIWebNavigation.LOAD_FLAGS_NONE;
|
let flags = Ci.nsIWebNavigation.LOAD_FLAGS_NONE;
|
||||||
if (aAllowThirdPartyFixup)
|
if (aAllowThirdPartyFixup)
|
||||||
|
@ -1563,15 +1564,26 @@
|
||||||
<parameter name="aCloseWindowFastpath"/>
|
<parameter name="aCloseWindowFastpath"/>
|
||||||
<body>
|
<body>
|
||||||
<![CDATA[
|
<![CDATA[
|
||||||
if (aTab.closing || this._windowIsClosing)
|
if (aTab.closing ||
|
||||||
|
aTab._pendingPermitUnload ||
|
||||||
|
this._windowIsClosing)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
var browser = this.getBrowserForTab(aTab);
|
var browser = this.getBrowserForTab(aTab);
|
||||||
|
|
||||||
if (!aTabWillBeMoved) {
|
if (!aTabWillBeMoved) {
|
||||||
let ds = browser.docShell;
|
let ds = browser.docShell;
|
||||||
if (ds && ds.contentViewer && !ds.contentViewer.permitUnload())
|
if (ds && ds.contentViewer) {
|
||||||
return false;
|
// We need to block while calling permitUnload() because it
|
||||||
|
// processes the event queue and may lead to another removeTab()
|
||||||
|
// call before permitUnload() even returned.
|
||||||
|
aTab._pendingPermitUnload = true;
|
||||||
|
let permitUnload = ds.contentViewer.permitUnload();
|
||||||
|
delete aTab._pendingPermitUnload;
|
||||||
|
|
||||||
|
if (!permitUnload)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var closeWindow = false;
|
var closeWindow = false;
|
||||||
|
|
|
@ -72,6 +72,7 @@ _BROWSER_TEST_FILES = \
|
||||||
browser_dbg_pause-resume.js \
|
browser_dbg_pause-resume.js \
|
||||||
browser_dbg_update-editor-mode.js \
|
browser_dbg_update-editor-mode.js \
|
||||||
browser_dbg_select-line.js \
|
browser_dbg_select-line.js \
|
||||||
|
browser_dbg_clean-exit.js \
|
||||||
head.js \
|
head.js \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
/*
|
||||||
|
* Any copyright is dedicated to the Public Domain.
|
||||||
|
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Test that closing a tab with the debugger in a paused state exits cleanly.
|
||||||
|
|
||||||
|
var gPane = null;
|
||||||
|
var gTab = null;
|
||||||
|
var gDebuggee = null;
|
||||||
|
var gDebugger = null;
|
||||||
|
|
||||||
|
const DEBUGGER_TAB_URL = "http://example.com/browser/browser/devtools/" +
|
||||||
|
"debugger/test/" +
|
||||||
|
"browser_dbg_debuggerstatement.html";
|
||||||
|
|
||||||
|
function test() {
|
||||||
|
debug_tab_pane(DEBUGGER_TAB_URL, function(aTab, aDebuggee, aPane) {
|
||||||
|
gTab = aTab;
|
||||||
|
gDebuggee = aDebuggee;
|
||||||
|
gPane = aPane;
|
||||||
|
gDebugger = gPane.debuggerWindow;
|
||||||
|
|
||||||
|
testCleanExit();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function testCleanExit() {
|
||||||
|
gPane.activeThread.addOneTimeListener("framesadded", function() {
|
||||||
|
Services.tm.currentThread.dispatch({ run: function() {
|
||||||
|
is(gDebugger.StackFrames.activeThread.paused, true,
|
||||||
|
"Should be paused after the debugger statement.");
|
||||||
|
|
||||||
|
gPane._client.addOneTimeListener("tabDetached", function () {
|
||||||
|
finish();
|
||||||
|
});
|
||||||
|
removeTab(gTab);
|
||||||
|
}}, 0);
|
||||||
|
});
|
||||||
|
|
||||||
|
gTab.linkedBrowser.contentWindow.wrappedJSObject.runDebuggerStatement();
|
||||||
|
}
|
|
@ -763,6 +763,9 @@ InspectorUI.prototype = {
|
||||||
this.boundRuleViewChanged = this.ruleViewChanged.bind(this);
|
this.boundRuleViewChanged = this.ruleViewChanged.bind(this);
|
||||||
this.ruleView.element.addEventListener("CssRuleViewChanged",
|
this.ruleView.element.addEventListener("CssRuleViewChanged",
|
||||||
this.boundRuleViewChanged);
|
this.boundRuleViewChanged);
|
||||||
|
this.cssRuleViewBoundCSSLinkClicked = this.ruleViewCSSLinkClicked.bind(this);
|
||||||
|
this.ruleView.element.addEventListener("CssRuleViewCSSLinkClicked",
|
||||||
|
this.cssRuleViewBoundCSSLinkClicked);
|
||||||
|
|
||||||
doc.documentElement.appendChild(this.ruleView.element);
|
doc.documentElement.appendChild(this.ruleView.element);
|
||||||
this.ruleView.highlight(this.selection);
|
this.ruleView.highlight(this.selection);
|
||||||
|
@ -800,6 +803,30 @@ InspectorUI.prototype = {
|
||||||
this.nodeChanged(this.ruleViewObject);
|
this.nodeChanged(this.ruleViewObject);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When a css link is clicked this method is called in order to either:
|
||||||
|
* 1. Open the link in view source (for element style attributes)
|
||||||
|
* 2. Open the link in the style editor
|
||||||
|
*
|
||||||
|
* @param aEvent The event containing the style rule to act on
|
||||||
|
*/
|
||||||
|
ruleViewCSSLinkClicked: function(aEvent)
|
||||||
|
{
|
||||||
|
if (!this.chromeWin) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let rule = aEvent.detail.rule;
|
||||||
|
let styleSheet = rule.sheet;
|
||||||
|
|
||||||
|
if (styleSheet) {
|
||||||
|
this.chromeWin.StyleEditor.openChrome(styleSheet, rule.ruleLine);
|
||||||
|
} else {
|
||||||
|
let href = rule.elementStyle.element.ownerDocument.location.href;
|
||||||
|
this.chromeWin.openUILinkIn("view-source:" + href, "window");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destroy the rule view.
|
* Destroy the rule view.
|
||||||
*/
|
*/
|
||||||
|
@ -811,6 +838,8 @@ InspectorUI.prototype = {
|
||||||
if (this.ruleView) {
|
if (this.ruleView) {
|
||||||
this.ruleView.element.removeEventListener("CssRuleViewChanged",
|
this.ruleView.element.removeEventListener("CssRuleViewChanged",
|
||||||
this.boundRuleViewChanged);
|
this.boundRuleViewChanged);
|
||||||
|
this.ruleView.element.removeEventListener("CssRuleViewCSSLinkClicked",
|
||||||
|
this.cssRuleViewBoundCSSLinkClicked);
|
||||||
delete boundRuleViewChanged;
|
delete boundRuleViewChanged;
|
||||||
this.ruleView.clear();
|
this.ruleView.clear();
|
||||||
delete this.ruleView;
|
delete this.ruleView;
|
||||||
|
|
|
@ -78,6 +78,9 @@ const ORION_EVENTS = {
|
||||||
Selection: "Selection",
|
Selection: "Selection",
|
||||||
Focus: "Focus",
|
Focus: "Focus",
|
||||||
Blur: "Blur",
|
Blur: "Blur",
|
||||||
|
MouseOver: "MouseOver",
|
||||||
|
MouseOut: "MouseOut",
|
||||||
|
MouseMove: "MouseMove",
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -161,6 +161,30 @@ SourceEditor.EVENTS = {
|
||||||
* The blur event is fired when the editor goes out of focus.
|
* The blur event is fired when the editor goes out of focus.
|
||||||
*/
|
*/
|
||||||
BLUR: "Blur",
|
BLUR: "Blur",
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The MouseMove event is sent when the user moves the mouse over a line
|
||||||
|
* annotation. The event object properties:
|
||||||
|
* - event - the DOM mousemove event object.
|
||||||
|
* - x and y - the mouse coordinates relative to the document being edited.
|
||||||
|
*/
|
||||||
|
MOUSE_MOVE: "MouseMove",
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The MouseOver event is sent when the mouse pointer enters a line
|
||||||
|
* annotation. The event object properties:
|
||||||
|
* - event - the DOM mouseover event object.
|
||||||
|
* - x and y - the mouse coordinates relative to the document being edited.
|
||||||
|
*/
|
||||||
|
MOUSE_OVER: "MouseOver",
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This MouseOut event is sent when the mouse pointer exits a line
|
||||||
|
* annotation. The event object properties:
|
||||||
|
* - event - the DOM mouseout event object.
|
||||||
|
* - x and y - the mouse coordinates relative to the document being edited.
|
||||||
|
*/
|
||||||
|
MOUSE_OUT: "MouseOut",
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -55,6 +55,7 @@ _BROWSER_TEST_FILES = \
|
||||||
browser_bug687160_line_api.js \
|
browser_bug687160_line_api.js \
|
||||||
browser_bug650345_find.js \
|
browser_bug650345_find.js \
|
||||||
browser_bug703692_focus_blur.js \
|
browser_bug703692_focus_blur.js \
|
||||||
|
browser_bug725388_mouse_events.js \
|
||||||
head.js \
|
head.js \
|
||||||
|
|
||||||
libs:: $(_BROWSER_TEST_FILES)
|
libs:: $(_BROWSER_TEST_FILES)
|
||||||
|
|
|
@ -0,0 +1,97 @@
|
||||||
|
/* vim: set ts=2 et sw=2 tw=80: */
|
||||||
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
let tempScope = {};
|
||||||
|
Cu.import("resource:///modules/source-editor.jsm", tempScope);
|
||||||
|
let SourceEditor = tempScope.SourceEditor;
|
||||||
|
|
||||||
|
let testWin;
|
||||||
|
let editor;
|
||||||
|
|
||||||
|
function test()
|
||||||
|
{
|
||||||
|
waitForExplicitFinish();
|
||||||
|
|
||||||
|
const windowUrl = "data:text/xml,<?xml version='1.0'?>" +
|
||||||
|
"<window xmlns='http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul'" +
|
||||||
|
" title='Test for bug 725388' width='600' height='500'><hbox flex='1'/></window>";
|
||||||
|
const windowFeatures = "chrome,titlebar,toolbar,centerscreen,resizable,dialog=no";
|
||||||
|
|
||||||
|
testWin = Services.ww.openWindow(null, windowUrl, "_blank", windowFeatures, null);
|
||||||
|
testWin.addEventListener("load", function onWindowLoad() {
|
||||||
|
testWin.removeEventListener("load", onWindowLoad, false);
|
||||||
|
waitForFocus(initEditor, testWin);
|
||||||
|
}, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
function initEditor()
|
||||||
|
{
|
||||||
|
let hbox = testWin.document.querySelector("hbox");
|
||||||
|
|
||||||
|
editor = new SourceEditor();
|
||||||
|
editor.init(hbox, {}, editorLoaded);
|
||||||
|
}
|
||||||
|
|
||||||
|
function editorLoaded()
|
||||||
|
{
|
||||||
|
let text = "BrowserBug - 725388";
|
||||||
|
editor.setText(text);
|
||||||
|
|
||||||
|
let target = editor.editorElement;
|
||||||
|
let targetWin = target.ownerDocument.defaultView;
|
||||||
|
|
||||||
|
let mMoveHandler = function(aEvent) {
|
||||||
|
editor.removeEventListener(SourceEditor.EVENTS.MOUSE_MOVE, mMoveHandler);
|
||||||
|
|
||||||
|
is(aEvent.event.type, "mousemove", "MouseMove event fired.");
|
||||||
|
|
||||||
|
editor.addEventListener(SourceEditor.EVENTS.MOUSE_OVER, mOverHandler);
|
||||||
|
waitForFocus(function() {
|
||||||
|
EventUtils.synthesizeMouse(target, 10, 10, {type: "mouseover"},
|
||||||
|
targetWin);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
let mOverHandler = function(aEvent) {
|
||||||
|
editor.removeEventListener(SourceEditor.EVENTS.MOUSE_OVER, mOverHandler);
|
||||||
|
|
||||||
|
is(aEvent.event.type, "mouseover", "MouseOver event fired.");
|
||||||
|
|
||||||
|
editor.addEventListener(SourceEditor.EVENTS.MOUSE_OUT, mOutHandler);
|
||||||
|
waitForFocus(function() {
|
||||||
|
EventUtils.synthesizeMouse(target, -10, -10, {type: "mouseout"},
|
||||||
|
targetWin);
|
||||||
|
}, targetWin);
|
||||||
|
};
|
||||||
|
|
||||||
|
let mOutHandler = function(aEvent) {
|
||||||
|
editor.removeEventListener(SourceEditor.EVENTS.MOUSE_OUT, mOutHandler);
|
||||||
|
|
||||||
|
is(aEvent.event.type, "mouseout", "MouseOut event fired.");
|
||||||
|
executeSoon(testEnd);
|
||||||
|
};
|
||||||
|
|
||||||
|
editor.addEventListener(SourceEditor.EVENTS.MOUSE_MOVE, mMoveHandler);
|
||||||
|
|
||||||
|
editor.focus();
|
||||||
|
waitForFocus(function() {
|
||||||
|
EventUtils.synthesizeMouse(target, 1, 1, {type: "mousemove"},
|
||||||
|
targetWin);
|
||||||
|
}, targetWin);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testEnd()
|
||||||
|
{
|
||||||
|
if (editor) {
|
||||||
|
editor.destroy();
|
||||||
|
}
|
||||||
|
if (testWin) {
|
||||||
|
testWin.close();
|
||||||
|
}
|
||||||
|
testWin = editor = null;
|
||||||
|
|
||||||
|
waitForFocus(finish, window);
|
||||||
|
}
|
|
@ -146,7 +146,7 @@ StyleEditor.prototype = {
|
||||||
*/
|
*/
|
||||||
get styleSheet()
|
get styleSheet()
|
||||||
{
|
{
|
||||||
assert(this._styleSheet, "StyleSheet must be loaded first.")
|
assert(this._styleSheet, "StyleSheet must be loaded first.");
|
||||||
return this._styleSheet;
|
return this._styleSheet;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -921,9 +921,11 @@ StyleEditor.prototype = {
|
||||||
aArgs.unshift(this);
|
aArgs.unshift(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// copy the list of listeners to allow adding/removing listeners in handlers
|
||||||
|
let listeners = this._actionListeners.concat();
|
||||||
// trigger all listeners that have this action handler
|
// trigger all listeners that have this action handler
|
||||||
for (let i = 0; i < this._actionListeners.length; ++i) {
|
for (let i = 0; i < listeners.length; ++i) {
|
||||||
let listener = this._actionListeners[i];
|
let listener = listeners[i];
|
||||||
let actionHandler = listener["on" + aName];
|
let actionHandler = listener["on" + aName];
|
||||||
if (actionHandler) {
|
if (actionHandler) {
|
||||||
actionHandler.apply(listener, aArgs);
|
actionHandler.apply(listener, aArgs);
|
||||||
|
|
|
@ -270,9 +270,11 @@ StyleEditorChrome.prototype = {
|
||||||
aArgs.unshift(this);
|
aArgs.unshift(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// trigger all listeners that have this named handler
|
// copy the list of listeners to allow adding/removing listeners in handlers
|
||||||
for (let i = 0; i < this._listeners.length; ++i) {
|
let listeners = this._listeners.concat();
|
||||||
let listener = this._listeners[i];
|
// trigger all listeners that have this named handler.
|
||||||
|
for (let i = 0; i < listeners.length; i++) {
|
||||||
|
let listener = listeners[i];
|
||||||
let handler = listener["on" + aName];
|
let handler = listener["on" + aName];
|
||||||
if (handler) {
|
if (handler) {
|
||||||
handler.apply(listener, aArgs);
|
handler.apply(listener, aArgs);
|
||||||
|
@ -329,10 +331,10 @@ StyleEditorChrome.prototype = {
|
||||||
{
|
{
|
||||||
this._resetChrome();
|
this._resetChrome();
|
||||||
|
|
||||||
this._document.title = _("chromeWindowTitle",
|
|
||||||
this.contentDocument.title || this.contentDocument.location.href);
|
|
||||||
|
|
||||||
let document = this.contentDocument;
|
let document = this.contentDocument;
|
||||||
|
this._document.title = _("chromeWindowTitle",
|
||||||
|
document.title || document.location.href);
|
||||||
|
|
||||||
for (let i = 0; i < document.styleSheets.length; ++i) {
|
for (let i = 0; i < document.styleSheets.length; ++i) {
|
||||||
let styleSheet = document.styleSheets[i];
|
let styleSheet = document.styleSheets[i];
|
||||||
|
|
||||||
|
@ -352,6 +354,79 @@ StyleEditorChrome.prototype = {
|
||||||
}, this);
|
}, this);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* selects a stylesheet and optionally moves the cursor to a selected line
|
||||||
|
*
|
||||||
|
* @param {CSSStyleSheet} [aSheet]
|
||||||
|
* Stylesheet that should be selected. If a stylesheet is not passed
|
||||||
|
* and the editor is not initialized we focus the first stylesheet. If
|
||||||
|
* a stylesheet is not passed and the editor is initialized we ignore
|
||||||
|
* the call.
|
||||||
|
* @param {Number} [aLine]
|
||||||
|
* Line to which the caret should be moved (one-indexed).
|
||||||
|
* @param {Number} [aCol]
|
||||||
|
* Column to which the caret should be moved (one-indexed).
|
||||||
|
*/
|
||||||
|
selectStyleSheet: function SEC_selectSheet(aSheet, aLine, aCol)
|
||||||
|
{
|
||||||
|
let select = function DEC_select(aEditor) {
|
||||||
|
let summary = aSheet ? this.getSummaryElementForEditor(aEditor)
|
||||||
|
: this._view.getSummaryElementByOrdinal(0);
|
||||||
|
let setCaret = false;
|
||||||
|
|
||||||
|
if (aLine || aCol) {
|
||||||
|
aLine = aLine || 1;
|
||||||
|
aCol = aCol || 1;
|
||||||
|
setCaret = true;
|
||||||
|
}
|
||||||
|
if (!aEditor.sourceEditor) {
|
||||||
|
// If a line or column was specified we move the caret appropriately.
|
||||||
|
if (setCaret) {
|
||||||
|
aEditor.addActionListener({
|
||||||
|
onAttach: function SEC_selectSheet_onAttach()
|
||||||
|
{
|
||||||
|
aEditor.removeActionListener(this);
|
||||||
|
aEditor.sourceEditor.setCaretPosition(aLine - 1, aCol - 1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
this._view.activeSummary = summary;
|
||||||
|
} else {
|
||||||
|
this._view.activeSummary = summary;
|
||||||
|
|
||||||
|
// If a line or column was specified we move the caret appropriately.
|
||||||
|
if (setCaret) {
|
||||||
|
aEditor.sourceEditor.setCaretPosition(aLine - 1, aCol - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.bind(this);
|
||||||
|
|
||||||
|
if (!this.editors.length) {
|
||||||
|
// We are in the main initialization phase so we wait for the editor
|
||||||
|
// containing the target stylesheet to be added and select the target
|
||||||
|
// stylesheet, optionally moving the cursor to a selected line.
|
||||||
|
this.addChromeListener({
|
||||||
|
onEditorAdded: function SEC_selectSheet_onEditorAdded(aChrome, aEditor) {
|
||||||
|
if ((!aSheet && aEditor.styleSheetIndex == 0) ||
|
||||||
|
aEditor.styleSheet == aSheet) {
|
||||||
|
aChrome.removeChromeListener(this);
|
||||||
|
select(aEditor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else if (aSheet) {
|
||||||
|
// We are already initialized and a stylesheet has been specified. Here
|
||||||
|
// we iterate through the editors and select the one containing the target
|
||||||
|
// stylesheet, optionally moving the cursor to a selected line.
|
||||||
|
for each (let editor in this.editors) {
|
||||||
|
if (editor.styleSheet == aSheet) {
|
||||||
|
select(editor);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Disable all UI, effectively making editors read-only.
|
* Disable all UI, effectively making editors read-only.
|
||||||
* This is automatically called when no content window is attached.
|
* This is automatically called when no content window is attached.
|
||||||
|
@ -455,9 +530,8 @@ StyleEditorChrome.prototype = {
|
||||||
}
|
}
|
||||||
}, false);
|
}, false);
|
||||||
|
|
||||||
// autofocus the first or new stylesheet
|
// autofocus new stylesheets
|
||||||
if (editor.styleSheetIndex == 0 ||
|
if (editor.hasFlag(StyleEditorFlags.NEW)) {
|
||||||
editor.hasFlag(StyleEditorFlags.NEW)) {
|
|
||||||
this._view.activeSummary = aSummary;
|
this._view.activeSummary = aSummary;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -132,8 +132,10 @@
|
||||||
<xul:script type="application/javascript"><![CDATA[
|
<xul:script type="application/javascript"><![CDATA[
|
||||||
Components.utils.import("resource:///modules/devtools/StyleEditorChrome.jsm");
|
Components.utils.import("resource:///modules/devtools/StyleEditorChrome.jsm");
|
||||||
let chromeRoot = document.getElementById("style-editor-chrome");
|
let chromeRoot = document.getElementById("style-editor-chrome");
|
||||||
let contentWindow = window.arguments[0];
|
let args = window.arguments[0].wrappedJSObject;
|
||||||
|
let contentWindow = args.contentWindow;
|
||||||
let chrome = new StyleEditorChrome(chromeRoot, contentWindow);
|
let chrome = new StyleEditorChrome(chromeRoot, contentWindow);
|
||||||
|
chrome.selectStyleSheet(args.selectedStyleSheet, args.line, args.col);
|
||||||
window.styleEditorChrome = chrome;
|
window.styleEditorChrome = chrome;
|
||||||
]]></xul:script>
|
]]></xul:script>
|
||||||
</xul:window>
|
</xul:window>
|
||||||
|
|
|
@ -51,6 +51,7 @@ _BROWSER_TEST_FILES = \
|
||||||
browser_styleeditor_init.js \
|
browser_styleeditor_init.js \
|
||||||
browser_styleeditor_loading.js \
|
browser_styleeditor_loading.js \
|
||||||
browser_styleeditor_new.js \
|
browser_styleeditor_new.js \
|
||||||
|
browser_styleeditor_passedinsheet.js \
|
||||||
browser_styleeditor_pretty.js \
|
browser_styleeditor_pretty.js \
|
||||||
browser_styleeditor_readonly.js \
|
browser_styleeditor_readonly.js \
|
||||||
browser_styleeditor_reopen.js \
|
browser_styleeditor_reopen.js \
|
||||||
|
|
|
@ -0,0 +1,61 @@
|
||||||
|
/* vim: set ts=2 et sw=2 tw=80: */
|
||||||
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
|
||||||
|
const TESTCASE_URI = TEST_BASE + "simple.html";
|
||||||
|
const LINE = 6;
|
||||||
|
const COL = 2;
|
||||||
|
|
||||||
|
let editor = null;
|
||||||
|
let sheet = null;
|
||||||
|
|
||||||
|
function test()
|
||||||
|
{
|
||||||
|
waitForExplicitFinish();
|
||||||
|
gBrowser.selectedBrowser.addEventListener("load", function () {
|
||||||
|
gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
|
||||||
|
run();
|
||||||
|
}, true);
|
||||||
|
content.location = TESTCASE_URI;
|
||||||
|
}
|
||||||
|
|
||||||
|
function run()
|
||||||
|
{
|
||||||
|
sheet = content.document.styleSheets[1];
|
||||||
|
launchStyleEditorChrome(function attachListeners(aChrome) {
|
||||||
|
aChrome.addChromeListener({
|
||||||
|
onEditorAdded: checkSourceEditor
|
||||||
|
});
|
||||||
|
}, sheet, LINE, COL);
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkSourceEditor(aChrome, aEditor)
|
||||||
|
{
|
||||||
|
if (!aEditor.sourceEditor) {
|
||||||
|
aEditor.addActionListener({
|
||||||
|
onAttach: function (aEditor) {
|
||||||
|
aEditor.removeActionListener(this);
|
||||||
|
validate(aEditor);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
validate(aEditor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function validate(aEditor)
|
||||||
|
{
|
||||||
|
info("validating style editor");
|
||||||
|
let sourceEditor = aEditor.sourceEditor;
|
||||||
|
let caretPosition = sourceEditor.getCaretPosition();
|
||||||
|
is(caretPosition.line, LINE - 1, "caret row is correct"); // index based
|
||||||
|
is(caretPosition.col, COL - 1, "caret column is correct");
|
||||||
|
is(aEditor.styleSheet, sheet, "loaded stylesheet matches document stylesheet");
|
||||||
|
finishUp();
|
||||||
|
}
|
||||||
|
|
||||||
|
function finishUp()
|
||||||
|
{
|
||||||
|
editor = sheet = null;
|
||||||
|
finish();
|
||||||
|
}
|
|
@ -19,9 +19,9 @@ function cleanup()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function launchStyleEditorChrome(aCallback)
|
function launchStyleEditorChrome(aCallback, aSheet, aLine, aCol)
|
||||||
{
|
{
|
||||||
gChromeWindow = StyleEditor.openChrome();
|
gChromeWindow = StyleEditor.openChrome(aSheet, aLine, aCol);
|
||||||
if (gChromeWindow.document.readyState != "complete") {
|
if (gChromeWindow.document.readyState != "complete") {
|
||||||
gChromeWindow.addEventListener("load", function onChromeLoad() {
|
gChromeWindow.addEventListener("load", function onChromeLoad() {
|
||||||
gChromeWindow.removeEventListener("load", onChromeLoad, true);
|
gChromeWindow.removeEventListener("load", onChromeLoad, true);
|
||||||
|
@ -34,12 +34,12 @@ function launchStyleEditorChrome(aCallback)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function addTabAndLaunchStyleEditorChromeWhenLoaded(aCallback)
|
function addTabAndLaunchStyleEditorChromeWhenLoaded(aCallback, aSheet, aLine, aCol)
|
||||||
{
|
{
|
||||||
gBrowser.selectedTab = gBrowser.addTab();
|
gBrowser.selectedTab = gBrowser.addTab();
|
||||||
gBrowser.selectedBrowser.addEventListener("load", function onLoad() {
|
gBrowser.selectedBrowser.addEventListener("load", function onLoad() {
|
||||||
gBrowser.selectedBrowser.removeEventListener("load", onLoad, true);
|
gBrowser.selectedBrowser.removeEventListener("load", onLoad, true);
|
||||||
launchStyleEditorChrome(aCallback);
|
launchStyleEditorChrome(aCallback, aSheet, aLine, aCol);
|
||||||
}, true);
|
}, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -273,6 +273,7 @@ CssHtmlTree.prototype = {
|
||||||
this._matchedProperties = null;
|
this._matchedProperties = null;
|
||||||
|
|
||||||
if (this.htmlComplete) {
|
if (this.htmlComplete) {
|
||||||
|
this.refreshSourceFilter();
|
||||||
this.refreshPanel();
|
this.refreshPanel();
|
||||||
} else {
|
} else {
|
||||||
if (this._refreshProcess) {
|
if (this._refreshProcess) {
|
||||||
|
@ -281,6 +282,9 @@ CssHtmlTree.prototype = {
|
||||||
|
|
||||||
CssHtmlTree.processTemplate(this.templateRoot, this.root, this);
|
CssHtmlTree.processTemplate(this.templateRoot, this.root, this);
|
||||||
|
|
||||||
|
// Refresh source filter ... this must be done after templateRoot has been
|
||||||
|
// processed.
|
||||||
|
this.refreshSourceFilter();
|
||||||
this.numVisibleProperties = 0;
|
this.numVisibleProperties = 0;
|
||||||
let fragment = this.doc.createDocumentFragment();
|
let fragment = this.doc.createDocumentFragment();
|
||||||
this._refreshProcess = new UpdateProcess(this.win, CssHtmlTree.propertyNames, {
|
this._refreshProcess = new UpdateProcess(this.win, CssHtmlTree.propertyNames, {
|
||||||
|
@ -362,21 +366,28 @@ CssHtmlTree.prototype = {
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The change event handler for the onlyUserStyles checkbox. When
|
* The change event handler for the onlyUserStyles checkbox.
|
||||||
* onlyUserStyles.checked is true we do not display properties that have no
|
|
||||||
* matched selectors, and we do not display UA styles. If .checked is false we
|
|
||||||
* do display even properties with no matched selectors, and we include the UA
|
|
||||||
* styles.
|
|
||||||
*
|
*
|
||||||
* @param {Event} aEvent the DOM Event object.
|
* @param {Event} aEvent the DOM Event object.
|
||||||
*/
|
*/
|
||||||
onlyUserStylesChanged: function CssHtmltree_onlyUserStylesChanged(aEvent)
|
onlyUserStylesChanged: function CssHtmltree_onlyUserStylesChanged(aEvent)
|
||||||
|
{
|
||||||
|
this.refreshSourceFilter();
|
||||||
|
this.refreshPanel();
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When onlyUserStyles.checked is true we only display properties that have
|
||||||
|
* matched selectors and have been included by the document or one of the
|
||||||
|
* document's stylesheets. If .checked is false we display all properties
|
||||||
|
* including those that come from UA stylesheets.
|
||||||
|
*/
|
||||||
|
refreshSourceFilter: function CssHtmlTree_setSourceFilter()
|
||||||
{
|
{
|
||||||
this._matchedProperties = null;
|
this._matchedProperties = null;
|
||||||
this.cssLogic.sourceFilter = this.showOnlyUserStyles ?
|
this.cssLogic.sourceFilter = this.showOnlyUserStyles ?
|
||||||
CssLogic.FILTER.ALL :
|
CssLogic.FILTER.ALL :
|
||||||
CssLogic.FILTER.UA;
|
CssLogic.FILTER.UA;
|
||||||
this.refreshPanel();
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -974,4 +985,24 @@ SelectorView.prototype = {
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When a css link is clicked this method is called in order to either:
|
||||||
|
* 1. Open the link in view source (for element style attributes).
|
||||||
|
* 2. Open the link in the style editor.
|
||||||
|
*
|
||||||
|
* @param aEvent The click event
|
||||||
|
*/
|
||||||
|
openStyleEditor: function(aEvent)
|
||||||
|
{
|
||||||
|
if (this.selectorInfo.selector._cssRule._cssSheet) {
|
||||||
|
let styleSheet = this.selectorInfo.selector._cssRule._cssSheet.domSheet;
|
||||||
|
let line = this.selectorInfo.ruleLine;
|
||||||
|
|
||||||
|
this.tree.win.StyleEditor.openChrome(styleSheet, line);
|
||||||
|
} else {
|
||||||
|
let href = this.selectorInfo.sourceElement.ownerDocument.location.href;
|
||||||
|
this.tree.win.openUILinkIn("view-source:" + href, "window");
|
||||||
|
}
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -232,7 +232,7 @@ CssLogic.prototype = {
|
||||||
// Update the CssSheet objects.
|
// Update the CssSheet objects.
|
||||||
this.forEachSheet(function(aSheet) {
|
this.forEachSheet(function(aSheet) {
|
||||||
aSheet._sheetAllowed = -1;
|
aSheet._sheetAllowed = -1;
|
||||||
if (!aSheet.systemSheet && aSheet.sheetAllowed) {
|
if (aSheet.contentSheet && aSheet.sheetAllowed) {
|
||||||
ruleCount += aSheet.ruleCount;
|
ruleCount += aSheet.ruleCount;
|
||||||
}
|
}
|
||||||
}, this);
|
}, this);
|
||||||
|
@ -345,7 +345,7 @@ CssLogic.prototype = {
|
||||||
|
|
||||||
let sheets = [];
|
let sheets = [];
|
||||||
this.forEachSheet(function (aSheet) {
|
this.forEachSheet(function (aSheet) {
|
||||||
if (!aSheet.systemSheet) {
|
if (aSheet.contentSheet) {
|
||||||
sheets.push(aSheet);
|
sheets.push(aSheet);
|
||||||
}
|
}
|
||||||
}, this);
|
}, this);
|
||||||
|
@ -395,7 +395,7 @@ CssLogic.prototype = {
|
||||||
}
|
}
|
||||||
|
|
||||||
sheet = new CssSheet(this, aDomSheet, aIndex);
|
sheet = new CssSheet(this, aDomSheet, aIndex);
|
||||||
if (sheet.sheetAllowed && !sheet.systemSheet) {
|
if (sheet.sheetAllowed && sheet.contentSheet) {
|
||||||
this._ruleCount += sheet.ruleCount;
|
this._ruleCount += sheet.ruleCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -569,7 +569,7 @@ CssLogic.prototype = {
|
||||||
|
|
||||||
this.forEachSheet(function (aSheet) {
|
this.forEachSheet(function (aSheet) {
|
||||||
// We do not show unmatched selectors from system stylesheets
|
// We do not show unmatched selectors from system stylesheets
|
||||||
if (aSheet.systemSheet || aSheet.disabled || !aSheet.mediaMatches) {
|
if (!aSheet.contentSheet || aSheet.disabled || !aSheet.mediaMatches) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -664,7 +664,7 @@ CssLogic.prototype = {
|
||||||
sheet._passId = this._passId;
|
sheet._passId = this._passId;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (filter !== CssLogic.FILTER.UA && sheet.systemSheet) {
|
if (filter === CssLogic.FILTER.ALL && !sheet.contentSheet) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -710,7 +710,7 @@ CssLogic.prototype = {
|
||||||
let result = {};
|
let result = {};
|
||||||
|
|
||||||
this.forSomeSheets(function (aSheet) {
|
this.forSomeSheets(function (aSheet) {
|
||||||
if (aSheet.systemSheet || aSheet.disabled || !aSheet.mediaMatches) {
|
if (!aSheet.contentSheet || aSheet.disabled || !aSheet.mediaMatches) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -865,29 +865,23 @@ XPCOMUtils.defineLazyGetter(CssLogic, "_strings", function() Services.strings
|
||||||
.createBundle("chrome://browser/locale/devtools/styleinspector.properties"));
|
.createBundle("chrome://browser/locale/devtools/styleinspector.properties"));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Is the given property sheet a system (user agent) stylesheet?
|
* Is the given property sheet a content stylesheet?
|
||||||
*
|
*
|
||||||
* @param {CSSStyleSheet} aSheet a stylesheet
|
* @param {CSSStyleSheet} aSheet a stylesheet
|
||||||
* @return {boolean} true if the given stylesheet is a system stylesheet or
|
* @return {boolean} true if the given stylesheet is a content stylesheet,
|
||||||
* false otherwise.
|
* false otherwise.
|
||||||
*/
|
*/
|
||||||
CssLogic.isSystemStyleSheet = function CssLogic_isSystemStyleSheet(aSheet)
|
CssLogic.isContentStylesheet = function CssLogic_isContentStylesheet(aSheet)
|
||||||
{
|
{
|
||||||
if (!aSheet) {
|
// All sheets with owner nodes have been included by content.
|
||||||
|
if (aSheet.ownerNode) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
let url = aSheet.href;
|
// If the sheet has a CSSImportRule we need to check the parent stylesheet.
|
||||||
|
if (aSheet.ownerRule instanceof Ci.nsIDOMCSSImportRule) {
|
||||||
if (!url) return false;
|
return CssLogic.isContentStylesheet(aSheet.parentStyleSheet);
|
||||||
if (url.length === 0) return true;
|
}
|
||||||
|
|
||||||
// Check for http[s]
|
|
||||||
if (url[0] === 'h') return false;
|
|
||||||
if (url.substr(0, 9) === "resource:") return true;
|
|
||||||
if (url.substr(0, 7) === "chrome:") return true;
|
|
||||||
if (url === "XPCSafeJSObjectWrapper.cpp") return true;
|
|
||||||
if (url.substr(0, 6) === "about:") return true;
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
@ -942,7 +936,7 @@ function CssSheet(aCssLogic, aDomSheet, aIndex)
|
||||||
{
|
{
|
||||||
this._cssLogic = aCssLogic;
|
this._cssLogic = aCssLogic;
|
||||||
this.domSheet = aDomSheet;
|
this.domSheet = aDomSheet;
|
||||||
this.index = this.systemSheet ? -100 * aIndex : aIndex;
|
this.index = this.contentSheet ? aIndex : -100 * aIndex;
|
||||||
|
|
||||||
// Cache of the sheets href. Cached by the getter.
|
// Cache of the sheets href. Cached by the getter.
|
||||||
this._href = null;
|
this._href = null;
|
||||||
|
@ -960,21 +954,21 @@ function CssSheet(aCssLogic, aDomSheet, aIndex)
|
||||||
|
|
||||||
CssSheet.prototype = {
|
CssSheet.prototype = {
|
||||||
_passId: null,
|
_passId: null,
|
||||||
_systemSheet: null,
|
_contentSheet: null,
|
||||||
_mediaMatches: null,
|
_mediaMatches: null,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tells if the stylesheet is provided by the browser or not.
|
* Tells if the stylesheet is provided by the browser or not.
|
||||||
*
|
*
|
||||||
* @return {boolean} true if this is a browser-provided stylesheet, or false
|
* @return {boolean} false if this is a browser-provided stylesheet, or true
|
||||||
* otherwise.
|
* otherwise.
|
||||||
*/
|
*/
|
||||||
get systemSheet()
|
get contentSheet()
|
||||||
{
|
{
|
||||||
if (this._systemSheet === null) {
|
if (this._contentSheet === null) {
|
||||||
this._systemSheet = CssLogic.isSystemStyleSheet(this.domSheet);
|
this._contentSheet = CssLogic.isContentStylesheet(this.domSheet);
|
||||||
}
|
}
|
||||||
return this._systemSheet;
|
return this._contentSheet;
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1048,7 +1042,7 @@ CssSheet.prototype = {
|
||||||
this._sheetAllowed = true;
|
this._sheetAllowed = true;
|
||||||
|
|
||||||
let filter = this._cssLogic.sourceFilter;
|
let filter = this._cssLogic.sourceFilter;
|
||||||
if (filter === CssLogic.FILTER.ALL && this.systemSheet) {
|
if (filter === CssLogic.FILTER.ALL && !this.contentSheet) {
|
||||||
this._sheetAllowed = false;
|
this._sheetAllowed = false;
|
||||||
}
|
}
|
||||||
if (filter !== CssLogic.FILTER.ALL && filter !== CssLogic.FILTER.UA) {
|
if (filter !== CssLogic.FILTER.ALL && filter !== CssLogic.FILTER.UA) {
|
||||||
|
@ -1202,13 +1196,13 @@ function CssRule(aCssSheet, aDomRule, aElement)
|
||||||
this.line = this._cssSheet._cssLogic.domUtils.getRuleLine(this._domRule);
|
this.line = this._cssSheet._cssLogic.domUtils.getRuleLine(this._domRule);
|
||||||
this.source = this._cssSheet.shortSource + ":" + this.line;
|
this.source = this._cssSheet.shortSource + ":" + this.line;
|
||||||
this.href = this._cssSheet.href;
|
this.href = this._cssSheet.href;
|
||||||
this.systemRule = this._cssSheet.systemSheet;
|
this.contentRule = this._cssSheet.contentSheet;
|
||||||
} else if (aElement) {
|
} else if (aElement) {
|
||||||
this._selectors = [ new CssSelector(this, "@element.style") ];
|
this._selectors = [ new CssSelector(this, "@element.style") ];
|
||||||
this.line = -1;
|
this.line = -1;
|
||||||
this.source = CssLogic.l10n("rule.sourceElement");
|
this.source = CssLogic.l10n("rule.sourceElement");
|
||||||
this.href = "#";
|
this.href = "#";
|
||||||
this.systemRule = false;
|
this.contentRule = true;
|
||||||
this.sourceElement = aElement;
|
this.sourceElement = aElement;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1396,12 +1390,12 @@ CssSelector.prototype = {
|
||||||
/**
|
/**
|
||||||
* Check if the selector comes from a browser-provided stylesheet.
|
* Check if the selector comes from a browser-provided stylesheet.
|
||||||
*
|
*
|
||||||
* @return {boolean} true if the selector comes from a browser-provided
|
* @return {boolean} true if the selector comes from a content-provided
|
||||||
* stylesheet, or false otherwise.
|
* stylesheet, or false otherwise.
|
||||||
*/
|
*/
|
||||||
get systemRule()
|
get contentRule()
|
||||||
{
|
{
|
||||||
return this._cssRule.systemRule;
|
return this._cssRule.contentRule;
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1794,12 +1788,12 @@ function CssSelectorInfo(aSelector, aProperty, aValue, aStatus)
|
||||||
4 important
|
4 important
|
||||||
5 inline important
|
5 inline important
|
||||||
*/
|
*/
|
||||||
let scorePrefix = this.systemRule ? 0 : 2;
|
let scorePrefix = this.contentRule ? 2 : 0;
|
||||||
if (this.elementStyle) {
|
if (this.elementStyle) {
|
||||||
scorePrefix++;
|
scorePrefix++;
|
||||||
}
|
}
|
||||||
if (this.important) {
|
if (this.important) {
|
||||||
scorePrefix += this.systemRule ? 1 : 2;
|
scorePrefix += this.contentRule ? 2 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.specificityScore = "" + scorePrefix + this.specificity.ids +
|
this.specificityScore = "" + scorePrefix + this.specificity.ids +
|
||||||
|
@ -1902,9 +1896,9 @@ CssSelectorInfo.prototype = {
|
||||||
* @return {boolean} true if the selector comes from a browser-provided
|
* @return {boolean} true if the selector comes from a browser-provided
|
||||||
* stylesheet, or false otherwise.
|
* stylesheet, or false otherwise.
|
||||||
*/
|
*/
|
||||||
get systemRule()
|
get contentRule()
|
||||||
{
|
{
|
||||||
return this.selector.systemRule;
|
return this.selector.contentRule;
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1916,8 +1910,8 @@ CssSelectorInfo.prototype = {
|
||||||
*/
|
*/
|
||||||
compareTo: function CssSelectorInfo_compareTo(aThat)
|
compareTo: function CssSelectorInfo_compareTo(aThat)
|
||||||
{
|
{
|
||||||
if (this.systemRule && !aThat.systemRule) return 1;
|
if (!this.contentRule && aThat.contentRule) return 1;
|
||||||
if (!this.systemRule && aThat.systemRule) return -1;
|
if (this.contentRule && !aThat.contentRule) return -1;
|
||||||
|
|
||||||
if (this.elementStyle && !aThat.elementStyle) {
|
if (this.elementStyle && !aThat.elementStyle) {
|
||||||
if (!this.important && aThat.important) return 1;
|
if (!this.important && aThat.important) return 1;
|
||||||
|
|
|
@ -38,7 +38,7 @@
|
||||||
*
|
*
|
||||||
* ***** END LICENSE BLOCK ***** */
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
"use strict"
|
"use strict";
|
||||||
|
|
||||||
const Cc = Components.classes;
|
const Cc = Components.classes;
|
||||||
const Ci = Components.interfaces;
|
const Ci = Components.interfaces;
|
||||||
|
@ -181,8 +181,8 @@ ElementStyle.prototype = {
|
||||||
let domRule = domRules.GetElementAt(i);
|
let domRule = domRules.GetElementAt(i);
|
||||||
|
|
||||||
// XXX: Optionally provide access to system sheets.
|
// XXX: Optionally provide access to system sheets.
|
||||||
let systemSheet = CssLogic.isSystemStyleSheet(domRule.parentStyleSheet);
|
let contentSheet = CssLogic.isContentStylesheet(domRule.parentStyleSheet);
|
||||||
if (systemSheet) {
|
if (!contentSheet) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -324,7 +324,7 @@ ElementStyle.prototype = {
|
||||||
aProp.overridden = overridden;
|
aProp.overridden = overridden;
|
||||||
return dirty;
|
return dirty;
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A single style rule or declaration.
|
* A single style rule or declaration.
|
||||||
|
@ -358,11 +358,9 @@ Rule.prototype = {
|
||||||
if (this._title) {
|
if (this._title) {
|
||||||
return this._title;
|
return this._title;
|
||||||
}
|
}
|
||||||
let sheet = this.domRule ? this.domRule.parentStyleSheet : null;
|
this._title = CssLogic.shortSource(this.sheet);
|
||||||
this._title = CssLogic.shortSource(sheet);
|
|
||||||
if (this.domRule) {
|
if (this.domRule) {
|
||||||
let line = this.elementStyle.domUtils.getRuleLine(this.domRule);
|
this._title += ":" + this.ruleLine;
|
||||||
this._title += ":" + line;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.inherited) {
|
if (this.inherited) {
|
||||||
|
@ -378,6 +376,26 @@ Rule.prototype = {
|
||||||
return this._title;
|
return this._title;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The rule's stylesheet.
|
||||||
|
*/
|
||||||
|
get sheet()
|
||||||
|
{
|
||||||
|
return this.domRule ? this.domRule.parentStyleSheet : null;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The rule's line within a stylesheet
|
||||||
|
*/
|
||||||
|
get ruleLine()
|
||||||
|
{
|
||||||
|
if (!this.sheet) {
|
||||||
|
// No stylesheet, no ruleLine
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return this.elementStyle.domUtils.getRuleLine(this.domRule);
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new TextProperty to include in the rule.
|
* Create a new TextProperty to include in the rule.
|
||||||
*
|
*
|
||||||
|
@ -530,7 +548,7 @@ Rule.prototype = {
|
||||||
this.textProps.push(textProp);
|
this.textProps.push(textProp);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A single property in a rule's cssText.
|
* A single property in a rule's cssText.
|
||||||
|
@ -618,7 +636,7 @@ TextProperty.prototype = {
|
||||||
{
|
{
|
||||||
this.rule.removeProperty(this);
|
this.rule.removeProperty(this);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -643,7 +661,7 @@ TextProperty.prototype = {
|
||||||
* apply to a given element. After construction, the 'element'
|
* apply to a given element. After construction, the 'element'
|
||||||
* property will be available with the user interface.
|
* property will be available with the user interface.
|
||||||
*
|
*
|
||||||
* @param Document aDocument
|
* @param Document aDoc
|
||||||
* The document that will contain the rule view.
|
* The document that will contain the rule view.
|
||||||
* @param object aStore
|
* @param object aStore
|
||||||
* The CSS rule view can use this object to store metadata
|
* The CSS rule view can use this object to store metadata
|
||||||
|
@ -655,7 +673,6 @@ function CssRuleView(aDoc, aStore)
|
||||||
{
|
{
|
||||||
this.doc = aDoc;
|
this.doc = aDoc;
|
||||||
this.store = aStore;
|
this.store = aStore;
|
||||||
|
|
||||||
this.element = this.doc.createElementNS(XUL_NS, "vbox");
|
this.element = this.doc.createElementNS(XUL_NS, "vbox");
|
||||||
this.element.setAttribute("tabindex", "0");
|
this.element.setAttribute("tabindex", "0");
|
||||||
this.element.classList.add("ruleview");
|
this.element.classList.add("ruleview");
|
||||||
|
@ -768,6 +785,14 @@ RuleEditor.prototype = {
|
||||||
class: "ruleview-rule-source",
|
class: "ruleview-rule-source",
|
||||||
textContent: this.rule.title
|
textContent: this.rule.title
|
||||||
});
|
});
|
||||||
|
source.addEventListener("click", function() {
|
||||||
|
let rule = this.rule;
|
||||||
|
let evt = this.doc.createEvent("CustomEvent");
|
||||||
|
evt.initCustomEvent("CssRuleViewCSSLinkClicked", true, false, {
|
||||||
|
rule: rule,
|
||||||
|
});
|
||||||
|
this.element.dispatchEvent(evt);
|
||||||
|
}.bind(this));
|
||||||
|
|
||||||
let code = createChild(this.element, "div", {
|
let code = createChild(this.element, "div", {
|
||||||
class: "ruleview-code"
|
class: "ruleview-code"
|
||||||
|
@ -1094,8 +1119,6 @@ TextPropertyEditor.prototype = {
|
||||||
_parseValue: function TextPropertyEditor_parseValue(aValue)
|
_parseValue: function TextPropertyEditor_parseValue(aValue)
|
||||||
{
|
{
|
||||||
let pieces = aValue.split("!", 2);
|
let pieces = aValue.split("!", 2);
|
||||||
let value = pieces[0];
|
|
||||||
let priority = pieces.length > 1 ? pieces[1] : "";
|
|
||||||
return {
|
return {
|
||||||
value: pieces[0].trim(),
|
value: pieces[0].trim(),
|
||||||
priority: (pieces.length > 1 ? pieces[1].trim() : "")
|
priority: (pieces.length > 1 ? pieces[1].trim() : "")
|
||||||
|
|
|
@ -114,7 +114,7 @@ To visually debug the templates without running firefox, alter the display:none
|
||||||
${selector.humanReadableText(__element)}
|
${selector.humanReadableText(__element)}
|
||||||
</td>
|
</td>
|
||||||
<td class="rule-link">
|
<td class="rule-link">
|
||||||
<a target="_blank" href="view-source:${selector.selectorInfo.href}" class="link"
|
<a target="_blank" onclick="${selector.openStyleEditor}" class="link"
|
||||||
title="${selector.selectorInfo.href}">${selector.selectorInfo.source}</a>
|
title="${selector.selectorInfo.href}">${selector.selectorInfo.source}</a>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
|
@ -59,11 +59,19 @@ _BROWSER_TEST_FILES = \
|
||||||
browser_ruleview_manipulation.js \
|
browser_ruleview_manipulation.js \
|
||||||
browser_ruleview_override.js \
|
browser_ruleview_override.js \
|
||||||
browser_ruleview_ui.js \
|
browser_ruleview_ui.js \
|
||||||
|
browser_bug705707_is_content_stylesheet.js \
|
||||||
head.js \
|
head.js \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
_BROWSER_TEST_PAGES = \
|
_BROWSER_TEST_PAGES = \
|
||||||
browser_bug683672.html \
|
browser_bug683672.html \
|
||||||
|
browser_bug705707_is_content_stylesheet.html \
|
||||||
|
browser_bug705707_is_content_stylesheet_imported.css \
|
||||||
|
browser_bug705707_is_content_stylesheet_imported2.css \
|
||||||
|
browser_bug705707_is_content_stylesheet_linked.css \
|
||||||
|
browser_bug705707_is_content_stylesheet_script.css \
|
||||||
|
browser_bug705707_is_content_stylesheet.xul \
|
||||||
|
browser_bug705707_is_content_stylesheet_xul.css \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
libs:: $(_BROWSER_TEST_FILES)
|
libs:: $(_BROWSER_TEST_FILES)
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>test</title>
|
||||||
|
|
||||||
|
<link href="./browser_bug705707_is_content_stylesheet_linked.css" rel="stylesheet" type="text/css">
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// Load script.css
|
||||||
|
function loadCSS() {
|
||||||
|
var link = document.createElement('link');
|
||||||
|
link.rel = 'stylesheet';
|
||||||
|
link.type = 'text/css';
|
||||||
|
link.href = "./browser_bug705707_is_content_stylesheet_script.css";
|
||||||
|
document.getElementsByTagName('head')[0].appendChild(link);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
table {
|
||||||
|
border: 1px solid #000;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body onload="loadCSS();">
|
||||||
|
<table id="target">
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<h3>Simple test</h3>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,100 @@
|
||||||
|
/* vim: set ts=2 et sw=2 tw=80: */
|
||||||
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
|
||||||
|
// Tests that the correct stylesheets origins are identified in HTML & XUL
|
||||||
|
// stylesheets
|
||||||
|
|
||||||
|
let doc;
|
||||||
|
|
||||||
|
const TEST_URI = "http://example.com/browser/browser/devtools/styleinspector/" +
|
||||||
|
"test/browser_bug705707_is_content_stylesheet.html";
|
||||||
|
const TEST_URI2 = "http://example.com/browser/browser/devtools/styleinspector/" +
|
||||||
|
"test/browser_bug705707_is_content_stylesheet.xul";
|
||||||
|
const XUL_URI = Cc["@mozilla.org/network/io-service;1"]
|
||||||
|
.getService(Ci.nsIIOService)
|
||||||
|
.newURI(TEST_URI2, null, null);
|
||||||
|
|
||||||
|
let tempScope = {};
|
||||||
|
Cu.import("resource:///modules/devtools/CssLogic.jsm", tempScope);
|
||||||
|
let CssLogic = tempScope.CssLogic;
|
||||||
|
|
||||||
|
function test()
|
||||||
|
{
|
||||||
|
waitForExplicitFinish();
|
||||||
|
addTab(TEST_URI);
|
||||||
|
browser.addEventListener("load", htmlLoaded, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
function htmlLoaded()
|
||||||
|
{
|
||||||
|
browser.removeEventListener("load", htmlLoaded, true);
|
||||||
|
doc = content.document;
|
||||||
|
testFromHTML()
|
||||||
|
}
|
||||||
|
|
||||||
|
function testFromHTML()
|
||||||
|
{
|
||||||
|
let target = doc.querySelector("#target");
|
||||||
|
|
||||||
|
executeSoon(function() {
|
||||||
|
checkSheets(target);
|
||||||
|
gBrowser.removeCurrentTab();
|
||||||
|
openXUL();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function openXUL()
|
||||||
|
{
|
||||||
|
Cc["@mozilla.org/permissionmanager;1"].getService(Ci.nsIPermissionManager)
|
||||||
|
.add(XUL_URI, 'allowXULXBL', Ci.nsIPermissionManager.ALLOW_ACTION);
|
||||||
|
addTab(TEST_URI2);
|
||||||
|
browser.addEventListener("load", xulLoaded, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
function xulLoaded()
|
||||||
|
{
|
||||||
|
browser.removeEventListener("load", xulLoaded, true);
|
||||||
|
doc = content.document;
|
||||||
|
testFromXUL()
|
||||||
|
}
|
||||||
|
|
||||||
|
function testFromXUL()
|
||||||
|
{
|
||||||
|
let target = doc.querySelector("#target");
|
||||||
|
|
||||||
|
executeSoon(function() {
|
||||||
|
checkSheets(target);
|
||||||
|
finishUp();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkSheets(aTarget)
|
||||||
|
{
|
||||||
|
let domUtils = Cc["@mozilla.org/inspector/dom-utils;1"]
|
||||||
|
.getService(Ci.inIDOMUtils);
|
||||||
|
let domRules = domUtils.getCSSStyleRules(aTarget);
|
||||||
|
|
||||||
|
for (let i = 0, n = domRules.Count(); i < n; i++) {
|
||||||
|
let domRule = domRules.GetElementAt(i);
|
||||||
|
let sheet = domRule.parentStyleSheet;
|
||||||
|
let isContentSheet = CssLogic.isContentStylesheet(sheet);
|
||||||
|
|
||||||
|
if (!sheet.href ||
|
||||||
|
/browser_bug705707_is_content_stylesheet_/.test(sheet.href)) {
|
||||||
|
ok(isContentSheet, sheet.href + " identified as content stylesheet");
|
||||||
|
} else {
|
||||||
|
ok(!isContentSheet, sheet.href + " identified as non-content stylesheet");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function finishUp()
|
||||||
|
{
|
||||||
|
info("finishing up");
|
||||||
|
Cc["@mozilla.org/permissionmanager;1"].getService(Ci.nsIPermissionManager)
|
||||||
|
.add(XUL_URI, 'allowXULXBL', Ci.nsIPermissionManager.DENY_ACTION);
|
||||||
|
doc = null;
|
||||||
|
gBrowser.removeCurrentTab();
|
||||||
|
finish();
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<?xml-stylesheet href="chrome://global/skin/xul.css" type="text/css"?>
|
||||||
|
<?xml-stylesheet href="./browser_bug705707_is_content_stylesheet_xul.css"
|
||||||
|
type="text/css"?>
|
||||||
|
<!DOCTYPE window>
|
||||||
|
<window id="testwindow" xmlns:html="http://www.w3.org/1999/xhtml"
|
||||||
|
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||||
|
<label id="target" value="Simple XUL document" />
|
||||||
|
</window>
|
|
@ -0,0 +1,5 @@
|
||||||
|
@import url("./browser_bug705707_is_content_stylesheet_imported2.css");
|
||||||
|
|
||||||
|
#target {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
#target {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
table {
|
||||||
|
border-collapse: collapse;
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
@import url("./browser_bug705707_is_content_stylesheet_imported.css");
|
||||||
|
|
||||||
|
table {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
#target {
|
||||||
|
font-size: 200px;
|
||||||
|
}
|
|
@ -126,6 +126,40 @@ gcli.addCommand({
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 'edit' command
|
||||||
|
*/
|
||||||
|
gcli.addCommand({
|
||||||
|
name: "edit",
|
||||||
|
description: gcli.lookup("editDesc"),
|
||||||
|
manual: gcli.lookup("editManual"),
|
||||||
|
params: [
|
||||||
|
{
|
||||||
|
name: 'resource',
|
||||||
|
type: {
|
||||||
|
name: 'resource',
|
||||||
|
include: 'text/css'
|
||||||
|
},
|
||||||
|
description: gcli.lookup("editResourceDesc")
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "line",
|
||||||
|
defaultValue: 1,
|
||||||
|
type: {
|
||||||
|
name: "number",
|
||||||
|
min: 1,
|
||||||
|
step: 10
|
||||||
|
},
|
||||||
|
description: gcli.lookup("editLineToJumpToDesc")
|
||||||
|
}
|
||||||
|
],
|
||||||
|
exec: function(args, context) {
|
||||||
|
let hud = HUDService.getHudReferenceById(context.environment.hudId);
|
||||||
|
let StyleEditor = hud.gcliterm.document.defaultView.StyleEditor;
|
||||||
|
StyleEditor.openChrome(args.resource.element, args.line);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
let breakpoints = [];
|
let breakpoints = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -129,3 +129,23 @@ breakdelRemoved=Breakpoint removed
|
||||||
# 'console close' command. This string is designed to be shown in a menu
|
# 'console close' command. This string is designed to be shown in a menu
|
||||||
# alongside the command name, which is why it should be as short as possible.
|
# alongside the command name, which is why it should be as short as possible.
|
||||||
consolecloseDesc=Close the console
|
consolecloseDesc=Close the console
|
||||||
|
|
||||||
|
# LOCALIZATION NOTE (editDesc) A very short description of the 'edit'
|
||||||
|
# command. See editManual for a fuller description of what it does. This
|
||||||
|
# string is designed to be shown in a menu alongside the command name, which
|
||||||
|
# is why it should be as short as possible.
|
||||||
|
editDesc=Tweak a page resource
|
||||||
|
|
||||||
|
# LOCALIZATION NOTE (editManual) A fuller description of the 'edit' command,
|
||||||
|
# displayed when the user asks for help on what it does.
|
||||||
|
editManual=Edit one of the resources that is part of this page (or maybe any generic web resource?)
|
||||||
|
|
||||||
|
# LOCALIZATION NOTE (editResourceDesc) A very short string to describe the
|
||||||
|
# 'resource' parameter to the 'edit' command, which is displayed in a dialog
|
||||||
|
# when the user is using this command.
|
||||||
|
editResourceDesc=URL to edit
|
||||||
|
|
||||||
|
# LOCALIZATION NOTE (editLineToJumpToDesc) A very short string to describe the
|
||||||
|
# 'line' parameter to the 'edit' command, which is displayed in a dialog
|
||||||
|
# when the user is using this command.
|
||||||
|
editLineToJumpToDesc=Line to jump to
|
||||||
|
|
|
@ -68,6 +68,9 @@
|
||||||
.helplink:visited {
|
.helplink:visited {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
.link:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
.helplink {
|
.helplink {
|
||||||
display: block;
|
display: block;
|
||||||
|
@ -135,6 +138,7 @@
|
||||||
.rule-link {
|
.rule-link {
|
||||||
text-align: end;
|
text-align: end;
|
||||||
-moz-padding-start: 10px;
|
-moz-padding-start: 10px;
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This rule is necessary because Templater.jsm breaks LTR TDs in RTL docs */
|
/* This rule is necessary because Templater.jsm breaks LTR TDs in RTL docs */
|
||||||
|
@ -200,7 +204,13 @@
|
||||||
|
|
||||||
.ruleview-rule-source {
|
.ruleview-rule-source {
|
||||||
background-color: -moz-dialog;
|
background-color: -moz-dialog;
|
||||||
|
color: #0091ff;
|
||||||
padding: 2px 5px;
|
padding: 2px 5px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ruleview-rule-source:hover {
|
||||||
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ruleview-code {
|
.ruleview-code {
|
||||||
|
|
|
@ -68,6 +68,9 @@
|
||||||
.helplink:visited {
|
.helplink:visited {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
.link:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
.helplink {
|
.helplink {
|
||||||
display: block;
|
display: block;
|
||||||
|
@ -137,6 +140,7 @@
|
||||||
.rule-link {
|
.rule-link {
|
||||||
text-align: end;
|
text-align: end;
|
||||||
-moz-padding-start: 10px;
|
-moz-padding-start: 10px;
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This rule is necessary because Templater.jsm breaks LTR TDs in RTL docs */
|
/* This rule is necessary because Templater.jsm breaks LTR TDs in RTL docs */
|
||||||
|
@ -202,7 +206,13 @@
|
||||||
|
|
||||||
.ruleview-rule-source {
|
.ruleview-rule-source {
|
||||||
background-color: -moz-dialog;
|
background-color: -moz-dialog;
|
||||||
|
color: #0091ff;
|
||||||
padding: 2px 5px;
|
padding: 2px 5px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ruleview-rule-source:hover {
|
||||||
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ruleview-code {
|
.ruleview-code {
|
||||||
|
|
|
@ -67,6 +67,9 @@
|
||||||
.helplink:visited {
|
.helplink:visited {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
.link:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
.helplink {
|
.helplink {
|
||||||
display: block;
|
display: block;
|
||||||
|
@ -135,6 +138,7 @@
|
||||||
.rule-link {
|
.rule-link {
|
||||||
text-align: end;
|
text-align: end;
|
||||||
-moz-padding-start: 10px;
|
-moz-padding-start: 10px;
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This rule is necessary because Templater.jsm breaks LTR TDs in RTL docs */
|
/* This rule is necessary because Templater.jsm breaks LTR TDs in RTL docs */
|
||||||
|
@ -200,7 +204,13 @@
|
||||||
|
|
||||||
.ruleview-rule-source {
|
.ruleview-rule-source {
|
||||||
background-color: -moz-dialog;
|
background-color: -moz-dialog;
|
||||||
|
color: #0091ff;
|
||||||
padding: 2px 5px;
|
padding: 2px 5px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ruleview-rule-source:hover {
|
||||||
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ruleview-code {
|
.ruleview-code {
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
|
#include "android/log.h"
|
||||||
#include "cutils/properties.h"
|
#include "cutils/properties.h"
|
||||||
|
|
||||||
#include "base/basictypes.h"
|
#include "base/basictypes.h"
|
||||||
|
@ -12,6 +13,7 @@
|
||||||
#include "nsStreamUtils.h"
|
#include "nsStreamUtils.h"
|
||||||
#include "nsThreadUtils.h"
|
#include "nsThreadUtils.h"
|
||||||
#include "nsRawStructs.h"
|
#include "nsRawStructs.h"
|
||||||
|
#include "prinit.h"
|
||||||
|
|
||||||
#define USE_GS2_LIBCAMERA
|
#define USE_GS2_LIBCAMERA
|
||||||
#define CameraHardwareInterface CameraHardwareInterface_SGS2
|
#define CameraHardwareInterface CameraHardwareInterface_SGS2
|
||||||
|
@ -48,11 +50,11 @@ using namespace mozilla;
|
||||||
|
|
||||||
class CameraHardwareInterface {
|
class CameraHardwareInterface {
|
||||||
public:
|
public:
|
||||||
typedef enum {
|
enum Type {
|
||||||
CAMERA_SGS2,
|
CAMERA_SGS2,
|
||||||
CAMERA_MAGURO,
|
CAMERA_MAGURO,
|
||||||
CAMERA_DEFAULT
|
CAMERA_DEFAULT
|
||||||
} Type;
|
};
|
||||||
|
|
||||||
static Type getType() {
|
static Type getType() {
|
||||||
char propValue[PROPERTY_VALUE_MAX];
|
char propValue[PROPERTY_VALUE_MAX];
|
||||||
|
@ -60,7 +62,7 @@ class CameraHardwareInterface {
|
||||||
if (!strcmp(propValue, "GT-I9100"))
|
if (!strcmp(propValue, "GT-I9100"))
|
||||||
return CAMERA_SGS2;
|
return CAMERA_SGS2;
|
||||||
|
|
||||||
if (!strcmp(propValue, "MSM7627A_SKU1") || !strcmp(propValue, "MSM7627A_SKU3"))
|
if (!strcmp(propValue, "msm7627a_sku1") || !strcmp(propValue, "MSM7627A_SKU3"))
|
||||||
return CAMERA_MAGURO;
|
return CAMERA_MAGURO;
|
||||||
|
|
||||||
printf_stderr("CameraHardwareInterface : unsupported camera for device %s\n", propValue);
|
printf_stderr("CameraHardwareInterface : unsupported camera for device %s\n", propValue);
|
||||||
|
@ -89,30 +91,25 @@ class CameraHardwareInterface {
|
||||||
CameraHardwareInterface(PRUint32 aCamera = 0) { };
|
CameraHardwareInterface(PRUint32 aCamera = 0) { };
|
||||||
};
|
};
|
||||||
|
|
||||||
class DlopenWrapper {
|
// Intentionally not trying to dlclose() this handle. That's playing
|
||||||
public:
|
// Russian roulette with security bugs.
|
||||||
DlopenWrapper() : mHandle(nsnull) { };
|
static void* sCameraLib;
|
||||||
|
static PRCallOnceType sInitCameraLib;
|
||||||
|
|
||||||
DlopenWrapper(const char* aLibrary) : mHandle(nsnull) {
|
static PRStatus
|
||||||
mHandle = dlopen(aLibrary, RTLD_LAZY);
|
InitCameraLib()
|
||||||
};
|
{
|
||||||
|
sCameraLib = dlopen("/system/lib/libcamera.so", RTLD_LAZY);
|
||||||
|
// We might fail to open the camera lib. That's OK.
|
||||||
|
return PR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
~DlopenWrapper() {
|
static void*
|
||||||
if (mHandle)
|
GetCameraLibHandle()
|
||||||
dlclose(mHandle);
|
{
|
||||||
};
|
PR_CallOnce(&sInitCameraLib, InitCameraLib);
|
||||||
|
return sCameraLib;
|
||||||
bool opened() {
|
}
|
||||||
return mHandle != nsnull;
|
|
||||||
};
|
|
||||||
|
|
||||||
void* dlsym(const char* aFunction) {
|
|
||||||
return ::dlsym(mHandle, aFunction);
|
|
||||||
};
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void* mHandle;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<class T> class CameraImpl : public CameraHardwareInterface {
|
template<class T> class CameraImpl : public CameraHardwareInterface {
|
||||||
public:
|
public:
|
||||||
|
@ -121,14 +118,13 @@ template<class T> class CameraImpl : public CameraHardwareInterface {
|
||||||
typedef sp<T> (*HAL_openCameraHardware_MAGURO)(int, int);
|
typedef sp<T> (*HAL_openCameraHardware_MAGURO)(int, int);
|
||||||
|
|
||||||
CameraImpl(PRUint32 aCamera = 0) : mOk(false), mCamera(nsnull) {
|
CameraImpl(PRUint32 aCamera = 0) : mOk(false), mCamera(nsnull) {
|
||||||
DlopenWrapper wrapper("/system/lib/libcamera.so");
|
void* cameraLib = GetCameraLibHandle();
|
||||||
|
if (!cameraLib) {
|
||||||
if (!wrapper.opened())
|
printf_stderr("CameraImpl: Failed to dlopen() camera library.");
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
mOk = true;
|
void *hal = dlsym(cameraLib, "HAL_openCameraHardware");
|
||||||
|
|
||||||
void *hal = wrapper.dlsym("HAL_openCameraHardware");
|
|
||||||
HAL_openCameraHardware_DEFAULT funct0;
|
HAL_openCameraHardware_DEFAULT funct0;
|
||||||
HAL_openCameraHardware_SGS2 funct1;
|
HAL_openCameraHardware_SGS2 funct1;
|
||||||
HAL_openCameraHardware_MAGURO funct2;
|
HAL_openCameraHardware_MAGURO funct2;
|
||||||
|
@ -146,6 +142,11 @@ template<class T> class CameraImpl : public CameraHardwareInterface {
|
||||||
mCamera = funct0(aCamera);
|
mCamera = funct0(aCamera);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mOk = mCamera != nsnull;
|
||||||
|
if (!mOk) {
|
||||||
|
printf_stderr("CameraImpl: HAL_openCameraHardware() returned NULL (no camera interface).");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ok() {
|
bool ok() {
|
||||||
|
@ -251,12 +252,11 @@ GonkCameraInputStream::DataCallback(int32_t aMsgType, const sp<IMemory>& aDataPt
|
||||||
PRUint32
|
PRUint32
|
||||||
GonkCameraInputStream::getNumberOfCameras() {
|
GonkCameraInputStream::getNumberOfCameras() {
|
||||||
typedef int (*HAL_getNumberOfCamerasFunct)(void);
|
typedef int (*HAL_getNumberOfCamerasFunct)(void);
|
||||||
DlopenWrapper wrapper("/system/lib/libcamera.so");
|
void* cameraLib = GetCameraLibHandle();
|
||||||
|
if (!cameraLib)
|
||||||
if (!wrapper.opened())
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
void *hal = wrapper.dlsym("HAL_getNumberOfCameras");
|
void *hal = dlsym(cameraLib, "HAL_getNumberOfCameras");
|
||||||
if (nsnull == hal)
|
if (nsnull == hal)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|
|
@ -120,6 +120,10 @@ ThreadActor.prototype = {
|
||||||
},
|
},
|
||||||
|
|
||||||
disconnect: function TA_disconnect() {
|
disconnect: function TA_disconnect() {
|
||||||
|
if (this._state == "paused") {
|
||||||
|
this.onResume();
|
||||||
|
}
|
||||||
|
|
||||||
this._state = "exited";
|
this._state = "exited";
|
||||||
if (this.dbg) {
|
if (this.dbg) {
|
||||||
this.dbg.enabled = false;
|
this.dbg.enabled = false;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче