Merge m-c to inbound a=merge CLOSED TREE

This commit is contained in:
Wes Kocher 2014-12-19 16:01:05 -08:00
Родитель 27460dcbd2 0996442e97
Коммит b6f591574c
32 изменённых файлов: 289 добавлений и 123 удалений

Просмотреть файл

@ -982,7 +982,7 @@ let MozLoopServiceInternal = {
code: code,
state: state,
};
return this.hawkRequest(LOOP_SESSION_TYPE.FXA, "/fxa-oauth/token", "POST", payload).then(response => {
return this.hawkRequestInternal(LOOP_SESSION_TYPE.FXA, "/fxa-oauth/token", "POST", payload).then(response => {
return JSON.parse(response.body);
},
error => {this._hawkRequestError(error);});

Просмотреть файл

@ -94,15 +94,10 @@ loop.roomViews = (function(mozL10n) {
handleFormSubmit: function(event) {
event.preventDefault();
var newRoomName = this.state.newRoomName;
if (newRoomName && this.state.roomName != newRoomName) {
this.props.dispatcher.dispatch(
new sharedActions.RenameRoom({
roomToken: this.state.roomToken,
newRoomName: newRoomName
}));
}
this.props.dispatcher.dispatch(new sharedActions.RenameRoom({
roomToken: this.state.roomToken,
newRoomName: this.state.newRoomName
}));
},
handleEmailButtonClick: function(event) {

Просмотреть файл

@ -94,15 +94,10 @@ loop.roomViews = (function(mozL10n) {
handleFormSubmit: function(event) {
event.preventDefault();
var newRoomName = this.state.newRoomName;
if (newRoomName && this.state.roomName != newRoomName) {
this.props.dispatcher.dispatch(
new sharedActions.RenameRoom({
roomToken: this.state.roomToken,
newRoomName: newRoomName
}));
}
this.props.dispatcher.dispatch(new sharedActions.RenameRoom({
roomToken: this.state.roomToken,
newRoomName: this.state.newRoomName
}));
},
handleEmailButtonClick: function(event) {

Просмотреть файл

@ -81,7 +81,6 @@ p {
.btn {
display: inline-block;
overflow: hidden;
margin: 0;
padding: 0;
border: none;
@ -89,12 +88,16 @@ p {
color: #fff;
text-align: center;
text-decoration: none;
text-overflow: ellipsis;
white-space: nowrap;
font-size: .9em;
cursor: pointer;
}
.btn.btn-constrained {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.btn-info {
background-color: #0096dd;
border: 1px solid #0095dd;

Просмотреть файл

@ -262,7 +262,7 @@
}
.call-action-group > .btn {
height: 26px;
min-height: 26px;
border-radius: 2px;
margin: 0 4px;
min-width: 64px;

Просмотреть файл

@ -154,10 +154,13 @@ loop.store = loop.store || {};
* @param {Object} addedRoomData The added room data.
*/
_onRoomAdded: function(eventName, addedRoomData) {
addedRoomData.participants = [];
addedRoomData.ctime = new Date().getTime();
addedRoomData.participants = addedRoomData.participants || [];
addedRoomData.ctime = addedRoomData.ctime || new Date().getTime();
this.dispatchAction(new sharedActions.UpdateRoomList({
roomList: this._storeState.rooms.concat(new Room(addedRoomData))
// Ensure the room isn't part of the list already, then add it.
roomList: this._storeState.rooms.filter(function(room) {
return addedRoomData.roomToken !== room.roomToken;
}).concat(new Room(addedRoomData))
}));
},
@ -420,8 +423,15 @@ loop.store = loop.store || {};
* @param {sharedActions.RenameRoom} actionData
*/
renameRoom: function(actionData) {
var newRoomName = actionData.newRoomName.trim();
// Skip update if name is unchanged or empty.
if (!newRoomName || this.getStoreState("roomName") === newRoomName) {
return;
}
this.setStoreState({error: null});
this._mozLoop.rooms.rename(actionData.roomToken, actionData.newRoomName,
this._mozLoop.rooms.rename(actionData.roomToken, newRoomName,
function(err) {
if (err) {
this.dispatchAction(new sharedActions.RenameRoomError({error: err}));

Просмотреть файл

@ -391,7 +391,7 @@ loop.webapp = (function($, _, OT, mozL10n) {
React.DOM.div({className: "standalone-btn-chevron-menu-group"},
React.DOM.div({className: "btn-group-chevron"},
React.DOM.div({className: "btn-group"},
React.DOM.button({className: "btn btn-large btn-accept",
React.DOM.button({className: "btn btn-constrained btn-large btn-accept",
onClick: this.props.startCall("audio-video"),
disabled: this.props.disabled,
title: mozL10n.get("initiate_audio_video_call_tooltip2")},

Просмотреть файл

@ -391,7 +391,7 @@ loop.webapp = (function($, _, OT, mozL10n) {
<div className="standalone-btn-chevron-menu-group">
<div className="btn-group-chevron">
<div className="btn-group">
<button className="btn btn-large btn-accept"
<button className="btn btn-constrained btn-large btn-accept"
onClick={this.props.startCall("audio-video")}
disabled={this.props.disabled}
title={mozL10n.get("initiate_audio_video_call_tooltip2")}>

Просмотреть файл

@ -128,14 +128,14 @@ describe("loop.roomViews", function () {
});
roomNameBox = view.getDOMNode().querySelector('.input-room-name');
React.addons.TestUtils.Simulate.change(roomNameBox, { target: {
value: "reallyFake"
}});
});
it("should dispatch a RenameRoom action when the focus is lost",
function() {
React.addons.TestUtils.Simulate.change(roomNameBox, { target: {
value: "reallyFake"
}});
React.addons.TestUtils.Simulate.blur(roomNameBox);
sinon.assert.calledOnce(dispatcher.dispatch);
@ -148,6 +148,10 @@ describe("loop.roomViews", function () {
it("should dispatch a RenameRoom action when Enter key is pressed",
function() {
React.addons.TestUtils.Simulate.change(roomNameBox, { target: {
value: "reallyFake"
}});
TestUtils.Simulate.keyDown(roomNameBox, {key: "Enter", which: 13});
sinon.assert.calledOnce(dispatcher.dispatch);

Просмотреть файл

@ -21,34 +21,34 @@ describe("loop.store.RoomStore", function () {
var sharedActions = loop.shared.actions;
var sharedUtils = loop.shared.utils;
var sandbox, dispatcher;
var fakeRoomList = [{
roomToken: "_nxD4V4FflQ",
roomUrl: "http://sample/_nxD4V4FflQ",
roomName: "First Room Name",
maxSize: 2,
participants: [],
ctime: 1405517546
}, {
roomToken: "QzBbvGmIZWU",
roomUrl: "http://sample/QzBbvGmIZWU",
roomName: "Second Room Name",
maxSize: 2,
participants: [],
ctime: 1405517418
}, {
roomToken: "3jKS_Els9IU",
roomUrl: "http://sample/3jKS_Els9IU",
roomName: "Third Room Name",
maxSize: 3,
clientMaxSize: 2,
participants: [],
ctime: 1405518241
}];
var fakeRoomList;
beforeEach(function() {
sandbox = sinon.sandbox.create();
dispatcher = new loop.Dispatcher();
fakeRoomList = [{
roomToken: "_nxD4V4FflQ",
roomUrl: "http://sample/_nxD4V4FflQ",
roomName: "First Room Name",
maxSize: 2,
participants: [],
ctime: 1405517546
}, {
roomToken: "QzBbvGmIZWU",
roomUrl: "http://sample/QzBbvGmIZWU",
roomName: "Second Room Name",
maxSize: 2,
participants: [],
ctime: 1405517418
}, {
roomToken: "3jKS_Els9IU",
roomUrl: "http://sample/3jKS_Els9IU",
roomName: "Third Room Name",
maxSize: 3,
clientMaxSize: 2,
participants: [],
ctime: 1405518241
}];
});
afterEach(function() {
@ -121,6 +121,17 @@ describe("loop.store.RoomStore", function () {
expect(store.getStoreState().rooms).to.have.length.of(4);
});
it("should avoid adding a duplicate room", function() {
var sampleRoom = fakeRoomList[0];
fakeMozLoop.rooms.trigger("add", "add", sampleRoom);
expect(store.getStoreState().rooms).to.have.length.of(3);
expect(store.getStoreState().rooms.reduce(function(count, room) {
return count += room.roomToken === sampleRoom.roomToken ? 1 : 0;
}, 0)).eql(1);
});
});
describe("update", function() {
@ -539,5 +550,16 @@ describe("loop.store.RoomStore", function () {
expect(store.getStoreState().error).eql(err);
});
it("should ensure only submitting a non-empty room name", function() {
fakeMozLoop.rooms.rename = sinon.spy();
dispatcher.dispatch(new sharedActions.RenameRoom({
roomToken: "42abc",
newRoomName: " \t \t "
}));
sinon.assert.notCalled(fakeMozLoop.rooms.rename);
});
});
});

Просмотреть файл

@ -90,6 +90,9 @@ var gSearchPane = {
onTreeKeyPress: function(aEvent) {
let index = gEngineView.selectedIndex;
let tree = document.getElementById("engineList");
if (tree.hasAttribute("editing"))
return;
if (aEvent.charCode == KeyEvent.DOM_VK_SPACE) {
// Space toggles the checkbox.
let newValue = !gEngineView._engineStore.engines[index].shown;

Просмотреть файл

@ -83,6 +83,9 @@ var gSearchPane = {
onTreeKeyPress: function(aEvent) {
let index = gEngineView.selectedIndex;
let tree = document.getElementById("engineList");
if (tree.hasAttribute("editing"))
return;
if (aEvent.charCode == KeyEvent.DOM_VK_SPACE) {
// Space toggles the checkbox.
let newValue = !gEngineView._engineStore.engines[index].shown;

Просмотреть файл

@ -5,20 +5,38 @@
font-family: bar;
src: url(bad/font/name.ttf), url(ostrich-regular.ttf) format("truetype");
}
@font-face {
font-family: barnormal;
font-weight: normal;
src: url(ostrich-regular.ttf);
}
@font-face {
font-family: bar;
font-weight: bold;
src: url(ostrich-black.ttf);
}
@font-face {
font-family: bar;
font-weight: 800;
src: url(ostrich-black.ttf);
}
body{
font-family:Arial;
font-size: 36px;
}
div {
font-family:Arial;
font-family:bar;
}
.normal-text {
font-family: barnormal;
font-weight: normal;
}
.bold-text {
font-family: bar;
font-weight: bold;
}
.black-text {
font-family: bar;
font-weight: 800;
}
@ -27,4 +45,7 @@
<body>
BODY
<div>DIV</div>
<div class="normal-text">NORMAL DIV</div>
<div class="bold-text">BOLD DIV</div>
<div class="black-text">800 DIV</div>
</body>

Просмотреть файл

@ -10,6 +10,19 @@ let TEST_URI = "http://mochi.test:8888/browser/browser/devtools/fontinspector/te
let view, viewDoc;
const BASE_URI = "http://mochi.test:8888/browser/browser/devtools/fontinspector/test/"
const FONTS = [
{name: "Ostrich Sans Medium", remote: true, url: BASE_URI + "ostrich-regular.ttf",
format: "truetype", cssName: "bar"},
{name: "Ostrich Sans Black", remote: true, url: BASE_URI + "ostrich-black.ttf",
format: "", cssName: "bar"},
{name: "Ostrich Sans Black", remote: true, url: BASE_URI + "ostrich-black.ttf",
format: "", cssName: "bar"},
{name: "Ostrich Sans Medium", remote: true, url: BASE_URI + "ostrich-regular.ttf",
format: "", cssName: "barnormal"},
];
add_task(function*() {
yield loadTab(TEST_URI);
let {toolbox, inspector} = yield openInspector();
@ -39,32 +52,41 @@ add_task(function*() {
function* testBodyFonts(inspector) {
let s = viewDoc.querySelectorAll("#all-fonts > section");
is(s.length, 2, "Found 2 fonts");
is(s.length, 5, "Found 5 fonts");
// test first web font
is(s[0].querySelector(".font-name").textContent,
"Ostrich Sans Medium", "font 0: Right font name");
ok(s[0].classList.contains("is-remote"),
"font 0: is remote");
is(s[0].querySelector(".font-url").value,
"http://mochi.test:8888/browser/browser/devtools/fontinspector/test/ostrich-regular.ttf",
"font 0: right url");
is(s[0].querySelector(".font-format").textContent,
"truetype", "font 0: right font format");
is(s[0].querySelector(".font-css-name").textContent,
"bar", "font 0: right css name");
for (let i = 0; i < FONTS.length; i++) {
let section = s[i];
let font = FONTS[i];
is(section.querySelector(".font-name").textContent, font.name,
"font " + i + " right font name");
is(section.classList.contains("is-remote"), font.remote,
"font " + i + " remote value correct");
is(section.querySelector(".font-url").value, font.url,
"font " + i + " url correct");
is(section.querySelector(".font-format").hidden, !font.format,
"font " + i + " format hidden value correct");
is(section.querySelector(".font-format").textContent,
font.format, "font " + i + " format correct");
is(section.querySelector(".font-css-name").textContent,
font.cssName, "font " + i + " css name correct");
}
// test that the bold and regular fonts have different previews
let regSrc = s[0].querySelector(".font-preview").src;
let boldSrc = s[1].querySelector(".font-preview").src;
isnot(regSrc, boldSrc, "preview for bold font is different from regular");
// test system font
let font2Name = s[1].querySelector(".font-name").textContent;
let font2CssName = s[1].querySelector(".font-css-name").textContent;
let localFontName = s[4].querySelector(".font-name").textContent;
let localFontCSSName = s[4].querySelector(".font-css-name").textContent;
// On Linux test machines, the Arial font doesn't exist.
// The fallback is "Liberation Sans"
ok((font2Name == "Arial") || (font2Name == "Liberation Sans"),
"font 1: Right font name");
ok(s[1].classList.contains("is-local"), "font 2: is local");
ok((font2CssName == "Arial") || (font2CssName == "Liberation Sans"),
"Arial", "font 2: right css name");
ok((localFontName == "Arial") || (localFontName == "Liberation Sans"),
"local font right font name");
ok(s[4].classList.contains("is-local"), "local font is local");
ok((localFontCSSName == "Arial") || (localFontCSSName == "Liberation Sans"),
"Arial", "local font has right css name");
}
function* testDivFonts(inspector) {
@ -87,5 +109,5 @@ function* testShowAllFonts(inspector) {
is(inspector.selection.nodeFront.nodeName, "BODY", "Show all fonts selected the body node");
let sections = viewDoc.querySelectorAll("#all-fonts > section");
is(sections.length, 2, "And font-inspector still shows 2 fonts for body");
is(sections.length, 5, "And font-inspector still shows 5 fonts for body");
}

Просмотреть файл

@ -29,24 +29,30 @@
<h2>&prefs_general_title;</h2>
<ul>
<li>
<label title="&prefs_options_templatesurl_tooltip;">
<span>&prefs_options_templatesurl;</span>
<input data-pref="devtools.webide.templatesURL"/>
</label>
</li>
<li>
<label title="&prefs_options_rememberlastproject_tooltip;">
<input type="checkbox" data-pref="devtools.webide.restoreLastProject"/>
<span>&prefs_options_rememberlastproject;</span>
</label>
</li>
<li>
<label title="&prefs_options_autoconnectruntime_tooltip;">
<input type="checkbox" data-pref="devtools.webide.autoConnectRuntime"/>
<span>&prefs_options_autoconnectruntime;</span>
</label>
</li>
<li>
<label title="&prefs_options_showeditor_tooltip;">
<input type="checkbox" data-pref="devtools.webide.showProjectEditor"/>
<span>&prefs_options_showeditor;</span>
</label>
</li>
<li>
<label title="&prefs_options_templatesurl_tooltip;">
<span>&prefs_options_templatesurl;</span>
<input data-pref="devtools.webide.templatesURL"/>
</label>
</li>
</ul>
<h2>&prefs_editor_title;</h2>

Просмотреть файл

@ -94,8 +94,6 @@ let UI = {
Services.prefs.setBoolPref("devtools.webide.autoinstallADBHelper", false);
Services.prefs.setBoolPref("devtools.webide.autoinstallFxdtAdapters", false);
this.lastConnectedRuntime = Services.prefs.getCharPref("devtools.webide.lastConnectedRuntime");
if (Services.prefs.getBoolPref("devtools.webide.widget.autoinstall") &&
!Services.prefs.getBoolPref("devtools.webide.widget.enabled")) {
Services.prefs.setBoolPref("devtools.webide.widget.enabled", true);
@ -393,10 +391,20 @@ let UI = {
}
},
get lastConnectedRuntime() {
return Services.prefs.getCharPref("devtools.webide.lastConnectedRuntime");
},
set lastConnectedRuntime(runtime) {
Services.prefs.setCharPref("devtools.webide.lastConnectedRuntime", runtime);
},
autoConnectRuntime: function () {
// Automatically reconnect to the previously selected runtime,
// if available and has an ID
if (AppManager.selectedRuntime || !this.lastConnectedRuntime) {
// if available and has an ID and feature is enabled
if (AppManager.selectedRuntime ||
!Services.prefs.getBoolPref("devtools.webide.autoConnectRuntime") ||
!this.lastConnectedRuntime) {
return;
}
let [_, type, id] = this.lastConnectedRuntime.match(/^(\w+):(.+)$/);
@ -415,6 +423,8 @@ let UI = {
// Some runtimes do not expose an id and don't support autoconnect (like
// remote connection)
if (runtime.id == id) {
// Only want one auto-connect attempt, so clear last runtime value
this.lastConnectedRuntime = "";
this.connectToRuntime(runtime);
}
}
@ -446,8 +456,6 @@ let UI = {
} else {
this.lastConnectedRuntime = "";
}
Services.prefs.setCharPref("devtools.webide.lastConnectedRuntime",
this.lastConnectedRuntime);
},
_actionsToLog: new Set(),

Просмотреть файл

@ -11,6 +11,7 @@ pref("devtools.webide.autoinstallFxdtAdapters", true);
#else
pref("devtools.webide.autoinstallFxdtAdapters", false);
#endif
pref("devtools.webide.autoConnectRuntime", true);
pref("devtools.webide.restoreLastProject", true);
pref("devtools.webide.enableLocalRuntime", false);
pref("devtools.webide.addonsURL", "https://ftp.mozilla.org/pub/mozilla.org/labs/fxos-simulator/index.json");

Просмотреть файл

@ -114,6 +114,8 @@
<!ENTITY prefs_general_title "General">
<!ENTITY prefs_restore "Restore Defaults">
<!ENTITY prefs_manage_components "Manage Extra Components">
<!ENTITY prefs_options_autoconnectruntime "Reconnect to previous runtime">
<!ENTITY prefs_options_autoconnectruntime_tooltip "Reconnect to previous runtime when WebIDE starts">
<!ENTITY prefs_options_rememberlastproject "Remember last project">
<!ENTITY prefs_options_rememberlastproject_tooltip "Restore previous project when WebIDE starts">
<!ENTITY prefs_options_templatesurl "Templates URL">

Просмотреть файл

@ -235,6 +235,9 @@ description > html|a {
background-color: #fbfbfb;
color: #424e5a;
font-size: 14px;
/* `transparent` will use the dialogText color in high-contrast themes and
when page colors are disabled */
border: 1px solid transparent;
border-radius: 2.5px;
box-shadow: 0 2px 4px 0 rgba(0,0,0,0.5);
display: -moz-box;

Просмотреть файл

@ -1650,6 +1650,7 @@ public abstract class GeckoApp
// updated before Gecko has restored.
if (mShouldRestore) {
final JSONArray tabs = new JSONArray();
final JSONObject windowObject = new JSONObject();
SessionParser parser = new SessionParser() {
@Override
public void onTabRead(SessionTab sessionTab) {
@ -1670,6 +1671,11 @@ public abstract class GeckoApp
}
tabs.put(tabObject);
}
@Override
public void onClosedTabsRead(final JSONArray closedTabData) throws JSONException {
windowObject.put("closedTabs", closedTabData);
}
};
if (mPrivateBrowsingSession == null) {
@ -1679,7 +1685,8 @@ public abstract class GeckoApp
}
if (tabs.length() > 0) {
sessionString = new JSONObject().put("windows", new JSONArray().put(new JSONObject().put("tabs", tabs))).toString();
windowObject.put("tabs", tabs);
sessionString = new JSONObject().put("windows", new JSONArray().put(windowObject)).toString();
} else {
throw new SessionRestoreException("No tabs could be read from session file");
}
@ -1688,7 +1695,6 @@ public abstract class GeckoApp
JSONObject restoreData = new JSONObject();
restoreData.put("sessionString", sessionString);
return restoreData.toString();
} catch (JSONException e) {
throw new SessionRestoreException(e);
}

Просмотреть файл

@ -52,6 +52,15 @@ public abstract class SessionParser {
abstract public void onTabRead(SessionTab tab);
/**
* Placeholder method that must be overloaded to handle closedTabs while parsing session data.
*
* @param closedTabs, JSONArray of recently closed tab entries.
* @throws JSONException
*/
public void onClosedTabsRead(final JSONArray closedTabs) throws JSONException{
}
public void parse(String... sessionStrings) {
final LinkedList<SessionTab> sessionTabs = new LinkedList<SessionTab>();
int totalCount = 0;
@ -61,6 +70,10 @@ public abstract class SessionParser {
final JSONObject window = new JSONObject(sessionString).getJSONArray("windows").getJSONObject(0);
final JSONArray tabs = window.getJSONArray("tabs");
final int optSelected = window.optInt("selected", -1);
final JSONArray closedTabs = window.optJSONArray("closedTabs");
if (closedTabs != null) {
onClosedTabsRead(closedTabs);
}
for (int i = 0; i < tabs.length(); i++) {
final JSONObject tab = tabs.getJSONObject(i);

Просмотреть файл

@ -140,7 +140,6 @@ public abstract class BrowserToolbar extends ThemedRelativeLayout
private final Paint shadowPaint;
private final int shadowSize;
private final LightweightTheme theme;
private final ToolbarPrefs prefs;
public abstract boolean isAnimating();
@ -179,7 +178,6 @@ public abstract class BrowserToolbar extends ThemedRelativeLayout
setWillNotDraw(false);
isNewTablet = NewTabletUI.isEnabled(context);
theme = ((GeckoApplication) context.getApplicationContext()).getLightweightTheme();
// BrowserToolbar is attached to BrowserApp only.
activity = (BrowserApp) context;

Просмотреть файл

@ -63,7 +63,7 @@ abstract class NavButton extends ShapedButton {
public void onLightweightThemeChanged() {
final Drawable drawable;
if (!NewTabletUI.isEnabled(getContext())) {
drawable = mTheme.getDrawable(this);
drawable = getTheme().getDrawable(this);
} else {
drawable = BrowserToolbar.getLightweightThemeDrawable(this, getResources(), getTheme(),
R.color.background_normal);

Просмотреть файл

@ -23,14 +23,12 @@ import android.util.AttributeSet;
public class ShapedButton extends ThemedImageButton
implements CanvasDelegate.DrawManager {
protected final LightweightTheme mTheme;
protected final Path mPath;
protected final CanvasDelegate mCanvasDelegate;
public ShapedButton(Context context, AttributeSet attrs) {
super(context, attrs);
mTheme = ((GeckoApplication) context.getApplicationContext()).getLightweightTheme();
// Path is clipped.
mPath = new Path();
@ -61,7 +59,7 @@ public class ShapedButton extends ThemedImageButton
@Override
public void onLightweightThemeChanged() {
final int background = getResources().getColor(R.color.background_tabs);
final LightweightThemeDrawable lightWeight = mTheme.getColorDrawable(this, background);
final LightweightThemeDrawable lightWeight = getTheme().getColorDrawable(this, background);
if (lightWeight == null)
return;

Просмотреть файл

@ -434,6 +434,10 @@ SessionStore.prototype = {
normalWin[prop] = data[prop];
}
normalWin.tabs = [];
// Save normal closed tabs. Forget about private closed tabs.
normalWin.closedTabs = win.closedTabs.filter(tab => !tab.isPrivate);
normalData.windows.push(normalWin);
privateData.windows.push({ tabs: [] });
@ -865,6 +869,11 @@ SessionStore.prototype = {
tab.browser.__SS_extdata = tabData.extData;
}
// Restore the closed tabs array on the current window.
if (state.windows[0].closedTabs) {
this._windows[window.__SSID].closedTabs = state.windows[0].closedTabs;
}
},
getClosedTabCount: function ss_getClosedTabCount(aWindow) {
@ -994,26 +1003,9 @@ SessionStore.prototype = {
let notifyMessage = "";
try {
// Normally, we'll receive the session string from Java, but there are
// cases where we may want to restore that Java cannot detect (e.g., if
// browser.sessionstore.resume_session_once is true). In these cases, the
// session will be read from sessionstore.bak (which is also used for
// "tabs from last time").
let data = aSessionString;
if (data == null) {
let bytes = yield OS.File.read(this._sessionFileBackup.path);
data = JSON.parse(new TextDecoder().decode(bytes) || "");
}
this._restoreWindow(data);
this._restoreWindow(aSessionString);
} catch (e) {
if (e instanceof OS.File.Error) {
Cu.reportError("SessionStore: " + e.message);
} else {
Cu.reportError("SessionStore: " + e);
}
Cu.reportError("SessionStore: " + e);
notifyMessage = "fail";
}

Просмотреть файл

@ -40,6 +40,8 @@ const XHTML_NS = "http://www.w3.org/1999/xhtml";
const FONT_PREVIEW_TEXT = "Abc";
const FONT_PREVIEW_FONT_SIZE = 40;
const FONT_PREVIEW_FILLSTYLE = "black";
const NORMAL_FONT_WEIGHT = 400;
const BOLD_FONT_WEIGHT = 700;
// Predeclare the domnode actor type for use in requests.
types.addActorType("domnode");
@ -276,10 +278,26 @@ var PageStyleActor = protocol.ActorClass({
fontFace.ruleText = font.rule.cssText;
}
// Get the weight and style of this font for the preview and sort order
let weight = NORMAL_FONT_WEIGHT, style = "";
if (font.rule) {
weight = font.rule.style.getPropertyValue("font-weight")
|| NORMAL_FONT_WEIGHT;
if (weight == "bold") {
weight = BOLD_FONT_WEIGHT;
} else if (weight == "normal") {
weight = NORMAL_FONT_WEIGHT;
}
style = font.rule.style.getPropertyValue("font-style") || "";
}
fontFace.weight = weight;
fontFace.style = style;
if (options.includePreviews) {
let opts = {
previewText: options.previewText,
previewFontSize: options.previewFontSize,
fontStyle: weight + " " + style,
fillStyle: options.previewFillStyle
}
let { dataURL, size } = getFontPreviewData(font.CSSFamilyName,
@ -293,6 +311,9 @@ var PageStyleActor = protocol.ActorClass({
}
// @font-face fonts at the top, then alphabetically, then by weight
fontsArray.sort(function(a, b) {
return a.weight > b.weight ? 1 : -1;
});
fontsArray.sort(function(a, b) {
if (a.CSSFamilyName == b.CSSFamilyName) {
return 0;

Просмотреть файл

@ -844,6 +844,11 @@ this.AddonRepository = {
if (idIndex == -1)
continue;
// Ignore add-on if the add-on manager doesn't know about its type:
if (!(result.addon.type in AddonManager.addonTypes)) {
continue;
}
results.push(result);
// Ignore this add-on from now on
ids.splice(idIndex, 1);
@ -1089,10 +1094,8 @@ this.AddonRepository = {
addon.type = "search";
break;
case 5:
addon.type = "langpack";
break;
case 6:
addon.type = "langpack-addon";
addon.type = "locale";
break;
case 7:
addon.type = "plugin";
@ -1303,6 +1306,10 @@ this.AddonRepository = {
if (requiredAttributes.some(function parseAddons_attributeFilter(aAttribute) !result.addon[aAttribute]))
continue;
// Ignore add-on with a type AddonManager doesn't understand:
if (!(result.addon.type in AddonManager.addonTypes))
continue;
// Add only if the add-on is compatible with the platform
if (!result.addon.isPlatformCompatible)
continue;

Просмотреть файл

@ -31,6 +31,37 @@
<compatible_os>ALL</compatible_os>
<install size="1">http://example.com/addon1.xpi</install>
</addon>
<addon>
<name>FAIL</name>
<type id='9'>lightweight theme</type>
<guid>addon12345@tests.mozilla.org</guid>
<version>1.0</version>
<authors>
<author>
<name>Test Creator</name>
<link>http://example.com/creator.html</link>
</author>
</authors>
<status id='4'>Public</status>
<summary>Addon with uninstallable type shouldn't be visible in search</summary>
<description>Test description</description>
<compatible_applications>
<application>
<name>Firefox</name>
<appID>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</appID>
<min_version>0</min_version>
<max_version>*</max_version>
</application>
<application>
<name>SeaMonkey</name>
<appID>{92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a}</appID>
<min_version>0</min_version>
<max_version>*</max_version>
</application>
</compatible_applications>
<compatible_os>ALL</compatible_os>
<install size="1">http://example.com/addon1.xpi</install>
</addon>
<addon>
<name>FAIL</name>
<type id='1'>Extension</type>

Просмотреть файл

@ -98,7 +98,7 @@
<addon>
<name>Repo Add-on 3</name>
<type id="9999">Unknown</type>
<type id="2">Theme</type>
<guid>test_AddonRepository_3@tests.mozilla.org</guid>
<version>2.3</version>
<icon size="32">http://localhost/repo/3/icon.png</icon>

Просмотреть файл

@ -169,7 +169,7 @@
-->
<addon>
<name>PASS</name>
<type id="9999">Unknown</type>
<type id="2">Theme</type>
<guid>test_AddonRepository_1@tests.mozilla.org</guid>
<version>1.4</version>
<status id="9999">Unknown</status>

Просмотреть файл

@ -105,6 +105,7 @@ var GET_RESULTS = [{
}]
}, {
id: "test_AddonRepository_1@tests.mozilla.org",
type: "theme",
version: "1.4",
repositoryStatus: 9999,
icons: {}

Просмотреть файл

@ -152,6 +152,7 @@ const REPOSITORY_ADDONS = [{
repositoryStatus: 9
}, {
id: ADDON_IDS[2],
type: "theme",
name: "Repo Add-on 3",
version: "2.3",
iconURL: BASE_URL + "/repo/3/icon.png",