Merge mozilla-central to mozilla-inbound

This commit is contained in:
Ed Morley 2012-09-27 14:06:04 +01:00
commit 5925d611df
16 changed files with 602 additions and 125 deletions

View File

@ -1014,6 +1014,7 @@ pref("devtools.inspector.htmlHeight", 112);
pref("devtools.inspector.htmlPanelOpen", false);
pref("devtools.inspector.sidebarOpen", false);
pref("devtools.inspector.activeSidebar", "ruleview");
pref("devtools.inspector.markupPreview", true);
// Enable the Layout View
pref("devtools.layoutview.enabled", true);

View File

@ -86,7 +86,9 @@ var tabPreviews = {
this._pendingUpdate = true;
setTimeout(function (self, aTab) {
self._pendingUpdate = false;
if (aTab.parentNode && !aTab.hasAttribute("busy"))
if (aTab.parentNode &&
!aTab.hasAttribute("busy") &&
!aTab.hasAttribute("pending"))
self.capture(aTab, true);
}, 2000, this, this._selectedTab);
}

View File

@ -10,8 +10,6 @@ const TAB_STATE_RESTORING = 2;
function test() {
/** Test for Bug 586068 - Cascade page loads when restoring **/
waitForExplicitFinish();
// Too many uncaught exceptions, see bug 789003.
ignoreAllUncaughtExceptions();
// This test does a lot of window opening / closing and waiting for loads.
// In order to prevent timeouts, we'll extend the default that mochitest uses.
requestLongerTimeout(4);

View File

@ -93,7 +93,7 @@ function GroupItem(listOfEls, options) {
// ___ Titlebar
var html =
"<div class='title-container'>" +
"<input class='name' placeholder='" + this.defaultName + "'/>" +
"<input class='name' />" +
"<div class='title-shield' />" +
"</div>";
@ -112,7 +112,7 @@ function GroupItem(listOfEls, options) {
// ___ Title
this.$titleContainer = iQ('.title-container', this.$titlebar);
this.$title = iQ('.name', this.$titlebar);
this.$title = iQ('.name', this.$titlebar).attr('placeholder', this.defaultName);
this.$titleShield = iQ('.title-shield', this.$titlebar);
this.setTitle(options.title);

View File

@ -146,9 +146,11 @@ gcli.addCommand({
let trans = Cc["@mozilla.org/widget/transferable;1"]
.createInstance(Ci.nsITransferable);
if ("init" in trans) {
trans.init(null);
}
let loadContext = document.defaultView
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsILoadContext);
trans.init(loadContext);
trans.addDataFlavor(channel.contentType);
trans.setTransferData(channel.contentType, wrapped, -1);
@ -214,7 +216,8 @@ gcli.addCommand({
let source = ioService.newURI(data, "UTF8", null);
persist.saveURI(source, null, null, null, null, file);
div.textContent = gcli.lookup("screenshotSavedToFile") + " " + filename;
div.textContent = gcli.lookup("screenshotSavedToFile") + " \"" + filename +
"\"";
div.addEventListener("click", function openFile() {
div.removeEventListener("click", openFile);
file.reveal();
@ -224,6 +227,7 @@ gcli.addCommand({
let previewHeight = parseInt(256*height/width);
image.setAttribute("style",
"width:256px; height:" + previewHeight + "px;" +
"max-height: 256px;" +
"background-image: url('" + data + "');" +
"background-size: 256px " + previewHeight + "px;" +
"margin: 4px; display: block");

View File

@ -10,6 +10,8 @@ let tempScope = {};
Cu.import("resource://gre/modules/FileUtils.jsm", tempScope);
let FileUtils = tempScope.FileUtils;
let pb = Cc["@mozilla.org/privatebrowsing;1"]
.getService(Ci.nsIPrivateBrowsingService);
function test() {
DeveloperToolbarTest.test(TEST_URI, [ testInput, testCapture ]);
}
@ -79,31 +81,19 @@ function testCapture() {
}
}
function clearClipboard() {
let clipid = Ci.nsIClipboard;
let clip = Cc["@mozilla.org/widget/clipboard;1"].getService(clipid);
clip.emptyClipboard(clipid.kGlobalClipboard);
}
function checkClipboard() {
try {
let clipid = Ci.nsIClipboard;
let clip = Cc["@mozilla.org/widget/clipboard;1"].getService(clipid);
let trans = Cc["@mozilla.org/widget/transferable;1"]
.createInstance(Ci.nsITransferable);
if ("init" in trans) {
trans.init(null);
}
let io = Cc["@mozilla.org/network/io-service;1"]
.getService(Ci.nsIIOService);
let contentType = io.newChannel("", null, null).contentType;
trans.addDataFlavor(contentType);
trans.init(null);
trans.addDataFlavor("image/png");
clip.getData(trans, clipid.kGlobalClipboard);
let str = new Object();
let strLength = new Object();
trans.getTransferData(contentType, str, strLength);
if (str && strLength > 0) {
clip.emptyClipboard(clipid.kGlobalClipboard);
trans.getTransferData("image/png", str, strLength);
if (str.value && strLength.value > 0) {
return true;
}
}
@ -111,6 +101,41 @@ function testCapture() {
return false;
}
let PBEntered = DeveloperToolbarTest.checkCalled(function() {
Services.obs.removeObserver(PBEntered,
"private-browsing-transition-complete",
false);
Services.obs.addObserver(PBLeft, "last-pb-context-exited", false);
DeveloperToolbarTest.exec({
typed: "screenshot --clipboard",
args: {
delay: 0,
filename: " ",
fullpage: false,
clipboard: true,
node: null,
chrome: false,
},
outputMatch: new RegExp("^Copied to clipboard.$"),
});
ok(checkClipboard(), "Screenshot present in clipboard in private browsing");
pb.privateBrowsingEnabled = false;
});
let PBLeft = DeveloperToolbarTest.checkCalled(function() {
Services.obs.removeObserver(PBLeft, "last-pb-context-exited", false);
executeSoon(function() {
ok(!checkClipboard(), "Screenshot taken in private browsing mode is not" +
" present outside of it in the clipboard");
Services.prefs.clearUserPref("browser.privatebrowsing.keep_current_session");
pb = null;
});
});
let path = FileUtils.getFile("TmpD", ["TestScreenshotFile.png"]).path;
DeveloperToolbarTest.exec({
@ -126,23 +151,29 @@ function testCapture() {
outputMatch: new RegExp("^Saved to "),
});
ok(checkTemporaryFile, "Screenshot got created");
Services.obs.addObserver(PBEntered, "private-browsing-transition-complete",
false);
clearClipboard();
executeSoon(function() {
ok(checkTemporaryFile(), "Screenshot got created");
DeveloperToolbarTest.exec({
typed: "screenshot --fullpage --clipboard",
args: {
delay: 0,
filename: " ",
fullpage: true,
clipboard: true,
node: null,
chrome: false,
},
outputMatch: new RegExp("^Copied to clipboard.$"),
DeveloperToolbarTest.exec({
typed: "screenshot --fullpage --clipboard",
args: {
delay: 0,
filename: " ",
fullpage: true,
clipboard: true,
node: null,
chrome: false,
},
outputMatch: new RegExp("^Copied to clipboard.$"),
});
ok(checkClipboard(), "Screenshot got created and copied");
Services.prefs.setBoolPref("browser.privatebrowsing.keep_current_session", true);
pb.privateBrowsingEnabled = true;
});
ok(checkClipboard, "Screenshot got created and copied");
}

View File

@ -11,12 +11,15 @@ const Ci = Components.interfaces;
// Page size for pageup/pagedown
const PAGE_SIZE = 10;
const PREVIEW_AREA = 700;
var EXPORTED_SYMBOLS = ["MarkupView"];
Cu.import("resource:///modules/devtools/LayoutHelpers.jsm");
Cu.import("resource:///modules/devtools/CssRuleView.jsm");
Cu.import("resource:///modules/devtools/Templater.jsm");
Cu.import("resource:///modules/devtools/Undo.jsm")
Cu.import("resource:///modules/devtools/Undo.jsm");
Cu.import("resource://gre/modules/Services.jsm");
/**
* Vocabulary for the purposes of this file:
@ -59,6 +62,8 @@ function MarkupView(aInspector, aFrame)
this._boundFocus = this._onFocus.bind(this);
this._frame.addEventListener("focus", this._boundFocus, false);
this._initPreview();
}
MarkupView.prototype = {
@ -473,9 +478,15 @@ MarkupView.prototype = {
this.undo.destroy();
delete this.undo;
this._frame.addEventListener("focus", this._boundFocus, false);
this._frame.removeEventListener("focus", this._boundFocus, false);
delete this._boundFocus;
this._frame.contentWindow.removeEventListener("scroll", this._boundUpdatePreview, true);
this._frame.contentWindow.removeEventListener("resize", this._boundUpdatePreview, true);
this._frame.contentWindow.removeEventListener("overflow", this._boundResizePreview, true);
this._frame.contentWindow.removeEventListener("underflow", this._boundResizePreview, true);
delete this._boundUpdatePreview;
this._frame.removeEventListener("keydown", this._boundKeyDown, true);
delete this._boundKeyDown;
@ -487,7 +498,85 @@ MarkupView.prototype = {
delete this._containers;
this._observer.disconnect();
delete this._observer;
}
},
/**
* Initialize the preview panel.
*/
_initPreview: function MT_initPreview()
{
if (!Services.prefs.getBoolPref("devtools.inspector.markupPreview")) {
return;
}
this._previewBar = this.doc.querySelector("#previewbar");
this._preview = this.doc.querySelector("#preview");
this._viewbox = this.doc.querySelector("#viewbox");
this._previewBar.classList.remove("disabled");
this._previewWidth = this._preview.getBoundingClientRect().width;
this._boundResizePreview = this._resizePreview.bind(this);
this._frame.contentWindow.addEventListener("resize", this._boundResizePreview, true);
this._frame.contentWindow.addEventListener("overflow", this._boundResizePreview, true);
this._frame.contentWindow.addEventListener("underflow", this._boundResizePreview, true);
this._boundUpdatePreview = this._updatePreview.bind(this);
this._frame.contentWindow.addEventListener("scroll", this._boundUpdatePreview, true);
this._updatePreview();
},
/**
* Move the preview viewbox.
*/
_updatePreview: function MT_updatePreview()
{
let win = this._frame.contentWindow;
if (win.scrollMaxY == 0) {
this._previewBar.classList.add("disabled");
return;
}
this._previewBar.classList.remove("disabled");
let ratio = this._previewWidth / PREVIEW_AREA;
let width = ratio * win.innerWidth;
let height = ratio * (win.scrollMaxY + win.innerHeight);
let scrollTo
if (height >= win.innerHeight) {
scrollTo = -(height - win.innerHeight) * (win.scrollY / win.scrollMaxY);
this._previewBar.setAttribute("style", "height:" + height + "px;transform:translateY(" + scrollTo + "px)");
} else {
this._previewBar.setAttribute("style", "height:100%");
}
let bgSize = ~~width + "px " + ~~height + "px";
this._preview.setAttribute("style", "background-size:" + bgSize);
let height = ~~(win.innerHeight * ratio) + "px";
let top = ~~(win.scrollY * ratio) + "px";
this._viewbox.setAttribute("style", "height:" + height + ";transform: translateY(" + top + ")");
},
/**
* Hide the preview while resizing, to avoid slowness.
*/
_resizePreview: function MT_resizePreview()
{
let win = this._frame.contentWindow;
this._previewBar.classList.add("hide");
win.clearTimeout(this._resizePreviewTimeout);
win.setTimeout(function() {
this._updatePreview();
this._previewBar.classList.remove("hide");
}.bind(this), 1000);
},
};

View File

@ -19,3 +19,45 @@ ul.children:not([expanded]) {
width: 1em;
height: 1ex;
}
#root {
margin-right: 80px;
}
/* Preview */
#previewbar {
position: fixed;
top: 0;
right: 0;
width: 90px;
background: black;
border-left: 1px solid #333;
border-bottom: 1px solid #333;
overflow: hidden;
}
#preview {
position: absolute;
top: 0;
right: 5px;
width: 80px;
height: 100%;
background-image: -moz-element(#root);
background-repeat: no-repeat;
}
#previewbar.hide,
#previewbar.disabled {
display: none;
}
#viewbox {
position: absolute;
top: 0;
right: 5px;
width: 80px;
border: 1px dashed #888;
background: rgba(205,205,255,0.2);
outline: 1px solid transparent;
}

View File

@ -13,8 +13,8 @@
<body role="application">
<div id="root"></div>
<div id="templates" style="display:none">
<ul>
<li id="template-container" save="${elt}" class="container"><span save="${expander}" class="expander"></span><span save="${codeBox}" class="codebox"><ul save="${children}" class="children"></ul></span></li>
<ul>
<li id="template-container" save="${elt}" class="container"><span save="${expander}" class="expander"></span><span save="${codeBox}" class="codebox"><ul save="${children}" class="children"></ul></span></li>
</ul>
<span id="template-element" save="${elt}" class="editor"><span>&lt;</span><span save="${tag}" class="tagname"></span><span save="${attrList}"></span><span save="${newAttr}" class="newattr" tabindex="0"></span>&gt;</span>
@ -31,5 +31,9 @@
<span id="template-elementClose" save="${closeElt}">&lt;/<span save="${closeTag}" class="tagname"></span>&gt;</span>
</div>
<div id="previewbar" class="disabled">
<div id="preview"/>
<div id="viewbox"/>
</div>
</body>
</html>

View File

@ -105,29 +105,30 @@ function ResponsiveUI(aWindow, aTab)
}
}
this.customPreset = {key: "custom", custom: true};
if (Array.isArray(presets)) {
this.presets = [{key: "custom", custom: true}].concat(presets)
this.presets = [this.customPreset].concat(presets);
} else {
Cu.reportError("Presets value (devtools.responsiveUI.presets) is malformated.");
this.presets = [{key: "custom", custom: true}];
this.presets = [this.customPreset];
}
try {
let width = Services.prefs.getIntPref("devtools.responsiveUI.customWidth");
let height = Services.prefs.getIntPref("devtools.responsiveUI.customHeight");
this.presets[0].width = Math.min(MAX_WIDTH, width);
this.presets[0].height = Math.min(MAX_HEIGHT, height);
this.customPreset.width = Math.min(MAX_WIDTH, width);
this.customPreset.height = Math.min(MAX_HEIGHT, height);
let key = Services.prefs.getCharPref("devtools.responsiveUI.currentPreset");
let idx = this.getPresetIdx(key);
this.currentPreset = (idx == -1 ? 0 : idx);
this.currentPresetKey = Services.prefs.getCharPref("devtools.responsiveUI.currentPreset");
} catch(e) {
// Default size. The first preset (custom) is the one that will be used.
let bbox = this.stack.getBoundingClientRect();
this.presets[0].width = bbox.width - 40; // horizontal padding of the container
this.presets[0].height = bbox.height - 80; // vertical padding + toolbar height
this.currentPreset = 0; // Custom
this.customPreset.width = bbox.width - 40; // horizontal padding of the container
this.customPreset.height = bbox.height - 80; // vertical padding + toolbar height
this.currentPresetKey = this.customPreset.key;
}
this.container.setAttribute("responsivemode", "true");
@ -135,6 +136,8 @@ function ResponsiveUI(aWindow, aTab)
// Let's bind some callbacks.
this.bound_presetSelected = this.presetSelected.bind(this);
this.bound_addPreset = this.addPreset.bind(this);
this.bound_removePreset = this.removePreset.bind(this);
this.bound_rotate = this.rotate.bind(this);
this.bound_startResizing = this.startResizing.bind(this);
this.bound_stopResizing = this.stopResizing.bind(this);
@ -189,14 +192,14 @@ ResponsiveUI.prototype = {
if (this.isResizing)
this.stopResizing();
this.saveCurrentPreset();
// Remove listeners.
this.mainWindow.document.removeEventListener("keypress", this.bound_onKeypress, false);
this.menulist.removeEventListener("select", this.bound_presetSelected, true);
this.tab.removeEventListener("TabClose", this);
this.tabContainer.removeEventListener("TabSelect", this);
this.rotatebutton.removeEventListener("command", this.bound_rotate, true);
this.addbutton.removeEventListener("command", this.bound_addPreset, true);
this.removebutton.removeEventListener("command", this.bound_removePreset, true);
// Removed elements.
this.container.removeChild(this.toolbar);
@ -210,21 +213,6 @@ ResponsiveUI.prototype = {
delete this.tab.__responsiveUI;
},
/**
* Retrieve a preset from its key.
*
* @param aKey preset's key.
* @returns the index of the preset, -1 if not found.
*/
getPresetIdx: function RUI_getPresetIdx(aKey) {
for (let i = 0; i < this.presets.length; i++) {
if (this.presets[i].key == aKey) {
return i;
}
}
return -1;
},
/**
* Handle keypressed.
*
@ -304,10 +292,24 @@ ResponsiveUI.prototype = {
this.menulist.addEventListener("select", this.bound_presetSelected, true);
this.menuitems = new Map();
let menupopup = this.chromeDoc.createElement("menupopup");
this.registerPresets(menupopup);
this.menulist.appendChild(menupopup);
this.addbutton = this.chromeDoc.createElement("menuitem");
this.addbutton.setAttribute("label", this.strings.GetStringFromName("responsiveUI.addPreset"));
this.addbutton.addEventListener("command", this.bound_addPreset, true);
this.removebutton = this.chromeDoc.createElement("menuitem");
this.removebutton.setAttribute("label", this.strings.GetStringFromName("responsiveUI.removePreset"));
this.removebutton.addEventListener("command", this.bound_removePreset, true);
menupopup.appendChild(this.chromeDoc.createElement("menuseparator"));
menupopup.appendChild(this.addbutton);
menupopup.appendChild(this.removebutton);
this.rotatebutton = this.chromeDoc.createElement("toolbarbutton");
this.rotatebutton.setAttribute("tabindex", "0");
this.rotatebutton.setAttribute("label", this.strings.GetStringFromName("responsiveUI.rotate"));
@ -344,11 +346,20 @@ ResponsiveUI.prototype = {
let fragment = this.chromeDoc.createDocumentFragment();
let doc = this.chromeDoc;
for (let i = 0; i < this.presets.length; i++) {
for (let preset of this.presets) {
let menuitem = doc.createElement("menuitem");
if (i == this.currentPreset)
menuitem.setAttribute("ispreset", true);
this.menuitems.set(menuitem, preset);
if (preset.key === this.currentPresetKey) {
menuitem.setAttribute("selected", "true");
this.setMenuLabel(menuitem, this.presets[i]);
this.selectedItem = menuitem;
}
if (preset.custom)
this.customMenuitem = menuitem;
this.setMenuLabel(menuitem, preset);
fragment.appendChild(menuitem);
}
aParent.appendChild(fragment);
@ -365,6 +376,9 @@ ResponsiveUI.prototype = {
if (aPreset.custom) {
let str = this.strings.formatStringFromName("responsiveUI.customResolution", [size], 1);
aMenuitem.setAttribute("label", str);
} else if (aPreset.name != null && aPreset.name !== "") {
let str = this.strings.formatStringFromName("responsiveUI.namedResolution", [size, aPreset.name], 2);
aMenuitem.setAttribute("label", str);
} else {
aMenuitem.setAttribute("label", size);
}
@ -374,10 +388,24 @@ ResponsiveUI.prototype = {
* When a preset is selected, apply it.
*/
presetSelected: function RUI_presetSelected() {
this.rotateValue = false;
this.currentPreset = this.menulist.selectedIndex;
let preset = this.presets[this.currentPreset];
this.loadPreset(preset);
if (this.menulist.selectedItem.getAttribute("ispreset") === "true") {
this.selectedItem = this.menulist.selectedItem;
this.rotateValue = false;
let selectedPreset = this.menuitems.get(this.selectedItem);
this.loadPreset(selectedPreset);
this.currentPresetKey = selectedPreset.key;
this.saveCurrentPreset();
// Update the buttons hidden status according to the new selected preset
if (selectedPreset == this.customPreset) {
this.addbutton.hidden = false;
this.removebutton.hidden = true;
} else {
this.addbutton.hidden = true;
this.removebutton.hidden = false;
}
}
},
/**
@ -389,15 +417,103 @@ ResponsiveUI.prototype = {
this.setSize(aPreset.width, aPreset.height);
},
/**
* Add a preset to the list and the memory
*/
addPreset: function RUI_addPreset() {
let w = this.customPreset.width;
let h = this.customPreset.height;
let newName = {};
let title = this.strings.GetStringFromName("responsiveUI.customNamePromptTitle");
let message = this.strings.formatStringFromName("responsiveUI.customNamePromptMsg", [w, h], 2);
Services.prompt.prompt(null, title, message, newName, null, {});
let newPreset = {
key: w + "x" + h,
name: newName.value,
width: w,
height: h
};
this.presets.push(newPreset);
// Sort the presets according to width/height ascending order
this.presets.sort(function RUI_sortPresets(aPresetA, aPresetB) {
// We keep custom preset at first
if (aPresetA.custom && !aPresetB.custom) {
return 1;
}
if (!aPresetA.custom && aPresetB.custom) {
return -1;
}
if (aPresetA.width === aPresetB.width) {
if (aPresetA.height === aPresetB.height) {
return 0;
} else {
return aPresetA.height > aPresetB.height;
}
} else {
return aPresetA.width > aPresetB.width;
}
});
this.savePresets();
let newMenuitem = this.chromeDoc.createElement("menuitem");
newMenuitem.setAttribute("ispreset", true);
this.setMenuLabel(newMenuitem, newPreset);
this.menuitems.set(newMenuitem, newPreset);
let idx = this.presets.indexOf(newPreset);
let beforeMenuitem = this.menulist.firstChild.childNodes[idx + 1];
this.menulist.firstChild.insertBefore(newMenuitem, beforeMenuitem);
this.menulist.selectedItem = newMenuitem;
this.currentPresetKey = newPreset.key;
this.saveCurrentPreset();
},
/**
* remove a preset from the list and the memory
*/
removePreset: function RUI_removePreset() {
let selectedPreset = this.menuitems.get(this.selectedItem);
let w = selectedPreset.width;
let h = selectedPreset.height;
this.presets.splice(this.presets.indexOf(selectedPreset), 1);
this.menulist.firstChild.removeChild(this.selectedItem);
this.menuitems.delete(this.selectedItem);
this.customPreset.width = w;
this.customPreset.height = h;
let menuitem = this.customMenuitem;
this.setMenuLabel(menuitem, this.customPreset);
this.menulist.selectedItem = menuitem;
this.currentPresetKey = this.customPreset.key;
this.setSize(w, h);
this.savePresets();
},
/**
* Swap width and height.
*/
rotate: function RUI_rotate() {
this.setSize(this.currentHeight, this.currentWidth);
if (this.currentPreset == 0) {
let selectedPreset = this.menuitems.get(this.selectedItem);
let width = this.rotateValue ? selectedPreset.height : selectedPreset.width;
let height = this.rotateValue ? selectedPreset.width : selectedPreset.height;
this.setSize(height, width);
if (selectedPreset.custom) {
this.saveCustomSize();
} else {
this.rotateValue = !this.rotateValue;
this.saveCurrentPreset();
}
},
@ -408,8 +524,8 @@ ResponsiveUI.prototype = {
* @param aHeight height of the browser.
*/
setSize: function RUI_setSize(aWidth, aHeight) {
this.currentWidth = Math.min(Math.max(aWidth, MIN_WIDTH), MAX_WIDTH);
this.currentHeight = Math.min(Math.max(aHeight, MIN_HEIGHT), MAX_WIDTH);
aWidth = Math.min(Math.max(aWidth, MIN_WIDTH), MAX_WIDTH);
aHeight = Math.min(Math.max(aHeight, MIN_HEIGHT), MAX_WIDTH);
// We resize the containing stack.
let style = "max-width: %width;" +
@ -417,22 +533,22 @@ ResponsiveUI.prototype = {
"max-height: %height;" +
"min-height: %height;";
style = style.replace(/%width/g, this.currentWidth + "px");
style = style.replace(/%height/g, this.currentHeight + "px");
style = style.replace(/%width/g, aWidth + "px");
style = style.replace(/%height/g, aHeight + "px");
this.stack.setAttribute("style", style);
if (!this.ignoreY)
this.resizeBar.setAttribute("top", Math.round(this.currentHeight / 2));
this.resizeBar.setAttribute("top", Math.round(aHeight / 2));
// We uptate the Custom menuitem if we are not using a preset.
if (this.presets[this.currentPreset].custom) {
let preset = this.presets[this.currentPreset];
preset.width = this.currentWidth;
preset.height = this.currentHeight;
let selectedPreset = this.menuitems.get(this.selectedItem);
let menuitem = this.menulist.firstChild.childNodes[this.currentPreset];
this.setMenuLabel(menuitem, preset);
// We uptate the custom menuitem if we are using it
if (selectedPreset.custom) {
selectedPreset.width = aWidth;
selectedPreset.height = aHeight;
this.setMenuLabel(this.selectedItem, selectedPreset);
}
},
@ -442,15 +558,17 @@ ResponsiveUI.prototype = {
* @param aEvent
*/
startResizing: function RUI_startResizing(aEvent) {
let preset = this.presets[this.currentPreset];
if (!preset.custom) {
this.currentPreset = 0;
preset = this.presets[0];
preset.width = this.currentWidth;
preset.height = this.currentHeight;
let menuitem = this.menulist.firstChild.childNodes[0];
this.setMenuLabel(menuitem, preset);
this.menulist.selectedIndex = 0;
let selectedPreset = this.menuitems.get(this.selectedItem);
if (!selectedPreset.custom) {
this.customPreset.width = this.rotateValue ? selectedPreset.height : selectedPreset.width;
this.customPreset.height = this.rotateValue ? selectedPreset.width : selectedPreset.height;
let menuitem = this.customMenuitem;
this.setMenuLabel(menuitem, this.customPreset);
this.currentPresetKey = this.customPreset.key;
this.menulist.selectedItem = menuitem;
}
this.mainWindow.addEventListener("mouseup", this.bound_stopResizing, true);
this.mainWindow.addEventListener("mousemove", this.bound_onDrag, true);
@ -479,8 +597,8 @@ ResponsiveUI.prototype = {
if (this.ignoreY)
deltaY = 0;
let width = this.currentWidth + deltaX;
let height = this.currentHeight + deltaY;
let width = this.customPreset.width + deltaX;
let height = this.customPreset.height + deltaY;
if (width < MIN_WIDTH) {
width = MIN_WIDTH;
@ -520,18 +638,29 @@ ResponsiveUI.prototype = {
* Store the custom size as a pref.
*/
saveCustomSize: function RUI_saveCustomSize() {
Services.prefs.setIntPref("devtools.responsiveUI.customWidth", this.currentWidth);
Services.prefs.setIntPref("devtools.responsiveUI.customHeight", this.currentHeight);
Services.prefs.setIntPref("devtools.responsiveUI.customWidth", this.customPreset.width);
Services.prefs.setIntPref("devtools.responsiveUI.customHeight", this.customPreset.height);
},
/**
* Store the current preset as a pref.
*/
saveCurrentPreset: function RUI_saveCurrentPreset() {
let key = this.presets[this.currentPreset].key;
Services.prefs.setCharPref("devtools.responsiveUI.currentPreset", key);
Services.prefs.setCharPref("devtools.responsiveUI.currentPreset", this.currentPresetKey);
Services.prefs.setBoolPref("devtools.responsiveUI.rotate", this.rotateValue);
},
/**
* Store the list of all registered presets as a pref.
*/
savePresets: function RUI_savePresets() {
// We exclude the custom one
let registeredPresets = this.presets.filter(function (aPreset) {
return !aPreset.custom;
});
Services.prefs.setCharPref("devtools.responsiveUI.presets", JSON.stringify(registeredPresets));
},
}
XPCOMUtils.defineLazyGetter(ResponsiveUI.prototype, "strings", function () {

View File

@ -49,6 +49,7 @@ _BROWSER_FILES = \
browser_responsiveruleview.js \
browser_responsive_cmd.js \
browser_responsivecomputedview.js \
browser_responsiveuiaddcustompreset.js \
head.js \
helpers.js \
$(NULL)

View File

@ -50,7 +50,8 @@ function test() {
testOnePreset(c - 1);
}
testOnePreset(instance.menulist.firstChild.childNodes.length - 1);
// Starting from length - 4 because last 3 items are not presets : separator, addbutton and removebutton
testOnePreset(instance.menulist.firstChild.childNodes.length - 4);
}
function extractSizeFromString(str) {

View File

@ -0,0 +1,162 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
function test() {
let instance, deletedPresetA, deletedPresetB, oldPrompt;
waitForExplicitFinish();
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function onload() {
gBrowser.selectedBrowser.removeEventListener("load", onload, true);
waitForFocus(startTest, content);
}, true);
content.location = "data:text/html,foo";
function startTest() {
// Mocking prompt
oldPrompt = Services.prompt;
Services.prompt = {
prompt: function(aParent, aDialogTitle, aText, aValue, aCheckMsg, aCheckState) {
aValue.value = "Testing preset";
}
};
document.getElementById("Tools:ResponsiveUI").removeAttribute("disabled");
synthesizeKeyFromKeyTag("key_responsiveUI");
executeSoon(onUIOpen);
}
function onUIOpen() {
// Is it open?
let container = gBrowser.getBrowserContainer();
is(container.getAttribute("responsivemode"), "true", "In responsive mode.");
instance = gBrowser.selectedTab.__responsiveUI;
ok(instance, "instance of the module is attached to the tab.");
instance.transitionsEnabled = false;
testAddCustomPreset();
}
function testAddCustomPreset() {
let customHeight = 123, customWidth = 456;
instance.setSize(customWidth, customHeight);
// Adds the custom preset with "Testing preset" as label (look at mock upper)
instance.addbutton.doCommand();
instance.menulist.selectedIndex = 1;
EventUtils.synthesizeKey("VK_ESCAPE", {});
executeSoon(restart);
}
function restart() {
synthesizeKeyFromKeyTag("key_responsiveUI");
let container = gBrowser.getBrowserContainer();
is(container.getAttribute("responsivemode"), "true", "In responsive mode.");
instance = gBrowser.selectedTab.__responsiveUI;
testCustomPresetInList();
}
function testCustomPresetInList() {
let customPresetIndex = getPresetIndex("456x123 (Testing preset)");
ok(customPresetIndex >= 0, "is the previously added preset (idx = " + customPresetIndex + ") in the list of items");
instance.menulist.selectedIndex = customPresetIndex;
is(content.innerWidth, 456, "add preset, and selected in the list, dimension valid (width)");
is(content.innerHeight, 123, "add preset, and selected in the list, dimension valid (height)");
testDeleteCustomPresets();
}
function testDeleteCustomPresets() {
instance.removebutton.doCommand();
instance.menulist.selectedIndex = 2;
deletedPresetA = instance.menulist.selectedItem.getAttribute("label");
instance.removebutton.doCommand();
instance.menulist.selectedIndex = 2;
deletedPresetB = instance.menulist.selectedItem.getAttribute("label");
instance.removebutton.doCommand();
EventUtils.synthesizeKey("VK_ESCAPE", {});
executeSoon(restartAgain);
}
function restartAgain() {
synthesizeKeyFromKeyTag("key_responsiveUI");
instance = gBrowser.selectedTab.__responsiveUI;
executeSoon(testCustomPresetsNotInListAnymore);
}
function testCustomPresetsNotInListAnymore() {
let customPresetIndex = getPresetIndex(deletedPresetA);
is(customPresetIndex, -1, "deleted preset " + deletedPresetA + " is not in the list anymore");
customPresetIndex = getPresetIndex(deletedPresetB);
is(customPresetIndex, -1, "deleted preset " + deletedPresetB + " is not in the list anymore");
executeSoon(finishUp);
}
function finishUp() {
delete instance;
gBrowser.removeCurrentTab();
Services.prompt = oldPrompt;
finish();
}
function getPresetIndex(presetLabel) {
function testOnePreset(c) {
if (c == 0) {
return -1;
}
instance.menulist.selectedIndex = c;
let item = instance.menulist.firstChild.childNodes[c];
if (item.getAttribute("label") === presetLabel) {
return c;
} else {
return testOnePreset(c - 1);
}
}
return testOnePreset(instance.menulist.firstChild.childNodes.length - 4);
}
function synthesizeKeyFromKeyTag(aKeyId) {
let key = document.getElementById(aKeyId);
isnot(key, null, "Successfully retrieved the <key> node");
let modifiersAttr = key.getAttribute("modifiers");
let name = null;
if (key.getAttribute("keycode"))
name = key.getAttribute("keycode");
else if (key.getAttribute("key"))
name = key.getAttribute("key");
isnot(name, null, "Successfully retrieved keycode/key");
let modifiers = {
shiftKey: modifiersAttr.match("shift"),
ctrlKey: modifiersAttr.match("ctrl"),
altKey: modifiersAttr.match("alt"),
metaKey: modifiersAttr.match("meta"),
accelKey: modifiersAttr.match("accel")
}
EventUtils.synthesizeKey(name, modifiers);
}
}

View File

@ -17,6 +17,7 @@
title="&window.title;"
windowtype="devtools:scratchpad"
macanimationtype="document"
fullscreenbutton="true"
screenX="4" screenY="4"
width="640" height="480"
persist="screenX screenY width height sizemode">

View File

@ -11,7 +11,26 @@
# LOCALIZATION NOTE (responsiveUI.rotate): label of the rotate button.
responsiveUI.rotate=rotate
# LOCALIZATION NOTE (responsiveUI.addPreset): label of the add preset button.
responsiveUI.addPreset=Add Preset
# LOCALIZATION NOTE (responsiveUI.removePreset): label of the remove preset button.
responsiveUI.removePreset=Remove Preset
# LOCALIZATION NOTE (responsiveUI.customResolution): label of the first item
# in the menulist at the beginning of the toolbar. For %S is replace with the
# current size of the page. For example: "400x600".
responsiveUI.customResolution=%S (custom)
# LOCALIZATION NOTE (responsiveUI.namedResolution): label of custom items with a name
# in the menulist of the toolbar.
# For example: "320x480 (phone)".
responsiveUI.namedResolution=%S (%S)
# LOCALIZATION NOTE (responsiveUI.customNamePromptTitle): prompt title when asking
# the user to specify a name for a new custom preset.
responsiveUI.customNamePromptTitle=Responsive Design View
# LOCALIZATION NOTE (responsiveUI.customNamePromptMsg): prompt message when asking
# the user to specify a name for a new custom preset.
responsiveUI.customNamePromptMsg=Give a name to the %Sx%S preset

View File

@ -159,14 +159,7 @@
...
}
{
Bug 793615
Memcheck:Leak
fun:malloc
fun:sqlite3MemMalloc
...
}
{
Bug 793616
Bug 793608 variant 2
Memcheck:Leak
fun:malloc
fun:make_request
@ -178,6 +171,13 @@
fun:start_thread
fun:clone
}
{
Bug 793615
Memcheck:Leak
fun:malloc
fun:sqlite3MemMalloc
...
}
{
Bug 794350
Memcheck:Leak
@ -217,13 +217,6 @@
fun:_ZN2js4mjit2ic10GetElementERNS_7VMFrameEPNS1_12GetElementICE
...
}
{
Bug 794365
Memcheck:Leak
fun:malloc
fun:_ZN14JSInlineString8uninlineEP9JSContext
...
}
{
Bug 794369
Memcheck:Leak