зеркало из https://github.com/mozilla/gecko-dev.git
merge fx-team to mozilla-central a=merge
This commit is contained in:
Коммит
cde42d544d
|
@ -656,9 +656,9 @@ loop.conversation = (function(mozL10n) {
|
|||
dispatcher: dispatcher,
|
||||
mozLoop: navigator.mozLoop
|
||||
});
|
||||
var conversationStore = new loop.store.ConversationStore({}, {
|
||||
var conversationStore = new loop.store.ConversationStore(dispatcher, {
|
||||
client: client,
|
||||
dispatcher: dispatcher,
|
||||
mozLoop: navigator.mozLoop,
|
||||
sdkDriver: sdkDriver
|
||||
});
|
||||
var activeRoomStore = new loop.store.ActiveRoomStore(dispatcher, {
|
||||
|
|
|
@ -656,9 +656,9 @@ loop.conversation = (function(mozL10n) {
|
|||
dispatcher: dispatcher,
|
||||
mozLoop: navigator.mozLoop
|
||||
});
|
||||
var conversationStore = new loop.store.ConversationStore({}, {
|
||||
var conversationStore = new loop.store.ConversationStore(dispatcher, {
|
||||
client: client,
|
||||
dispatcher: dispatcher,
|
||||
mozLoop: navigator.mozLoop,
|
||||
sdkDriver: sdkDriver
|
||||
});
|
||||
var activeRoomStore = new loop.store.ActiveRoomStore(dispatcher, {
|
||||
|
|
|
@ -224,7 +224,7 @@ loop.conversationViews = (function(mozL10n) {
|
|||
},
|
||||
|
||||
_onEmailLinkReceived: function() {
|
||||
var emailLink = this.props.store.get("emailLink");
|
||||
var emailLink = this.props.store.getStoreState("emailLink");
|
||||
var contactEmail = _getPreferredEmail(this.props.contact).value;
|
||||
sharedUtils.composeCallUrlEmail(emailLink, contactEmail);
|
||||
window.close();
|
||||
|
@ -428,7 +428,10 @@ loop.conversationViews = (function(mozL10n) {
|
|||
* the different views that need displaying.
|
||||
*/
|
||||
var OutgoingConversationView = React.createClass({displayName: 'OutgoingConversationView',
|
||||
mixins: [sharedMixins.AudioMixin],
|
||||
mixins: [
|
||||
sharedMixins.AudioMixin,
|
||||
Backbone.Events
|
||||
],
|
||||
|
||||
propTypes: {
|
||||
dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
|
||||
|
@ -438,12 +441,18 @@ loop.conversationViews = (function(mozL10n) {
|
|||
},
|
||||
|
||||
getInitialState: function() {
|
||||
return this.props.store.attributes;
|
||||
return this.props.store.getStoreState();
|
||||
},
|
||||
|
||||
componentWillMount: function() {
|
||||
this.props.store.on("change", function() {
|
||||
this.setState(this.props.store.attributes);
|
||||
this.listenTo(this.props.store, "change", function() {
|
||||
this.setState(this.props.store.getStoreState());
|
||||
}, this);
|
||||
},
|
||||
|
||||
componentWillUnmount: function() {
|
||||
this.stopListening(this.props.store, "change", function() {
|
||||
this.setState(this.props.store.getStoreState());
|
||||
}, this);
|
||||
},
|
||||
|
||||
|
|
|
@ -224,7 +224,7 @@ loop.conversationViews = (function(mozL10n) {
|
|||
},
|
||||
|
||||
_onEmailLinkReceived: function() {
|
||||
var emailLink = this.props.store.get("emailLink");
|
||||
var emailLink = this.props.store.getStoreState("emailLink");
|
||||
var contactEmail = _getPreferredEmail(this.props.contact).value;
|
||||
sharedUtils.composeCallUrlEmail(emailLink, contactEmail);
|
||||
window.close();
|
||||
|
@ -428,7 +428,10 @@ loop.conversationViews = (function(mozL10n) {
|
|||
* the different views that need displaying.
|
||||
*/
|
||||
var OutgoingConversationView = React.createClass({
|
||||
mixins: [sharedMixins.AudioMixin],
|
||||
mixins: [
|
||||
sharedMixins.AudioMixin,
|
||||
Backbone.Events
|
||||
],
|
||||
|
||||
propTypes: {
|
||||
dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
|
||||
|
@ -438,12 +441,18 @@ loop.conversationViews = (function(mozL10n) {
|
|||
},
|
||||
|
||||
getInitialState: function() {
|
||||
return this.props.store.attributes;
|
||||
return this.props.store.getStoreState();
|
||||
},
|
||||
|
||||
componentWillMount: function() {
|
||||
this.props.store.on("change", function() {
|
||||
this.setState(this.props.store.attributes);
|
||||
this.listenTo(this.props.store, "change", function() {
|
||||
this.setState(this.props.store.getStoreState());
|
||||
}, this);
|
||||
},
|
||||
|
||||
componentWillUnmount: function() {
|
||||
this.stopListening(this.props.store, "change", function() {
|
||||
this.setState(this.props.store.getStoreState());
|
||||
}, this);
|
||||
},
|
||||
|
||||
|
|
|
@ -162,15 +162,20 @@ loop.roomViews = (function(mozL10n) {
|
|||
*/
|
||||
window.addEventListener('orientationchange', this.updateVideoContainer);
|
||||
window.addEventListener('resize', this.updateVideoContainer);
|
||||
},
|
||||
|
||||
componentWillUpdate: function(nextProps, nextState) {
|
||||
// The SDK needs to know about the configuration and the elements to use
|
||||
// for display. So the best way seems to pass the information here - ideally
|
||||
// the sdk wouldn't need to know this, but we can't change that.
|
||||
this.props.dispatcher.dispatch(new sharedActions.SetupStreamElements({
|
||||
publisherConfig: this._getPublisherConfig(),
|
||||
getLocalElementFunc: this._getElement.bind(this, ".local"),
|
||||
getRemoteElementFunc: this._getElement.bind(this, ".remote")
|
||||
}));
|
||||
if (this.state.roomState !== ROOM_STATES.MEDIA_WAIT &&
|
||||
nextState.roomState === ROOM_STATES.MEDIA_WAIT) {
|
||||
this.props.dispatcher.dispatch(new sharedActions.SetupStreamElements({
|
||||
publisherConfig: this._getPublisherConfig(),
|
||||
getLocalElementFunc: this._getElement.bind(this, ".local"),
|
||||
getRemoteElementFunc: this._getElement.bind(this, ".remote")
|
||||
}));
|
||||
}
|
||||
},
|
||||
|
||||
_getPublisherConfig: function() {
|
||||
|
|
|
@ -162,15 +162,20 @@ loop.roomViews = (function(mozL10n) {
|
|||
*/
|
||||
window.addEventListener('orientationchange', this.updateVideoContainer);
|
||||
window.addEventListener('resize', this.updateVideoContainer);
|
||||
},
|
||||
|
||||
componentWillUpdate: function(nextProps, nextState) {
|
||||
// The SDK needs to know about the configuration and the elements to use
|
||||
// for display. So the best way seems to pass the information here - ideally
|
||||
// the sdk wouldn't need to know this, but we can't change that.
|
||||
this.props.dispatcher.dispatch(new sharedActions.SetupStreamElements({
|
||||
publisherConfig: this._getPublisherConfig(),
|
||||
getLocalElementFunc: this._getElement.bind(this, ".local"),
|
||||
getRemoteElementFunc: this._getElement.bind(this, ".remote")
|
||||
}));
|
||||
if (this.state.roomState !== ROOM_STATES.MEDIA_WAIT &&
|
||||
nextState.roomState === ROOM_STATES.MEDIA_WAIT) {
|
||||
this.props.dispatcher.dispatch(new sharedActions.SetupStreamElements({
|
||||
publisherConfig: this._getPublisherConfig(),
|
||||
getLocalElementFunc: this._getElement.bind(this, ".local"),
|
||||
getRemoteElementFunc: this._getElement.bind(this, ".remote")
|
||||
}));
|
||||
}
|
||||
},
|
||||
|
||||
_getPublisherConfig: function() {
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
var loop = loop || {};
|
||||
loop.store = loop.store || {};
|
||||
|
||||
loop.store.ConversationStore = (function() {
|
||||
(function() {
|
||||
var sharedActions = loop.shared.actions;
|
||||
var CALL_TYPES = loop.shared.utils.CALL_TYPES;
|
||||
|
||||
|
@ -53,81 +53,84 @@ loop.store.ConversationStore = (function() {
|
|||
TERMINATED: "cs-terminated"
|
||||
};
|
||||
|
||||
// XXX this needs to migrate to use loop.store.createStore
|
||||
var ConversationStore = Backbone.Model.extend({
|
||||
defaults: {
|
||||
// The id of the window. Currently used for getting the window id.
|
||||
windowId: undefined,
|
||||
// The current state of the call
|
||||
callState: CALL_STATES.INIT,
|
||||
// The reason if a call was terminated
|
||||
callStateReason: undefined,
|
||||
// The error information, if there was a failure
|
||||
error: undefined,
|
||||
// True if the call is outgoing, false if not, undefined if unknown
|
||||
outgoing: undefined,
|
||||
// The contact being called for outgoing calls
|
||||
contact: undefined,
|
||||
// The call type for the call.
|
||||
// XXX Don't hard-code, this comes from the data in bug 1072323
|
||||
callType: CALL_TYPES.AUDIO_VIDEO,
|
||||
/**
|
||||
* Conversation store.
|
||||
*
|
||||
* @param {loop.Dispatcher} dispatcher The dispatcher for dispatching actions
|
||||
* and registering to consume actions.
|
||||
* @param {Object} options Options object:
|
||||
* - {client} client The client object.
|
||||
* - {mozLoop} mozLoop The MozLoop API object.
|
||||
* - {loop.OTSdkDriver} loop.OTSdkDriver The SDK Driver
|
||||
*/
|
||||
loop.store.ConversationStore = loop.store.createStore({
|
||||
// Further actions are registered in setupWindowData when
|
||||
// we know what window type this is.
|
||||
actions: [
|
||||
"setupWindowData"
|
||||
],
|
||||
|
||||
// Call Connection information
|
||||
// The call id from the loop-server
|
||||
callId: undefined,
|
||||
// The caller id of the contacting side
|
||||
callerId: undefined,
|
||||
// The connection progress url to connect the websocket
|
||||
progressURL: undefined,
|
||||
// The websocket token that allows connection to the progress url
|
||||
websocketToken: undefined,
|
||||
// SDK API key
|
||||
apiKey: undefined,
|
||||
// SDK session ID
|
||||
sessionId: undefined,
|
||||
// SDK session token
|
||||
sessionToken: undefined,
|
||||
// If the audio is muted
|
||||
audioMuted: false,
|
||||
// If the video is muted
|
||||
videoMuted: false
|
||||
getInitialStoreState: function() {
|
||||
return {
|
||||
// The id of the window. Currently used for getting the window id.
|
||||
windowId: undefined,
|
||||
// The current state of the call
|
||||
callState: CALL_STATES.INIT,
|
||||
// The reason if a call was terminated
|
||||
callStateReason: undefined,
|
||||
// True if the call is outgoing, false if not, undefined if unknown
|
||||
outgoing: undefined,
|
||||
// The contact being called for outgoing calls
|
||||
contact: undefined,
|
||||
// The call type for the call.
|
||||
// XXX Don't hard-code, this comes from the data in bug 1072323
|
||||
callType: CALL_TYPES.AUDIO_VIDEO,
|
||||
// A link for emailing once obtained from the server
|
||||
emailLink: undefined,
|
||||
|
||||
// Call Connection information
|
||||
// The call id from the loop-server
|
||||
callId: undefined,
|
||||
// The caller id of the contacting side
|
||||
callerId: undefined,
|
||||
// The connection progress url to connect the websocket
|
||||
progressURL: undefined,
|
||||
// The websocket token that allows connection to the progress url
|
||||
websocketToken: undefined,
|
||||
// SDK API key
|
||||
apiKey: undefined,
|
||||
// SDK session ID
|
||||
sessionId: undefined,
|
||||
// SDK session token
|
||||
sessionToken: undefined,
|
||||
// If the audio is muted
|
||||
audioMuted: false,
|
||||
// If the video is muted
|
||||
videoMuted: false
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* Handles initialisation of the store.
|
||||
*
|
||||
* Options:
|
||||
* - {loop.Dispatcher} dispatcher The dispatcher for dispatching actions and
|
||||
* registering to consume actions.
|
||||
* - {Object} client A client object for communicating with the server.
|
||||
*
|
||||
* @param {Object} attributes Attributes object.
|
||||
* @param {Object} options Options object.
|
||||
*/
|
||||
initialize: function(attributes, options) {
|
||||
initialize: function(options) {
|
||||
options = options || {};
|
||||
|
||||
if (!options.dispatcher) {
|
||||
throw new Error("Missing option dispatcher");
|
||||
}
|
||||
if (!options.client) {
|
||||
throw new Error("Missing option client");
|
||||
}
|
||||
if (!options.sdkDriver) {
|
||||
throw new Error("Missing option sdkDriver");
|
||||
}
|
||||
if (!options.mozLoop) {
|
||||
throw new Error("Missing option mozLoop");
|
||||
}
|
||||
|
||||
this.client = options.client;
|
||||
this.dispatcher = options.dispatcher;
|
||||
this.sdkDriver = options.sdkDriver;
|
||||
|
||||
// XXX Further actions are registered in setupWindowData when
|
||||
// we know what window type this is. At some stage, we might want to
|
||||
// consider store mixins or some alternative which means the stores
|
||||
// would only be created when we want them.
|
||||
this.dispatcher.register(this, [
|
||||
"setupWindowData"
|
||||
]);
|
||||
this.mozLoop = options.mozLoop;
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -138,7 +141,7 @@ loop.store.ConversationStore = (function() {
|
|||
*/
|
||||
connectionFailure: function(actionData) {
|
||||
this._endSession();
|
||||
this.set({
|
||||
this.setStoreState({
|
||||
callState: CALL_STATES.TERMINATED,
|
||||
callStateReason: actionData.reason
|
||||
});
|
||||
|
@ -151,34 +154,35 @@ loop.store.ConversationStore = (function() {
|
|||
* @param {sharedActions.ConnectionProgress} actionData The action data.
|
||||
*/
|
||||
connectionProgress: function(actionData) {
|
||||
var callState = this.get("callState");
|
||||
var state = this.getStoreState();
|
||||
|
||||
switch(actionData.wsState) {
|
||||
case WS_STATES.INIT: {
|
||||
if (callState === CALL_STATES.GATHER) {
|
||||
this.set({callState: CALL_STATES.CONNECTING});
|
||||
if (state.callState === CALL_STATES.GATHER) {
|
||||
this.setStoreState({callState: CALL_STATES.CONNECTING});
|
||||
}
|
||||
break;
|
||||
}
|
||||
case WS_STATES.ALERTING: {
|
||||
this.set({callState: CALL_STATES.ALERTING});
|
||||
this.setStoreState({callState: CALL_STATES.ALERTING});
|
||||
break;
|
||||
}
|
||||
case WS_STATES.CONNECTING: {
|
||||
this.sdkDriver.connectSession({
|
||||
apiKey: this.get("apiKey"),
|
||||
sessionId: this.get("sessionId"),
|
||||
sessionToken: this.get("sessionToken")
|
||||
apiKey: state.apiKey,
|
||||
sessionId: state.sessionId,
|
||||
sessionToken: state.sessionToken
|
||||
});
|
||||
navigator.mozLoop.addConversationContext(this.get("windowId"),
|
||||
this.get("sessionId"),
|
||||
this.get("callId"));
|
||||
this.set({callState: CALL_STATES.ONGOING});
|
||||
this.mozLoop.addConversationContext(
|
||||
state.windowId,
|
||||
state.sessionId,
|
||||
state.callId);
|
||||
this.setStoreState({callState: CALL_STATES.ONGOING});
|
||||
break;
|
||||
}
|
||||
case WS_STATES.HALF_CONNECTED:
|
||||
case WS_STATES.CONNECTED: {
|
||||
this.set({callState: CALL_STATES.ONGOING});
|
||||
this.setStoreState({callState: CALL_STATES.ONGOING});
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
|
@ -209,7 +213,7 @@ loop.store.ConversationStore = (function() {
|
|||
"fetchEmailLink"
|
||||
]);
|
||||
|
||||
this.set({
|
||||
this.setStoreState({
|
||||
contact: actionData.contact,
|
||||
outgoing: windowType === "outgoing",
|
||||
windowId: actionData.windowId,
|
||||
|
@ -218,7 +222,7 @@ loop.store.ConversationStore = (function() {
|
|||
videoMuted: actionData.callType === CALL_TYPES.AUDIO_ONLY
|
||||
});
|
||||
|
||||
if (this.get("outgoing")) {
|
||||
if (this.getStoreState("outgoing")) {
|
||||
this._setupOutgoingCall();
|
||||
} // XXX Else, other types aren't supported yet.
|
||||
},
|
||||
|
@ -231,7 +235,7 @@ loop.store.ConversationStore = (function() {
|
|||
* @param {sharedActions.ConnectCall} actionData The action data.
|
||||
*/
|
||||
connectCall: function(actionData) {
|
||||
this.set(actionData.sessionData);
|
||||
this.setStoreState(actionData.sessionData);
|
||||
this._connectWebSocket();
|
||||
},
|
||||
|
||||
|
@ -245,7 +249,7 @@ loop.store.ConversationStore = (function() {
|
|||
}
|
||||
|
||||
this._endSession();
|
||||
this.set({callState: CALL_STATES.FINISHED});
|
||||
this.setStoreState({callState: CALL_STATES.FINISHED});
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -259,9 +263,9 @@ loop.store.ConversationStore = (function() {
|
|||
// If the peer hungup, we end normally, otherwise
|
||||
// we treat this as a call failure.
|
||||
if (actionData.peerHungup) {
|
||||
this.set({callState: CALL_STATES.FINISHED});
|
||||
this.setStoreState({callState: CALL_STATES.FINISHED});
|
||||
} else {
|
||||
this.set({
|
||||
this.setStoreState({
|
||||
callState: CALL_STATES.TERMINATED,
|
||||
callStateReason: "peerNetworkDisconnected"
|
||||
});
|
||||
|
@ -272,7 +276,7 @@ loop.store.ConversationStore = (function() {
|
|||
* Cancels a call
|
||||
*/
|
||||
cancelCall: function() {
|
||||
var callState = this.get("callState");
|
||||
var callState = this.getStoreState("callState");
|
||||
if (this._websocket &&
|
||||
(callState === CALL_STATES.CONNECTING ||
|
||||
callState === CALL_STATES.ALERTING)) {
|
||||
|
@ -281,21 +285,21 @@ loop.store.ConversationStore = (function() {
|
|||
}
|
||||
|
||||
this._endSession();
|
||||
this.set({callState: CALL_STATES.CLOSE});
|
||||
this.setStoreState({callState: CALL_STATES.CLOSE});
|
||||
},
|
||||
|
||||
/**
|
||||
* Retries a call
|
||||
*/
|
||||
retryCall: function() {
|
||||
var callState = this.get("callState");
|
||||
var callState = this.getStoreState("callState");
|
||||
if (callState !== CALL_STATES.TERMINATED) {
|
||||
console.error("Unexpected retry in state", callState);
|
||||
return;
|
||||
}
|
||||
|
||||
this.set({callState: CALL_STATES.GATHER});
|
||||
if (this.get("outgoing")) {
|
||||
this.setStoreState({callState: CALL_STATES.GATHER});
|
||||
if (this.getStoreState("outgoing")) {
|
||||
this._setupOutgoingCall();
|
||||
}
|
||||
},
|
||||
|
@ -313,8 +317,9 @@ loop.store.ConversationStore = (function() {
|
|||
* @param {sharedActions.setMute} actionData The mute state for the stream type.
|
||||
*/
|
||||
setMute: function(actionData) {
|
||||
var muteType = actionData.type + "Muted";
|
||||
this.set(muteType, !actionData.enabled);
|
||||
var newState = {};
|
||||
newState[actionData.type + "Muted"] = !actionData.enabled;
|
||||
this.setStoreState(newState);
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -329,7 +334,7 @@ loop.store.ConversationStore = (function() {
|
|||
this.trigger("error:emailLink");
|
||||
return;
|
||||
}
|
||||
this.set("emailLink", callUrlData.callUrl);
|
||||
this.setStoreState({"emailLink": callUrlData.callUrl});
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
|
@ -339,9 +344,9 @@ loop.store.ConversationStore = (function() {
|
|||
*/
|
||||
_setupOutgoingCall: function() {
|
||||
var contactAddresses = [];
|
||||
var contact = this.get("contact");
|
||||
var contact = this.getStoreState("contact");
|
||||
|
||||
navigator.mozLoop.calls.setCallInProgress(this.get("windowId"));
|
||||
this.mozLoop.calls.setCallInProgress(this.getStoreState("windowId"));
|
||||
|
||||
function appendContactValues(property, strip) {
|
||||
if (contact.hasOwnProperty(property)) {
|
||||
|
@ -362,7 +367,7 @@ loop.store.ConversationStore = (function() {
|
|||
appendContactValues("tel", true);
|
||||
|
||||
this.client.setupOutgoingCall(contactAddresses,
|
||||
this.get("callType"),
|
||||
this.getStoreState("callType"),
|
||||
function(err, result) {
|
||||
if (err) {
|
||||
console.error("Failed to get outgoing call data", err);
|
||||
|
@ -385,9 +390,9 @@ loop.store.ConversationStore = (function() {
|
|||
*/
|
||||
_connectWebSocket: function() {
|
||||
this._websocket = new loop.CallConnectionWebSocket({
|
||||
url: this.get("progressURL"),
|
||||
callId: this.get("callId"),
|
||||
websocketToken: this.get("websocketToken")
|
||||
url: this.getStoreState("progressURL"),
|
||||
callId: this.getStoreState("callId"),
|
||||
websocketToken: this.getStoreState("websocketToken")
|
||||
});
|
||||
|
||||
this._websocket.promiseConnect().then(
|
||||
|
@ -422,7 +427,8 @@ loop.store.ConversationStore = (function() {
|
|||
delete this._websocket;
|
||||
}
|
||||
|
||||
navigator.mozLoop.calls.clearCallInProgress(this.get("windowId"));
|
||||
this.mozLoop.calls.clearCallInProgress(
|
||||
this.getStoreState("windowId"));
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -450,6 +456,4 @@ loop.store.ConversationStore = (function() {
|
|||
this.dispatcher.dispatch(action);
|
||||
}
|
||||
});
|
||||
|
||||
return ConversationStore;
|
||||
})();
|
||||
|
|
|
@ -127,6 +127,10 @@ loop.standaloneRoomViews = (function(mozL10n) {
|
|||
React.DOM.div({className: "room-inner-info-area"},
|
||||
React.DOM.p({className: "failed-room-message"},
|
||||
this._getFailureString()
|
||||
),
|
||||
React.DOM.button({className: "btn btn-join btn-info",
|
||||
onClick: this.props.joinRoom},
|
||||
mozL10n.get("retry_call_button")
|
||||
)
|
||||
)
|
||||
);
|
||||
|
|
|
@ -128,6 +128,10 @@ loop.standaloneRoomViews = (function(mozL10n) {
|
|||
<p className="failed-room-message">
|
||||
{this._getFailureString()}
|
||||
</p>
|
||||
<button className="btn btn-join btn-info"
|
||||
onClick={this.props.joinRoom}>
|
||||
{mozL10n.get("retry_call_button")}
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ describe("loop.conversationViews", function () {
|
|||
|
||||
var sharedUtils = loop.shared.utils;
|
||||
var sandbox, oldTitle, view, dispatcher, contact, fakeAudioXHR;
|
||||
var fakeMozLoop;
|
||||
|
||||
var CALL_STATES = loop.store.CALL_STATES;
|
||||
|
||||
|
@ -43,7 +44,7 @@ describe("loop.conversationViews", function () {
|
|||
onload: null
|
||||
};
|
||||
|
||||
navigator.mozLoop = {
|
||||
fakeMozLoop = navigator.mozLoop = {
|
||||
getLoopPref: sinon.stub().returns("http://fakeurl"),
|
||||
composeEmail: sinon.spy(),
|
||||
get appVersionInfo() {
|
||||
|
@ -242,9 +243,9 @@ describe("loop.conversationViews", function () {
|
|||
}
|
||||
|
||||
beforeEach(function() {
|
||||
store = new loop.store.ConversationStore({}, {
|
||||
dispatcher: dispatcher,
|
||||
store = new loop.store.ConversationStore(dispatcher, {
|
||||
client: {},
|
||||
mozLoop: navigator.mozLoop,
|
||||
sdkDriver: {}
|
||||
});
|
||||
fakeAudio = {
|
||||
|
@ -306,7 +307,7 @@ describe("loop.conversationViews", function () {
|
|||
it("should compose an email once the email link is received", function() {
|
||||
var composeCallUrlEmail = sandbox.stub(sharedUtils, "composeCallUrlEmail");
|
||||
view = mountTestComponent();
|
||||
store.set("emailLink", "http://fake.invalid/");
|
||||
store.setStoreState({emailLink: "http://fake.invalid/"});
|
||||
|
||||
sinon.assert.calledOnce(composeCallUrlEmail);
|
||||
sinon.assert.calledWithExactly(composeCallUrlEmail,
|
||||
|
@ -318,7 +319,7 @@ describe("loop.conversationViews", function () {
|
|||
sandbox.stub(window, "close");
|
||||
view = mountTestComponent();
|
||||
|
||||
store.set("emailLink", "http://fake.invalid/");
|
||||
store.setStoreState({emailLink: "http://fake.invalid/"});
|
||||
|
||||
sinon.assert.calledOnce(window.close);
|
||||
});
|
||||
|
@ -457,9 +458,9 @@ describe("loop.conversationViews", function () {
|
|||
}
|
||||
|
||||
beforeEach(function() {
|
||||
store = new loop.store.ConversationStore({}, {
|
||||
dispatcher: dispatcher,
|
||||
store = new loop.store.ConversationStore(dispatcher, {
|
||||
client: {},
|
||||
mozLoop: fakeMozLoop,
|
||||
sdkDriver: {}
|
||||
});
|
||||
feedbackStore = new loop.store.FeedbackStore(dispatcher, {
|
||||
|
@ -469,7 +470,7 @@ describe("loop.conversationViews", function () {
|
|||
|
||||
it("should render the CallFailedView when the call state is 'terminated'",
|
||||
function() {
|
||||
store.set({callState: CALL_STATES.TERMINATED});
|
||||
store.setStoreState({callState: CALL_STATES.TERMINATED});
|
||||
|
||||
view = mountTestComponent();
|
||||
|
||||
|
@ -479,7 +480,7 @@ describe("loop.conversationViews", function () {
|
|||
|
||||
it("should render the PendingConversationView when the call state is 'gather'",
|
||||
function() {
|
||||
store.set({
|
||||
store.setStoreState({
|
||||
callState: CALL_STATES.GATHER,
|
||||
contact: contact
|
||||
});
|
||||
|
@ -492,7 +493,7 @@ describe("loop.conversationViews", function () {
|
|||
|
||||
it("should render the OngoingConversationView when the call state is 'ongoing'",
|
||||
function() {
|
||||
store.set({callState: CALL_STATES.ONGOING});
|
||||
store.setStoreState({callState: CALL_STATES.ONGOING});
|
||||
|
||||
view = mountTestComponent();
|
||||
|
||||
|
@ -502,7 +503,7 @@ describe("loop.conversationViews", function () {
|
|||
|
||||
it("should render the FeedbackView when the call state is 'finished'",
|
||||
function() {
|
||||
store.set({callState: CALL_STATES.FINISHED});
|
||||
store.setStoreState({callState: CALL_STATES.FINISHED});
|
||||
|
||||
view = mountTestComponent();
|
||||
|
||||
|
@ -519,7 +520,7 @@ describe("loop.conversationViews", function () {
|
|||
};
|
||||
sandbox.stub(window, "Audio").returns(fakeAudio);
|
||||
|
||||
store.set({callState: CALL_STATES.FINISHED});
|
||||
store.setStoreState({callState: CALL_STATES.FINISHED});
|
||||
|
||||
view = mountTestComponent();
|
||||
|
||||
|
@ -528,7 +529,7 @@ describe("loop.conversationViews", function () {
|
|||
|
||||
it("should update the rendered views when the state is changed.",
|
||||
function() {
|
||||
store.set({
|
||||
store.setStoreState({
|
||||
callState: CALL_STATES.GATHER,
|
||||
contact: contact
|
||||
});
|
||||
|
@ -538,7 +539,7 @@ describe("loop.conversationViews", function () {
|
|||
TestUtils.findRenderedComponentWithType(view,
|
||||
loop.conversationViews.PendingConversationView);
|
||||
|
||||
store.set({callState: CALL_STATES.TERMINATED});
|
||||
store.setStoreState({callState: CALL_STATES.TERMINATED});
|
||||
|
||||
TestUtils.findRenderedComponentWithType(view,
|
||||
loop.conversationViews.CallFailedView);
|
||||
|
|
|
@ -160,20 +160,22 @@ describe("loop.conversation", function() {
|
|||
sdk: {}
|
||||
});
|
||||
dispatcher = new loop.Dispatcher();
|
||||
conversationStore = new loop.store.ConversationStore({
|
||||
contact: {
|
||||
name: [ "Mr Smith" ],
|
||||
email: [{
|
||||
type: "home",
|
||||
value: "fakeEmail",
|
||||
pref: true
|
||||
}]
|
||||
}
|
||||
}, {
|
||||
client: client,
|
||||
dispatcher: dispatcher,
|
||||
sdkDriver: {}
|
||||
});
|
||||
conversationStore = new loop.store.ConversationStore(
|
||||
dispatcher, {
|
||||
client: client,
|
||||
mozLoop: navigator.mozLoop,
|
||||
sdkDriver: {}
|
||||
});
|
||||
|
||||
conversationStore.setStoreState({contact: {
|
||||
name: [ "Mr Smith" ],
|
||||
email: [{
|
||||
type: "home",
|
||||
value: "fakeEmail",
|
||||
pref: true
|
||||
}]
|
||||
}});
|
||||
|
||||
roomStore = new loop.store.RoomStore(dispatcher, {
|
||||
mozLoop: navigator.mozLoop,
|
||||
});
|
||||
|
|
|
@ -41,7 +41,6 @@
|
|||
<!-- App scripts -->
|
||||
<script src="../../content/shared/js/utils.js"></script>
|
||||
<script src="../../content/shared/js/feedbackApiClient.js"></script>
|
||||
<script src="../../content/shared/js/conversationStore.js"></script>
|
||||
<script src="../../content/shared/js/models.js"></script>
|
||||
<script src="../../content/shared/js/mixins.js"></script>
|
||||
<script src="../../content/shared/js/views.js"></script>
|
||||
|
@ -51,6 +50,7 @@
|
|||
<script src="../../content/shared/js/dispatcher.js"></script>
|
||||
<script src="../../content/shared/js/otSdkDriver.js"></script>
|
||||
<script src="../../content/shared/js/store.js"></script>
|
||||
<script src="../../content/shared/js/conversationStore.js"></script>
|
||||
<script src="../../content/shared/js/roomStore.js"></script>
|
||||
<script src="../../content/shared/js/activeRoomStore.js"></script>
|
||||
<script src="../../content/shared/js/feedbackStore.js"></script>
|
||||
|
|
|
@ -206,15 +206,6 @@ describe("loop.roomViews", function () {
|
|||
}));
|
||||
}
|
||||
|
||||
it("should dispatch a setupStreamElements action when the view is created",
|
||||
function() {
|
||||
view = mountTestComponent();
|
||||
|
||||
sinon.assert.calledOnce(dispatcher.dispatch);
|
||||
sinon.assert.calledWithMatch(dispatcher.dispatch,
|
||||
sinon.match.hasOwn("name", "setupStreamElements"));
|
||||
});
|
||||
|
||||
it("should dispatch a setMute action when the audio mute button is pressed",
|
||||
function() {
|
||||
view = mountTestComponent();
|
||||
|
@ -271,6 +262,44 @@ describe("loop.roomViews", function () {
|
|||
expect(muteBtn.classList.contains("muted")).eql(true);
|
||||
});
|
||||
|
||||
describe("#componentWillUpdate", function() {
|
||||
function expectActionDispatched(view) {
|
||||
sinon.assert.calledOnce(dispatcher.dispatch);
|
||||
sinon.assert.calledWithExactly(dispatcher.dispatch,
|
||||
sinon.match.instanceOf(sharedActions.SetupStreamElements));
|
||||
sinon.assert.calledWithExactly(dispatcher.dispatch,
|
||||
sinon.match(function(value) {
|
||||
return value.getLocalElementFunc() ===
|
||||
view.getDOMNode().querySelector(".local");
|
||||
}));
|
||||
sinon.assert.calledWithExactly(dispatcher.dispatch,
|
||||
sinon.match(function(value) {
|
||||
return value.getRemoteElementFunc() ===
|
||||
view.getDOMNode().querySelector(".remote");
|
||||
}));
|
||||
}
|
||||
|
||||
it("should dispatch a `SetupStreamElements` action when the MEDIA_WAIT state " +
|
||||
"is entered", function() {
|
||||
activeRoomStore.setStoreState({roomState: ROOM_STATES.READY});
|
||||
var view = mountTestComponent();
|
||||
|
||||
activeRoomStore.setStoreState({roomState: ROOM_STATES.MEDIA_WAIT});
|
||||
|
||||
expectActionDispatched(view);
|
||||
});
|
||||
|
||||
it("should dispatch a `SetupStreamElements` action on MEDIA_WAIT state is " +
|
||||
"re-entered", function() {
|
||||
activeRoomStore.setStoreState({roomState: ROOM_STATES.ENDED});
|
||||
var view = mountTestComponent();
|
||||
|
||||
activeRoomStore.setStoreState({roomState: ROOM_STATES.MEDIA_WAIT});
|
||||
|
||||
expectActionDispatched(view);
|
||||
});
|
||||
});
|
||||
|
||||
describe("#render", function() {
|
||||
it("should set document.title to store.serverData.roomName", function() {
|
||||
mountTestComponent();
|
||||
|
|
|
@ -11,7 +11,7 @@ describe("loop.store.ConversationStore", function () {
|
|||
var sharedActions = loop.shared.actions;
|
||||
var sharedUtils = loop.shared.utils;
|
||||
var sandbox, dispatcher, client, store, fakeSessionData, sdkDriver;
|
||||
var contact;
|
||||
var contact, fakeMozLoop;
|
||||
var connectPromise, resolveConnectPromise, rejectConnectPromise;
|
||||
var wsCancelSpy, wsCloseSpy, wsMediaUpSpy, fakeWebsocket;
|
||||
|
||||
|
@ -36,7 +36,7 @@ describe("loop.store.ConversationStore", function () {
|
|||
}]
|
||||
};
|
||||
|
||||
navigator.mozLoop = {
|
||||
fakeMozLoop = {
|
||||
getLoopPref: sandbox.stub(),
|
||||
addConversationContext: sandbox.stub(),
|
||||
calls: {
|
||||
|
@ -65,9 +65,9 @@ describe("loop.store.ConversationStore", function () {
|
|||
mediaUp: wsMediaUpSpy
|
||||
};
|
||||
|
||||
store = new loop.store.ConversationStore({}, {
|
||||
store = new loop.store.ConversationStore(dispatcher, {
|
||||
client: client,
|
||||
dispatcher: dispatcher,
|
||||
mozLoop: fakeMozLoop,
|
||||
sdkDriver: sdkDriver
|
||||
});
|
||||
fakeSessionData = {
|
||||
|
@ -99,19 +99,9 @@ describe("loop.store.ConversationStore", function () {
|
|||
});
|
||||
|
||||
describe("#initialize", function() {
|
||||
it("should throw an error if the dispatcher is missing", function() {
|
||||
expect(function() {
|
||||
new loop.store.ConversationStore({}, {
|
||||
client: client,
|
||||
sdkDriver: sdkDriver
|
||||
});
|
||||
}).to.Throw(/dispatcher/);
|
||||
});
|
||||
|
||||
it("should throw an error if the client is missing", function() {
|
||||
expect(function() {
|
||||
new loop.store.ConversationStore({}, {
|
||||
dispatcher: dispatcher,
|
||||
new loop.store.ConversationStore(dispatcher, {
|
||||
sdkDriver: sdkDriver
|
||||
});
|
||||
}).to.Throw(/client/);
|
||||
|
@ -119,18 +109,26 @@ describe("loop.store.ConversationStore", function () {
|
|||
|
||||
it("should throw an error if the sdkDriver is missing", function() {
|
||||
expect(function() {
|
||||
new loop.store.ConversationStore({}, {
|
||||
client: client,
|
||||
dispatcher: dispatcher
|
||||
new loop.store.ConversationStore(dispatcher, {
|
||||
client: client
|
||||
});
|
||||
}).to.Throw(/sdkDriver/);
|
||||
});
|
||||
|
||||
it("should throw an error if mozLoop is missing", function() {
|
||||
expect(function() {
|
||||
new loop.store.ConversationStore(dispatcher, {
|
||||
sdkDriver: sdkDriver,
|
||||
client: client
|
||||
});
|
||||
}).to.Throw(/mozLoop/);
|
||||
});
|
||||
});
|
||||
|
||||
describe("#connectionFailure", function() {
|
||||
beforeEach(function() {
|
||||
store._websocket = fakeWebsocket;
|
||||
store.set({windowId: "42"});
|
||||
store.setStoreState({windowId: "42"});
|
||||
});
|
||||
|
||||
it("should disconnect the session", function() {
|
||||
|
@ -148,71 +146,71 @@ describe("loop.store.ConversationStore", function () {
|
|||
});
|
||||
|
||||
it("should set the state to 'terminated'", function() {
|
||||
store.set({callState: CALL_STATES.ALERTING});
|
||||
store.setStoreState({callState: CALL_STATES.ALERTING});
|
||||
|
||||
store.connectionFailure(
|
||||
new sharedActions.ConnectionFailure({reason: "fake"}));
|
||||
|
||||
expect(store.get("callState")).eql(CALL_STATES.TERMINATED);
|
||||
expect(store.get("callStateReason")).eql("fake");
|
||||
expect(store.getStoreState("callState")).eql(CALL_STATES.TERMINATED);
|
||||
expect(store.getStoreState("callStateReason")).eql("fake");
|
||||
});
|
||||
|
||||
it("should release mozLoop callsData", function() {
|
||||
store.connectionFailure(
|
||||
new sharedActions.ConnectionFailure({reason: "fake"}));
|
||||
|
||||
sinon.assert.calledOnce(navigator.mozLoop.calls.clearCallInProgress);
|
||||
sinon.assert.calledOnce(fakeMozLoop.calls.clearCallInProgress);
|
||||
sinon.assert.calledWithExactly(
|
||||
navigator.mozLoop.calls.clearCallInProgress, "42");
|
||||
fakeMozLoop.calls.clearCallInProgress, "42");
|
||||
});
|
||||
});
|
||||
|
||||
describe("#connectionProgress", function() {
|
||||
describe("progress: init", function() {
|
||||
it("should change the state from 'gather' to 'connecting'", function() {
|
||||
store.set({callState: CALL_STATES.GATHER});
|
||||
store.setStoreState({callState: CALL_STATES.GATHER});
|
||||
|
||||
store.connectionProgress(
|
||||
new sharedActions.ConnectionProgress({wsState: WS_STATES.INIT}));
|
||||
|
||||
expect(store.get("callState")).eql(CALL_STATES.CONNECTING);
|
||||
expect(store.getStoreState("callState")).eql(CALL_STATES.CONNECTING);
|
||||
});
|
||||
});
|
||||
|
||||
describe("progress: alerting", function() {
|
||||
it("should change the state from 'gather' to 'alerting'", function() {
|
||||
store.set({callState: CALL_STATES.GATHER});
|
||||
store.setStoreState({callState: CALL_STATES.GATHER});
|
||||
|
||||
store.connectionProgress(
|
||||
new sharedActions.ConnectionProgress({wsState: WS_STATES.ALERTING}));
|
||||
|
||||
expect(store.get("callState")).eql(CALL_STATES.ALERTING);
|
||||
expect(store.getStoreState("callState")).eql(CALL_STATES.ALERTING);
|
||||
});
|
||||
|
||||
it("should change the state from 'init' to 'alerting'", function() {
|
||||
store.set({callState: CALL_STATES.INIT});
|
||||
store.setStoreState({callState: CALL_STATES.INIT});
|
||||
|
||||
store.connectionProgress(
|
||||
new sharedActions.ConnectionProgress({wsState: WS_STATES.ALERTING}));
|
||||
|
||||
expect(store.get("callState")).eql(CALL_STATES.ALERTING);
|
||||
expect(store.getStoreState("callState")).eql(CALL_STATES.ALERTING);
|
||||
});
|
||||
});
|
||||
|
||||
describe("progress: connecting", function() {
|
||||
beforeEach(function() {
|
||||
store.set({callState: CALL_STATES.ALERTING});
|
||||
store.setStoreState({callState: CALL_STATES.ALERTING});
|
||||
});
|
||||
|
||||
it("should change the state to 'ongoing'", function() {
|
||||
store.connectionProgress(
|
||||
new sharedActions.ConnectionProgress({wsState: WS_STATES.CONNECTING}));
|
||||
|
||||
expect(store.get("callState")).eql(CALL_STATES.ONGOING);
|
||||
expect(store.getStoreState("callState")).eql(CALL_STATES.ONGOING);
|
||||
});
|
||||
|
||||
it("should connect the session", function() {
|
||||
store.set(fakeSessionData);
|
||||
store.setStoreState(fakeSessionData);
|
||||
|
||||
store.connectionProgress(
|
||||
new sharedActions.ConnectionProgress({wsState: WS_STATES.CONNECTING}));
|
||||
|
@ -226,13 +224,13 @@ describe("loop.store.ConversationStore", function () {
|
|||
});
|
||||
|
||||
it("should call mozLoop.addConversationContext", function() {
|
||||
store.set(fakeSessionData);
|
||||
store.setStoreState(fakeSessionData);
|
||||
|
||||
store.connectionProgress(
|
||||
new sharedActions.ConnectionProgress({wsState: WS_STATES.CONNECTING}));
|
||||
|
||||
sinon.assert.calledOnce(navigator.mozLoop.addConversationContext);
|
||||
sinon.assert.calledWithExactly(navigator.mozLoop.addConversationContext,
|
||||
sinon.assert.calledOnce(fakeMozLoop.addConversationContext);
|
||||
sinon.assert.calledWithExactly(fakeMozLoop.addConversationContext,
|
||||
"28", "321456", "142536");
|
||||
});
|
||||
});
|
||||
|
@ -242,7 +240,7 @@ describe("loop.store.ConversationStore", function () {
|
|||
var fakeSetupWindowData;
|
||||
|
||||
beforeEach(function() {
|
||||
store.set({callState: CALL_STATES.INIT});
|
||||
store.setStoreState({callState: CALL_STATES.INIT});
|
||||
fakeSetupWindowData = {
|
||||
windowId: "123456",
|
||||
type: "outgoing",
|
||||
|
@ -255,23 +253,24 @@ describe("loop.store.ConversationStore", function () {
|
|||
dispatcher.dispatch(
|
||||
new sharedActions.SetupWindowData(fakeSetupWindowData));
|
||||
|
||||
expect(store.get("callState")).eql(CALL_STATES.GATHER);
|
||||
expect(store.getStoreState("callState")).eql(CALL_STATES.GATHER);
|
||||
});
|
||||
|
||||
it("should save the basic call information", function() {
|
||||
dispatcher.dispatch(
|
||||
new sharedActions.SetupWindowData(fakeSetupWindowData));
|
||||
|
||||
expect(store.get("windowId")).eql("123456");
|
||||
expect(store.get("outgoing")).eql(true);
|
||||
expect(store.getStoreState("windowId")).eql("123456");
|
||||
expect(store.getStoreState("outgoing")).eql(true);
|
||||
});
|
||||
|
||||
it("should save the basic information from the mozLoop api", function() {
|
||||
dispatcher.dispatch(
|
||||
new sharedActions.SetupWindowData(fakeSetupWindowData));
|
||||
|
||||
expect(store.get("contact")).eql(contact);
|
||||
expect(store.get("callType")).eql(sharedUtils.CALL_TYPES.AUDIO_VIDEO);
|
||||
expect(store.getStoreState("contact")).eql(contact);
|
||||
expect(store.getStoreState("callType"))
|
||||
.eql(sharedUtils.CALL_TYPES.AUDIO_VIDEO);
|
||||
});
|
||||
|
||||
describe("outgoing calls", function() {
|
||||
|
@ -402,12 +401,12 @@ describe("loop.store.ConversationStore", function () {
|
|||
store.connectCall(
|
||||
new sharedActions.ConnectCall({sessionData: fakeSessionData}));
|
||||
|
||||
expect(store.get("apiKey")).eql("fakeKey");
|
||||
expect(store.get("callId")).eql("142536");
|
||||
expect(store.get("sessionId")).eql("321456");
|
||||
expect(store.get("sessionToken")).eql("341256");
|
||||
expect(store.get("websocketToken")).eql("543216");
|
||||
expect(store.get("progressURL")).eql("fakeURL");
|
||||
expect(store.getStoreState("apiKey")).eql("fakeKey");
|
||||
expect(store.getStoreState("callId")).eql("142536");
|
||||
expect(store.getStoreState("sessionId")).eql("321456");
|
||||
expect(store.getStoreState("sessionToken")).eql("341256");
|
||||
expect(store.getStoreState("websocketToken")).eql("543216");
|
||||
expect(store.getStoreState("progressURL")).eql("fakeURL");
|
||||
});
|
||||
|
||||
it("should initialize the websocket", function() {
|
||||
|
@ -488,8 +487,8 @@ describe("loop.store.ConversationStore", function () {
|
|||
mediaFail: wsMediaFailSpy,
|
||||
close: wsCloseSpy
|
||||
};
|
||||
store.set({callState: CALL_STATES.ONGOING});
|
||||
store.set({windowId: "42"});
|
||||
store.setStoreState({callState: CALL_STATES.ONGOING});
|
||||
store.setStoreState({windowId: "42"});
|
||||
});
|
||||
|
||||
it("should disconnect the session", function() {
|
||||
|
@ -513,15 +512,15 @@ describe("loop.store.ConversationStore", function () {
|
|||
it("should set the callState to finished", function() {
|
||||
store.hangupCall(new sharedActions.HangupCall());
|
||||
|
||||
expect(store.get("callState")).eql(CALL_STATES.FINISHED);
|
||||
expect(store.getStoreState("callState")).eql(CALL_STATES.FINISHED);
|
||||
});
|
||||
|
||||
it("should release mozLoop callsData", function() {
|
||||
store.hangupCall(new sharedActions.HangupCall());
|
||||
|
||||
sinon.assert.calledOnce(navigator.mozLoop.calls.clearCallInProgress);
|
||||
sinon.assert.calledOnce(fakeMozLoop.calls.clearCallInProgress);
|
||||
sinon.assert.calledWithExactly(
|
||||
navigator.mozLoop.calls.clearCallInProgress, "42");
|
||||
fakeMozLoop.calls.clearCallInProgress, "42");
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -535,8 +534,8 @@ describe("loop.store.ConversationStore", function () {
|
|||
mediaFail: wsMediaFailSpy,
|
||||
close: wsCloseSpy
|
||||
};
|
||||
store.set({callState: CALL_STATES.ONGOING});
|
||||
store.set({windowId: "42"});
|
||||
store.setStoreState({callState: CALL_STATES.ONGOING});
|
||||
store.setStoreState({windowId: "42"});
|
||||
});
|
||||
|
||||
it("should disconnect the session", function() {
|
||||
|
@ -560,9 +559,9 @@ describe("loop.store.ConversationStore", function () {
|
|||
peerHungup: true
|
||||
}));
|
||||
|
||||
sinon.assert.calledOnce(navigator.mozLoop.calls.clearCallInProgress);
|
||||
sinon.assert.calledOnce(fakeMozLoop.calls.clearCallInProgress);
|
||||
sinon.assert.calledWithExactly(
|
||||
navigator.mozLoop.calls.clearCallInProgress, "42");
|
||||
fakeMozLoop.calls.clearCallInProgress, "42");
|
||||
});
|
||||
|
||||
it("should set the callState to finished if the peer hungup", function() {
|
||||
|
@ -570,7 +569,7 @@ describe("loop.store.ConversationStore", function () {
|
|||
peerHungup: true
|
||||
}));
|
||||
|
||||
expect(store.get("callState")).eql(CALL_STATES.FINISHED);
|
||||
expect(store.getStoreState("callState")).eql(CALL_STATES.FINISHED);
|
||||
});
|
||||
|
||||
it("should set the callState to terminated if the peer was disconnected" +
|
||||
|
@ -579,7 +578,7 @@ describe("loop.store.ConversationStore", function () {
|
|||
peerHungup: false
|
||||
}));
|
||||
|
||||
expect(store.get("callState")).eql(CALL_STATES.TERMINATED);
|
||||
expect(store.getStoreState("callState")).eql(CALL_STATES.TERMINATED);
|
||||
});
|
||||
|
||||
it("should set the reason to peerNetworkDisconnected if the peer was" +
|
||||
|
@ -588,7 +587,8 @@ describe("loop.store.ConversationStore", function () {
|
|||
peerHungup: false
|
||||
}));
|
||||
|
||||
expect(store.get("callStateReason")).eql("peerNetworkDisconnected");
|
||||
expect(store.getStoreState("callStateReason"))
|
||||
.eql("peerNetworkDisconnected");
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -596,8 +596,8 @@ describe("loop.store.ConversationStore", function () {
|
|||
beforeEach(function() {
|
||||
store._websocket = fakeWebsocket;
|
||||
|
||||
store.set({callState: CALL_STATES.CONNECTING});
|
||||
store.set({windowId: "42"});
|
||||
store.setStoreState({callState: CALL_STATES.CONNECTING});
|
||||
store.setStoreState({windowId: "42"});
|
||||
});
|
||||
|
||||
it("should disconnect the session", function() {
|
||||
|
@ -621,37 +621,38 @@ describe("loop.store.ConversationStore", function () {
|
|||
it("should set the state to close if the call is connecting", function() {
|
||||
store.cancelCall(new sharedActions.CancelCall());
|
||||
|
||||
expect(store.get("callState")).eql(CALL_STATES.CLOSE);
|
||||
expect(store.getStoreState("callState")).eql(CALL_STATES.CLOSE);
|
||||
});
|
||||
|
||||
it("should set the state to close if the call has terminated already", function() {
|
||||
store.set({callState: CALL_STATES.TERMINATED});
|
||||
store.setStoreState({callState: CALL_STATES.TERMINATED});
|
||||
|
||||
store.cancelCall(new sharedActions.CancelCall());
|
||||
|
||||
expect(store.get("callState")).eql(CALL_STATES.CLOSE);
|
||||
expect(store.getStoreState("callState")).eql(CALL_STATES.CLOSE);
|
||||
});
|
||||
|
||||
it("should release mozLoop callsData", function() {
|
||||
store.cancelCall(new sharedActions.CancelCall());
|
||||
|
||||
sinon.assert.calledOnce(navigator.mozLoop.calls.clearCallInProgress);
|
||||
sinon.assert.calledOnce(fakeMozLoop.calls.clearCallInProgress);
|
||||
sinon.assert.calledWithExactly(
|
||||
navigator.mozLoop.calls.clearCallInProgress, "42");
|
||||
fakeMozLoop.calls.clearCallInProgress, "42");
|
||||
});
|
||||
});
|
||||
|
||||
describe("#retryCall", function() {
|
||||
it("should set the state to gather", function() {
|
||||
store.set({callState: CALL_STATES.TERMINATED});
|
||||
store.setStoreState({callState: CALL_STATES.TERMINATED});
|
||||
|
||||
store.retryCall(new sharedActions.RetryCall());
|
||||
|
||||
expect(store.get("callState")).eql(CALL_STATES.GATHER);
|
||||
expect(store.getStoreState("callState"))
|
||||
.eql(CALL_STATES.GATHER);
|
||||
});
|
||||
|
||||
it("should request the outgoing call data", function() {
|
||||
store.set({
|
||||
store.setStoreState({
|
||||
callState: CALL_STATES.TERMINATED,
|
||||
outgoing: true,
|
||||
callType: sharedUtils.CALL_TYPES.AUDIO_VIDEO,
|
||||
|
@ -678,25 +679,25 @@ describe("loop.store.ConversationStore", function () {
|
|||
|
||||
describe("#setMute", function() {
|
||||
it("should save the mute state for the audio stream", function() {
|
||||
store.set({"audioMuted": false});
|
||||
store.setStoreState({"audioMuted": false});
|
||||
|
||||
dispatcher.dispatch(new sharedActions.SetMute({
|
||||
type: "audio",
|
||||
enabled: true
|
||||
}));
|
||||
|
||||
expect(store.get("audioMuted")).eql(false);
|
||||
expect(store.getStoreState("audioMuted")).eql(false);
|
||||
});
|
||||
|
||||
it("should save the mute state for the video stream", function() {
|
||||
store.set({"videoMuted": true});
|
||||
store.setStoreState({"videoMuted": true});
|
||||
|
||||
dispatcher.dispatch(new sharedActions.SetMute({
|
||||
type: "video",
|
||||
enabled: false
|
||||
}));
|
||||
|
||||
expect(store.get("videoMuted")).eql(true);
|
||||
expect(store.getStoreState("videoMuted")).eql(true);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -715,7 +716,7 @@ describe("loop.store.ConversationStore", function () {
|
|||
};
|
||||
store.fetchEmailLink(new sharedActions.FetchEmailLink());
|
||||
|
||||
expect(store.get("emailLink")).eql("http://fake.invalid/");
|
||||
expect(store.getStoreState("emailLink")).eql("http://fake.invalid/");
|
||||
});
|
||||
|
||||
it("should trigger an error:emailLink event in case of failure",
|
||||
|
|
|
@ -203,6 +203,14 @@ describe("loop.standaloneRoomViews", function() {
|
|||
expect(view.getDOMNode().querySelector(".failed-room-message"))
|
||||
.not.eql(null);
|
||||
});
|
||||
|
||||
it("should display a retry button",
|
||||
function() {
|
||||
activeRoomStore.setStoreState({roomState: ROOM_STATES.FAILED});
|
||||
|
||||
expect(view.getDOMNode().querySelector(".btn-info"))
|
||||
.not.eql(null);
|
||||
});
|
||||
});
|
||||
|
||||
describe("Join button", function() {
|
||||
|
|
|
@ -8333,9 +8333,6 @@ Parser<ParseHandler>::accumulateTelemetry()
|
|||
JSContext* cx = context->maybeJSContext();
|
||||
if (!cx)
|
||||
return;
|
||||
JSAccumulateTelemetryDataCallback cb = cx->runtime()->telemetryCallback;
|
||||
if (!cb)
|
||||
return;
|
||||
const char* filename = getFilename();
|
||||
if (!filename)
|
||||
return;
|
||||
|
@ -8361,17 +8358,17 @@ Parser<ParseHandler>::accumulateTelemetry()
|
|||
|
||||
// Call back into Firefox's Telemetry reporter.
|
||||
if (sawDeprecatedForEach)
|
||||
(*cb)(JS_TELEMETRY_DEPRECATED_LANGUAGE_EXTENSIONS_IN_CONTENT, DeprecatedForEach);
|
||||
cx->runtime()->addTelemetry(JS_TELEMETRY_DEPRECATED_LANGUAGE_EXTENSIONS_IN_CONTENT, DeprecatedForEach);
|
||||
if (sawDeprecatedDestructuringForIn)
|
||||
(*cb)(JS_TELEMETRY_DEPRECATED_LANGUAGE_EXTENSIONS_IN_CONTENT, DeprecatedDestructuringForIn);
|
||||
cx->runtime()->addTelemetry(JS_TELEMETRY_DEPRECATED_LANGUAGE_EXTENSIONS_IN_CONTENT, DeprecatedDestructuringForIn);
|
||||
if (sawDeprecatedLegacyGenerator)
|
||||
(*cb)(JS_TELEMETRY_DEPRECATED_LANGUAGE_EXTENSIONS_IN_CONTENT, DeprecatedLegacyGenerator);
|
||||
cx->runtime()->addTelemetry(JS_TELEMETRY_DEPRECATED_LANGUAGE_EXTENSIONS_IN_CONTENT, DeprecatedLegacyGenerator);
|
||||
if (sawDeprecatedExpressionClosure)
|
||||
(*cb)(JS_TELEMETRY_DEPRECATED_LANGUAGE_EXTENSIONS_IN_CONTENT, DeprecatedExpressionClosure);
|
||||
cx->runtime()->addTelemetry(JS_TELEMETRY_DEPRECATED_LANGUAGE_EXTENSIONS_IN_CONTENT, DeprecatedExpressionClosure);
|
||||
if (sawDeprecatedLetBlock)
|
||||
(*cb)(JS_TELEMETRY_DEPRECATED_LANGUAGE_EXTENSIONS_IN_CONTENT, DeprecatedLetBlock);
|
||||
cx->runtime()->addTelemetry(JS_TELEMETRY_DEPRECATED_LANGUAGE_EXTENSIONS_IN_CONTENT, DeprecatedLetBlock);
|
||||
if (sawDeprecatedLetExpression)
|
||||
(*cb)(JS_TELEMETRY_DEPRECATED_LANGUAGE_EXTENSIONS_IN_CONTENT, DeprecatedLetExpression);
|
||||
cx->runtime()->addTelemetry(JS_TELEMETRY_DEPRECATED_LANGUAGE_EXTENSIONS_IN_CONTENT, DeprecatedLetExpression);
|
||||
}
|
||||
|
||||
template class Parser<FullParseHandler>;
|
||||
|
|
|
@ -749,28 +749,26 @@ Statistics::endGC()
|
|||
for (int i = 0; i < PHASE_LIMIT; i++)
|
||||
phaseTotals[i] += phaseTimes[i];
|
||||
|
||||
if (JSAccumulateTelemetryDataCallback cb = runtime->telemetryCallback) {
|
||||
int64_t total, longest;
|
||||
gcDuration(&total, &longest);
|
||||
int64_t total, longest;
|
||||
gcDuration(&total, &longest);
|
||||
|
||||
int64_t sccTotal, sccLongest;
|
||||
sccDurations(&sccTotal, &sccLongest);
|
||||
int64_t sccTotal, sccLongest;
|
||||
sccDurations(&sccTotal, &sccLongest);
|
||||
|
||||
(*cb)(JS_TELEMETRY_GC_IS_COMPARTMENTAL, !zoneStats.isCollectingAllZones());
|
||||
(*cb)(JS_TELEMETRY_GC_MS, t(total));
|
||||
(*cb)(JS_TELEMETRY_GC_MAX_PAUSE_MS, t(longest));
|
||||
(*cb)(JS_TELEMETRY_GC_MARK_MS, t(phaseTimes[PHASE_MARK]));
|
||||
(*cb)(JS_TELEMETRY_GC_SWEEP_MS, t(phaseTimes[PHASE_SWEEP]));
|
||||
(*cb)(JS_TELEMETRY_GC_MARK_ROOTS_MS, t(phaseTimes[PHASE_MARK_ROOTS]));
|
||||
(*cb)(JS_TELEMETRY_GC_MARK_GRAY_MS, t(phaseTimes[PHASE_SWEEP_MARK_GRAY]));
|
||||
(*cb)(JS_TELEMETRY_GC_NON_INCREMENTAL, !!nonincrementalReason);
|
||||
(*cb)(JS_TELEMETRY_GC_INCREMENTAL_DISABLED, !runtime->gc.isIncrementalGCAllowed());
|
||||
(*cb)(JS_TELEMETRY_GC_SCC_SWEEP_TOTAL_MS, t(sccTotal));
|
||||
(*cb)(JS_TELEMETRY_GC_SCC_SWEEP_MAX_PAUSE_MS, t(sccLongest));
|
||||
|
||||
double mmu50 = computeMMU(50 * PRMJ_USEC_PER_MSEC);
|
||||
(*cb)(JS_TELEMETRY_GC_MMU_50, mmu50 * 100);
|
||||
}
|
||||
runtime->addTelemetry(JS_TELEMETRY_GC_IS_COMPARTMENTAL, !zoneStats.isCollectingAllZones());
|
||||
runtime->addTelemetry(JS_TELEMETRY_GC_MS, t(total));
|
||||
runtime->addTelemetry(JS_TELEMETRY_GC_MAX_PAUSE_MS, t(longest));
|
||||
runtime->addTelemetry(JS_TELEMETRY_GC_MARK_MS, t(phaseTimes[PHASE_MARK]));
|
||||
runtime->addTelemetry(JS_TELEMETRY_GC_SWEEP_MS, t(phaseTimes[PHASE_SWEEP]));
|
||||
runtime->addTelemetry(JS_TELEMETRY_GC_MARK_ROOTS_MS, t(phaseTimes[PHASE_MARK_ROOTS]));
|
||||
runtime->addTelemetry(JS_TELEMETRY_GC_MARK_GRAY_MS, t(phaseTimes[PHASE_SWEEP_MARK_GRAY]));
|
||||
runtime->addTelemetry(JS_TELEMETRY_GC_NON_INCREMENTAL, !!nonincrementalReason);
|
||||
runtime->addTelemetry(JS_TELEMETRY_GC_INCREMENTAL_DISABLED, !runtime->gc.isIncrementalGCAllowed());
|
||||
runtime->addTelemetry(JS_TELEMETRY_GC_SCC_SWEEP_TOTAL_MS, t(sccTotal));
|
||||
runtime->addTelemetry(JS_TELEMETRY_GC_SCC_SWEEP_MAX_PAUSE_MS, t(sccLongest));
|
||||
|
||||
double mmu50 = computeMMU(50 * PRMJ_USEC_PER_MSEC);
|
||||
runtime->addTelemetry(JS_TELEMETRY_GC_MMU_50, mmu50 * 100);
|
||||
|
||||
if (fp)
|
||||
printStats();
|
||||
|
@ -795,8 +793,7 @@ Statistics::beginSlice(const ZoneGCStats &zoneStats, JSGCInvocationKind gckind,
|
|||
if (!slices.append(data))
|
||||
CrashAtUnhandlableOOM("Failed to allocate statistics slice.");
|
||||
|
||||
if (JSAccumulateTelemetryDataCallback cb = runtime->telemetryCallback)
|
||||
(*cb)(JS_TELEMETRY_GC_REASON, reason);
|
||||
runtime->addTelemetry(JS_TELEMETRY_GC_REASON, reason);
|
||||
|
||||
// Slice callbacks should only fire for the outermost level
|
||||
if (++gcDepth == 1) {
|
||||
|
@ -813,10 +810,8 @@ Statistics::endSlice()
|
|||
slices.back().end = PRMJ_Now();
|
||||
slices.back().endFaults = GetPageFaultCount();
|
||||
|
||||
if (JSAccumulateTelemetryDataCallback cb = runtime->telemetryCallback) {
|
||||
(*cb)(JS_TELEMETRY_GC_SLICE_MS, t(slices.back().end - slices.back().start));
|
||||
(*cb)(JS_TELEMETRY_GC_RESET, !!slices.back().resetReason);
|
||||
}
|
||||
runtime->addTelemetry(JS_TELEMETRY_GC_SLICE_MS, t(slices.back().end - slices.back().start));
|
||||
runtime->addTelemetry(JS_TELEMETRY_GC_RESET, !!slices.back().resetReason);
|
||||
|
||||
bool last = runtime->gc.state() == gc::NO_INCREMENTAL;
|
||||
if (last)
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "jsfun.h"
|
||||
#include "jsnum.h"
|
||||
#include "jsobj.h"
|
||||
#include "jsprf.h"
|
||||
#include "jsscript.h"
|
||||
#include "jstypes.h"
|
||||
#include "jsutil.h"
|
||||
|
@ -713,8 +714,31 @@ ErrorReport::init(JSContext *cx, HandleValue exn)
|
|||
if (exn.isObject()) {
|
||||
exnObject = &exn.toObject();
|
||||
reportp = js_ErrorFromException(cx, exnObject);
|
||||
}
|
||||
|
||||
JSCompartment *comp = exnObject->compartment();
|
||||
JSAddonId *addonId = comp->addonId;
|
||||
if (addonId) {
|
||||
UniqueChars addonIdChars(JS_EncodeString(cx, addonId));
|
||||
|
||||
const char *filename = nullptr;
|
||||
|
||||
if (reportp && reportp->filename) {
|
||||
filename = strrchr(reportp->filename, '/');
|
||||
if (filename)
|
||||
filename++;
|
||||
}
|
||||
if (!filename) {
|
||||
filename = "FILE_NOT_FOUND";
|
||||
}
|
||||
char histogramKey[64];
|
||||
JS_snprintf(histogramKey, sizeof(histogramKey),
|
||||
"%s %s %u",
|
||||
addonIdChars.get(),
|
||||
filename,
|
||||
(reportp ? reportp->lineno : 0) );
|
||||
cx->runtime()->addTelemetry(JS_TELEMETRY_ADDON_EXCEPTIONS, 1, histogramKey);
|
||||
}
|
||||
}
|
||||
// Be careful not to invoke ToString if we've already successfully extracted
|
||||
// an error report, since the exception might be wrapped in a security
|
||||
// wrapper, and ToString-ing it might throw.
|
||||
|
|
|
@ -681,7 +681,7 @@ js::StringToLinearStringSlow(JSContext *cx, JSString *str)
|
|||
JS_FRIEND_API(void)
|
||||
JS_SetAccumulateTelemetryCallback(JSRuntime *rt, JSAccumulateTelemetryDataCallback callback)
|
||||
{
|
||||
rt->telemetryCallback = callback;
|
||||
rt->setTelemetryCallback(rt, callback);
|
||||
}
|
||||
|
||||
JS_FRIEND_API(JSObject *)
|
||||
|
|
|
@ -110,11 +110,12 @@ enum {
|
|||
JS_TELEMETRY_GC_NON_INCREMENTAL,
|
||||
JS_TELEMETRY_GC_SCC_SWEEP_TOTAL_MS,
|
||||
JS_TELEMETRY_GC_SCC_SWEEP_MAX_PAUSE_MS,
|
||||
JS_TELEMETRY_DEPRECATED_LANGUAGE_EXTENSIONS_IN_CONTENT
|
||||
JS_TELEMETRY_DEPRECATED_LANGUAGE_EXTENSIONS_IN_CONTENT,
|
||||
JS_TELEMETRY_ADDON_EXCEPTIONS
|
||||
};
|
||||
|
||||
typedef void
|
||||
(* JSAccumulateTelemetryDataCallback)(int id, uint32_t sample);
|
||||
(*JSAccumulateTelemetryDataCallback)(int id, uint32_t sample, const char *key);
|
||||
|
||||
extern JS_FRIEND_API(void)
|
||||
JS_SetAccumulateTelemetryCallback(JSRuntime *rt, JSAccumulateTelemetryDataCallback callback);
|
||||
|
|
|
@ -139,6 +139,7 @@ JSRuntime::JSRuntime(JSRuntime *parentRuntime)
|
|||
parentRuntime(parentRuntime),
|
||||
interrupt_(false),
|
||||
interruptPar_(false),
|
||||
telemetryCallback(nullptr),
|
||||
handlingSignal(false),
|
||||
interruptCallback(nullptr),
|
||||
exclusiveAccessLock(nullptr),
|
||||
|
@ -196,7 +197,6 @@ JSRuntime::JSRuntime(JSRuntime *parentRuntime)
|
|||
DOMcallbacks(nullptr),
|
||||
destroyPrincipals(nullptr),
|
||||
structuredCloneCallbacks(nullptr),
|
||||
telemetryCallback(nullptr),
|
||||
errorReporter(nullptr),
|
||||
linkedAsmJSModules(nullptr),
|
||||
propertyRemovals(0),
|
||||
|
@ -458,6 +458,19 @@ JSRuntime::~JSRuntime()
|
|||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
JSRuntime::addTelemetry(int id, uint32_t sample, const char *key)
|
||||
{
|
||||
if (telemetryCallback)
|
||||
(*telemetryCallback)(id, sample, key);
|
||||
}
|
||||
|
||||
void
|
||||
JSRuntime::setTelemetryCallback(JSRuntime *rt, JSAccumulateTelemetryDataCallback callback)
|
||||
{
|
||||
rt->telemetryCallback = callback;
|
||||
}
|
||||
|
||||
void
|
||||
NewObjectCache::clearNurseryObjects(JSRuntime *rt)
|
||||
{
|
||||
|
|
|
@ -707,7 +707,16 @@ struct JSRuntime : public JS::shadow::Runtime,
|
|||
private:
|
||||
mozilla::Atomic<uint32_t, mozilla::Relaxed> interrupt_;
|
||||
mozilla::Atomic<uint32_t, mozilla::Relaxed> interruptPar_;
|
||||
|
||||
/* Call this to accumulate telemetry data. */
|
||||
JSAccumulateTelemetryDataCallback telemetryCallback;
|
||||
public:
|
||||
// Accumulates data for Firefox telemetry. |id| is the ID of a JS_TELEMETRY_*
|
||||
// histogram. |key| provides an additional key to identify the histogram.
|
||||
// |sample| is the data to add to the histogram.
|
||||
void addTelemetry(int id, uint32_t sample, const char *key = nullptr);
|
||||
|
||||
void setTelemetryCallback(JSRuntime *rt, JSAccumulateTelemetryDataCallback callback);
|
||||
|
||||
enum InterruptMode {
|
||||
RequestInterruptUrgent,
|
||||
|
@ -1090,9 +1099,6 @@ struct JSRuntime : public JS::shadow::Runtime,
|
|||
/* Structured data callbacks are runtime-wide. */
|
||||
const JSStructuredCloneCallbacks *structuredCloneCallbacks;
|
||||
|
||||
/* Call this to accumulate telemetry data. */
|
||||
JSAccumulateTelemetryDataCallback telemetryCallback;
|
||||
|
||||
/* Optional error reporter. */
|
||||
JSErrorReporter errorReporter;
|
||||
|
||||
|
|
|
@ -2963,7 +2963,7 @@ DiagnosticMemoryCallback(void *ptr, size_t size)
|
|||
#endif
|
||||
|
||||
static void
|
||||
AccumulateTelemetryCallback(int id, uint32_t sample)
|
||||
AccumulateTelemetryCallback(int id, uint32_t sample, const char *key)
|
||||
{
|
||||
switch (id) {
|
||||
case JS_TELEMETRY_GC_REASON:
|
||||
|
@ -3015,6 +3015,9 @@ AccumulateTelemetryCallback(int id, uint32_t sample)
|
|||
MOZ_ASSERT(sample <= 5);
|
||||
Telemetry::Accumulate(Telemetry::JS_DEPRECATED_LANGUAGE_EXTENSIONS_IN_CONTENT, sample);
|
||||
break;
|
||||
case JS_TELEMETRY_ADDON_EXCEPTIONS:
|
||||
Telemetry::Accumulate(Telemetry::JS_TELEMETRY_ADDON_EXCEPTIONS, nsDependentCString(key), sample);
|
||||
break;
|
||||
default:
|
||||
MOZ_ASSERT_UNREACHABLE("Unexpected JS_TELEMETRY id");
|
||||
}
|
||||
|
|
|
@ -157,7 +157,6 @@ public class BrowserContract {
|
|||
public static final String TAGS_FOLDER_GUID = "tags";
|
||||
public static final String TOOLBAR_FOLDER_GUID = "toolbar";
|
||||
public static final String UNFILED_FOLDER_GUID = "unfiled";
|
||||
public static final String READING_LIST_FOLDER_GUID = "readinglist";
|
||||
public static final String FAKE_DESKTOP_FOLDER_GUID = "desktop";
|
||||
public static final String PINNED_FOLDER_GUID = "pinned";
|
||||
|
||||
|
@ -342,53 +341,6 @@ public class BrowserContract {
|
|||
new String[] { _ID, DATASET_ID, URL, TITLE, DESCRIPTION, IMAGE_URL, FILTER };
|
||||
}
|
||||
|
||||
/*
|
||||
* Contains names and schema definitions for tables and views
|
||||
* no longer being used by current ContentProviders. These values are used
|
||||
* to make incremental updates to the schema during a database upgrade. Will be
|
||||
* removed with bug 947018.
|
||||
*/
|
||||
static final class Obsolete {
|
||||
public static final String TABLE_IMAGES = "images";
|
||||
public static final String VIEW_BOOKMARKS_WITH_IMAGES = "bookmarks_with_images";
|
||||
public static final String VIEW_HISTORY_WITH_IMAGES = "history_with_images";
|
||||
public static final String VIEW_COMBINED_WITH_IMAGES = "combined_with_images";
|
||||
|
||||
public static final class Images implements CommonColumns, SyncColumns {
|
||||
private Images() {}
|
||||
|
||||
public static final String URL = "url_key";
|
||||
public static final String FAVICON_URL = "favicon_url";
|
||||
public static final String FAVICON = "favicon";
|
||||
public static final String THUMBNAIL = "thumbnail";
|
||||
public static final String _ID = "_id";
|
||||
public static final String GUID = "guid";
|
||||
public static final String DATE_CREATED = "created";
|
||||
public static final String DATE_MODIFIED = "modified";
|
||||
public static final String IS_DELETED = "deleted";
|
||||
}
|
||||
|
||||
public static final class Combined {
|
||||
private Combined() {}
|
||||
|
||||
public static final String THUMBNAIL = "thumbnail";
|
||||
public static final String DISPLAY = "display";
|
||||
|
||||
public static final int DISPLAY_NORMAL = 0;
|
||||
public static final int DISPLAY_READER = 1;
|
||||
}
|
||||
|
||||
static final String TABLE_BOOKMARKS_JOIN_IMAGES = Bookmarks.TABLE_NAME + " LEFT OUTER JOIN " +
|
||||
Obsolete.TABLE_IMAGES + " ON " + Bookmarks.TABLE_NAME + "." + Bookmarks.URL + " = " +
|
||||
Obsolete.TABLE_IMAGES + "." + Obsolete.Images.URL;
|
||||
|
||||
static final String TABLE_HISTORY_JOIN_IMAGES = History.TABLE_NAME + " LEFT OUTER JOIN " +
|
||||
Obsolete.TABLE_IMAGES + " ON " + Bookmarks.TABLE_NAME + "." + History.URL + " = " +
|
||||
Obsolete.TABLE_IMAGES + "." + Obsolete.Images.URL;
|
||||
|
||||
static final String FAVICON_DB = "favicon_urls.db";
|
||||
}
|
||||
|
||||
@RobocopTarget
|
||||
public static final class ReadingListItems implements CommonColumns, URLColumns, SyncColumns {
|
||||
private ReadingListItems() {}
|
||||
|
|
|
@ -11,14 +11,12 @@ import java.util.List;
|
|||
import org.mozilla.gecko.R;
|
||||
import org.mozilla.gecko.db.BrowserContract.Bookmarks;
|
||||
import org.mozilla.gecko.db.BrowserContract.Combined;
|
||||
import org.mozilla.gecko.db.BrowserContract.FaviconColumns;
|
||||
import org.mozilla.gecko.db.BrowserContract.Favicons;
|
||||
import org.mozilla.gecko.db.BrowserContract.History;
|
||||
import org.mozilla.gecko.db.BrowserContract.Obsolete;
|
||||
import org.mozilla.gecko.db.BrowserContract.ReadingListItems;
|
||||
import org.mozilla.gecko.db.BrowserContract.SearchHistory;
|
||||
import org.mozilla.gecko.db.BrowserContract.Thumbnails;
|
||||
import org.mozilla.gecko.sync.Utils;
|
||||
import static org.mozilla.gecko.db.DBUtils.qualifyColumn;
|
||||
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
|
@ -61,7 +59,6 @@ final class BrowserDatabaseHelper extends SQLiteOpenHelper {
|
|||
|
||||
static final String TABLE_BOOKMARKS_TMP = TABLE_BOOKMARKS + "_tmp";
|
||||
static final String TABLE_HISTORY_TMP = TABLE_HISTORY + "_tmp";
|
||||
static final String TABLE_IMAGES_TMP = Obsolete.TABLE_IMAGES + "_tmp";
|
||||
|
||||
private static final String[] mobileIdColumns = new String[] { Bookmarks._ID };
|
||||
private static final String[] mobileIdSelectionArgs = new String[] { Bookmarks.MOBILE_FOLDER_GUID };
|
||||
|
@ -74,37 +71,6 @@ final class BrowserDatabaseHelper extends SQLiteOpenHelper {
|
|||
private void createBookmarksTable(SQLiteDatabase db) {
|
||||
debug("Creating " + TABLE_BOOKMARKS + " table");
|
||||
|
||||
db.execSQL("CREATE TABLE " + TABLE_BOOKMARKS + "(" +
|
||||
Bookmarks._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
|
||||
Bookmarks.TITLE + " TEXT," +
|
||||
Bookmarks.URL + " TEXT," +
|
||||
Bookmarks.TYPE + " INTEGER NOT NULL DEFAULT " + Bookmarks.TYPE_BOOKMARK + "," +
|
||||
Bookmarks.PARENT + " INTEGER," +
|
||||
Bookmarks.POSITION + " INTEGER NOT NULL," +
|
||||
Bookmarks.KEYWORD + " TEXT," +
|
||||
Bookmarks.DESCRIPTION + " TEXT," +
|
||||
Bookmarks.TAGS + " TEXT," +
|
||||
Bookmarks.DATE_CREATED + " INTEGER," +
|
||||
Bookmarks.DATE_MODIFIED + " INTEGER," +
|
||||
Bookmarks.GUID + " TEXT NOT NULL," +
|
||||
Bookmarks.IS_DELETED + " INTEGER NOT NULL DEFAULT 0, " +
|
||||
"FOREIGN KEY (" + Bookmarks.PARENT + ") REFERENCES " +
|
||||
TABLE_BOOKMARKS + "(" + Bookmarks._ID + ")" +
|
||||
");");
|
||||
|
||||
db.execSQL("CREATE INDEX bookmarks_url_index ON " + TABLE_BOOKMARKS + "("
|
||||
+ Bookmarks.URL + ")");
|
||||
db.execSQL("CREATE INDEX bookmarks_type_deleted_index ON " + TABLE_BOOKMARKS + "("
|
||||
+ Bookmarks.TYPE + ", " + Bookmarks.IS_DELETED + ")");
|
||||
db.execSQL("CREATE UNIQUE INDEX bookmarks_guid_index ON " + TABLE_BOOKMARKS + "("
|
||||
+ Bookmarks.GUID + ")");
|
||||
db.execSQL("CREATE INDEX bookmarks_modified_index ON " + TABLE_BOOKMARKS + "("
|
||||
+ Bookmarks.DATE_MODIFIED + ")");
|
||||
}
|
||||
|
||||
private void createBookmarksTableOn13(SQLiteDatabase db) {
|
||||
debug("Creating " + TABLE_BOOKMARKS + " table");
|
||||
|
||||
db.execSQL("CREATE TABLE " + TABLE_BOOKMARKS + "(" +
|
||||
Bookmarks._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
|
||||
Bookmarks.TITLE + " TEXT," +
|
||||
|
@ -135,30 +101,6 @@ final class BrowserDatabaseHelper extends SQLiteOpenHelper {
|
|||
}
|
||||
|
||||
private void createHistoryTable(SQLiteDatabase db) {
|
||||
debug("Creating " + TABLE_HISTORY + " table");
|
||||
db.execSQL("CREATE TABLE " + TABLE_HISTORY + "(" +
|
||||
History._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
|
||||
History.TITLE + " TEXT," +
|
||||
History.URL + " TEXT NOT NULL," +
|
||||
History.VISITS + " INTEGER NOT NULL DEFAULT 0," +
|
||||
History.DATE_LAST_VISITED + " INTEGER," +
|
||||
History.DATE_CREATED + " INTEGER," +
|
||||
History.DATE_MODIFIED + " INTEGER," +
|
||||
History.GUID + " TEXT NOT NULL," +
|
||||
History.IS_DELETED + " INTEGER NOT NULL DEFAULT 0" +
|
||||
");");
|
||||
|
||||
db.execSQL("CREATE INDEX history_url_index ON " + TABLE_HISTORY + "("
|
||||
+ History.URL + ")");
|
||||
db.execSQL("CREATE UNIQUE INDEX history_guid_index ON " + TABLE_HISTORY + "("
|
||||
+ History.GUID + ")");
|
||||
db.execSQL("CREATE INDEX history_modified_index ON " + TABLE_HISTORY + "("
|
||||
+ History.DATE_MODIFIED + ")");
|
||||
db.execSQL("CREATE INDEX history_visited_index ON " + TABLE_HISTORY + "("
|
||||
+ History.DATE_LAST_VISITED + ")");
|
||||
}
|
||||
|
||||
private void createHistoryTableOn13(SQLiteDatabase db) {
|
||||
debug("Creating " + TABLE_HISTORY + " table");
|
||||
db.execSQL("CREATE TABLE " + TABLE_HISTORY + "(" +
|
||||
History._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
|
||||
|
@ -173,36 +115,14 @@ final class BrowserDatabaseHelper extends SQLiteOpenHelper {
|
|||
History.IS_DELETED + " INTEGER NOT NULL DEFAULT 0" +
|
||||
");");
|
||||
|
||||
db.execSQL("CREATE INDEX history_url_index ON " + TABLE_HISTORY + "("
|
||||
+ History.URL + ")");
|
||||
db.execSQL("CREATE UNIQUE INDEX history_guid_index ON " + TABLE_HISTORY + "("
|
||||
+ History.GUID + ")");
|
||||
db.execSQL("CREATE INDEX history_modified_index ON " + TABLE_HISTORY + "("
|
||||
+ History.DATE_MODIFIED + ")");
|
||||
db.execSQL("CREATE INDEX history_visited_index ON " + TABLE_HISTORY + "("
|
||||
+ History.DATE_LAST_VISITED + ")");
|
||||
}
|
||||
|
||||
private void createImagesTable(SQLiteDatabase db) {
|
||||
debug("Creating " + Obsolete.TABLE_IMAGES + " table");
|
||||
db.execSQL("CREATE TABLE " + Obsolete.TABLE_IMAGES + " (" +
|
||||
Obsolete.Images._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
|
||||
Obsolete.Images.URL + " TEXT UNIQUE NOT NULL," +
|
||||
Obsolete.Images.FAVICON + " BLOB," +
|
||||
Obsolete.Images.FAVICON_URL + " TEXT," +
|
||||
Obsolete.Images.THUMBNAIL + " BLOB," +
|
||||
Obsolete.Images.DATE_CREATED + " INTEGER," +
|
||||
Obsolete.Images.DATE_MODIFIED + " INTEGER," +
|
||||
Obsolete.Images.GUID + " TEXT NOT NULL," +
|
||||
Obsolete.Images.IS_DELETED + " INTEGER NOT NULL DEFAULT 0" +
|
||||
");");
|
||||
|
||||
db.execSQL("CREATE INDEX images_url_index ON " + Obsolete.TABLE_IMAGES + "("
|
||||
+ Obsolete.Images.URL + ")");
|
||||
db.execSQL("CREATE UNIQUE INDEX images_guid_index ON " + Obsolete.TABLE_IMAGES + "("
|
||||
+ Obsolete.Images.GUID + ")");
|
||||
db.execSQL("CREATE INDEX images_modified_index ON " + Obsolete.TABLE_IMAGES + "("
|
||||
+ Obsolete.Images.DATE_MODIFIED + ")");
|
||||
db.execSQL("CREATE INDEX history_url_index ON " + TABLE_HISTORY + '('
|
||||
+ History.URL + ')');
|
||||
db.execSQL("CREATE UNIQUE INDEX history_guid_index ON " + TABLE_HISTORY + '('
|
||||
+ History.GUID + ')');
|
||||
db.execSQL("CREATE INDEX history_modified_index ON " + TABLE_HISTORY + '('
|
||||
+ History.DATE_MODIFIED + ')');
|
||||
db.execSQL("CREATE INDEX history_visited_index ON " + TABLE_HISTORY + '('
|
||||
+ History.DATE_LAST_VISITED + ')');
|
||||
}
|
||||
|
||||
private void createFaviconsTable(SQLiteDatabase db) {
|
||||
|
@ -233,15 +153,6 @@ final class BrowserDatabaseHelper extends SQLiteOpenHelper {
|
|||
+ Thumbnails.URL + ")");
|
||||
}
|
||||
|
||||
private void createBookmarksWithImagesView(SQLiteDatabase db) {
|
||||
debug("Creating " + Obsolete.VIEW_BOOKMARKS_WITH_IMAGES + " view");
|
||||
|
||||
db.execSQL("CREATE VIEW IF NOT EXISTS " + Obsolete.VIEW_BOOKMARKS_WITH_IMAGES + " AS " +
|
||||
"SELECT " + qualifyColumn(TABLE_BOOKMARKS, "*") +
|
||||
", " + Obsolete.Images.FAVICON + ", " + Obsolete.Images.THUMBNAIL + " FROM " +
|
||||
Obsolete.TABLE_BOOKMARKS_JOIN_IMAGES);
|
||||
}
|
||||
|
||||
private void createBookmarksWithFaviconsView(SQLiteDatabase db) {
|
||||
debug("Creating " + VIEW_BOOKMARKS_WITH_FAVICONS + " view");
|
||||
|
||||
|
@ -252,15 +163,6 @@ final class BrowserDatabaseHelper extends SQLiteOpenHelper {
|
|||
" FROM " + TABLE_BOOKMARKS_JOIN_FAVICONS);
|
||||
}
|
||||
|
||||
private void createHistoryWithImagesView(SQLiteDatabase db) {
|
||||
debug("Creating " + Obsolete.VIEW_HISTORY_WITH_IMAGES + " view");
|
||||
|
||||
db.execSQL("CREATE VIEW IF NOT EXISTS " + Obsolete.VIEW_HISTORY_WITH_IMAGES + " AS " +
|
||||
"SELECT " + qualifyColumn(TABLE_HISTORY, "*") +
|
||||
", " + Obsolete.Images.FAVICON + ", " + Obsolete.Images.THUMBNAIL + " FROM " +
|
||||
Obsolete.TABLE_HISTORY_JOIN_IMAGES);
|
||||
}
|
||||
|
||||
private void createHistoryWithFaviconsView(SQLiteDatabase db) {
|
||||
debug("Creating " + VIEW_HISTORY_WITH_FAVICONS + " view");
|
||||
|
||||
|
@ -271,363 +173,6 @@ final class BrowserDatabaseHelper extends SQLiteOpenHelper {
|
|||
" FROM " + TABLE_HISTORY_JOIN_FAVICONS);
|
||||
}
|
||||
|
||||
private void createCombinedWithImagesView(SQLiteDatabase db) {
|
||||
debug("Creating " + Obsolete.VIEW_COMBINED_WITH_IMAGES + " view");
|
||||
|
||||
db.execSQL("CREATE VIEW IF NOT EXISTS " + Obsolete.VIEW_COMBINED_WITH_IMAGES + " AS" +
|
||||
" SELECT " + Combined.BOOKMARK_ID + ", " +
|
||||
Combined.HISTORY_ID + ", " +
|
||||
// We need to return an _id column because CursorAdapter requires it for its
|
||||
// default implementation for the getItemId() method. However, since
|
||||
// we're not using this feature in the parts of the UI using this view,
|
||||
// we can just use 0 for all rows.
|
||||
"0 AS " + Combined._ID + ", " +
|
||||
Combined.URL + ", " +
|
||||
Combined.TITLE + ", " +
|
||||
Combined.VISITS + ", " +
|
||||
Combined.DATE_LAST_VISITED + ", " +
|
||||
qualifyColumn(Obsolete.TABLE_IMAGES, Obsolete.Images.FAVICON) + " AS " + Combined.FAVICON + ", " +
|
||||
qualifyColumn(Obsolete.TABLE_IMAGES, Obsolete.Images.THUMBNAIL) + " AS " + Obsolete.Combined.THUMBNAIL +
|
||||
" FROM (" +
|
||||
// Bookmarks without history.
|
||||
" SELECT " + qualifyColumn(TABLE_BOOKMARKS, Bookmarks._ID) + " AS " + Combined.BOOKMARK_ID + ", " +
|
||||
qualifyColumn(TABLE_BOOKMARKS, Bookmarks.URL) + " AS " + Combined.URL + ", " +
|
||||
qualifyColumn(TABLE_BOOKMARKS, Bookmarks.TITLE) + " AS " + Combined.TITLE + ", " +
|
||||
"-1 AS " + Combined.HISTORY_ID + ", " +
|
||||
"-1 AS " + Combined.VISITS + ", " +
|
||||
"-1 AS " + Combined.DATE_LAST_VISITED +
|
||||
" FROM " + TABLE_BOOKMARKS +
|
||||
" WHERE " + qualifyColumn(TABLE_BOOKMARKS, Bookmarks.TYPE) + " = " + Bookmarks.TYPE_BOOKMARK + " AND " +
|
||||
qualifyColumn(TABLE_BOOKMARKS, Bookmarks.IS_DELETED) + " = 0 AND " +
|
||||
qualifyColumn(TABLE_BOOKMARKS, Bookmarks.URL) +
|
||||
" NOT IN (SELECT " + History.URL + " FROM " + TABLE_HISTORY + ")" +
|
||||
" UNION ALL" +
|
||||
// History with and without bookmark.
|
||||
" SELECT " + qualifyColumn(TABLE_BOOKMARKS, Bookmarks._ID) + " AS " + Combined.BOOKMARK_ID + ", " +
|
||||
qualifyColumn(TABLE_HISTORY, History.URL) + " AS " + Combined.URL + ", " +
|
||||
// Prioritize bookmark titles over history titles, since the user may have
|
||||
// customized the title for a bookmark.
|
||||
"COALESCE(" + qualifyColumn(TABLE_BOOKMARKS, Bookmarks.TITLE) + ", " +
|
||||
qualifyColumn(TABLE_HISTORY, History.TITLE) +")" + " AS " + Combined.TITLE + ", " +
|
||||
qualifyColumn(TABLE_HISTORY, History._ID) + " AS " + Combined.HISTORY_ID + ", " +
|
||||
qualifyColumn(TABLE_HISTORY, History.VISITS) + " AS " + Combined.VISITS + ", " +
|
||||
qualifyColumn(TABLE_HISTORY, History.DATE_LAST_VISITED) + " AS " + Combined.DATE_LAST_VISITED +
|
||||
" FROM " + TABLE_HISTORY + " LEFT OUTER JOIN " + TABLE_BOOKMARKS +
|
||||
" ON " + qualifyColumn(TABLE_BOOKMARKS, Bookmarks.URL) + " = " + qualifyColumn(TABLE_HISTORY, History.URL) +
|
||||
" WHERE " + qualifyColumn(TABLE_HISTORY, History.URL) + " IS NOT NULL AND " +
|
||||
qualifyColumn(TABLE_HISTORY, History.IS_DELETED) + " = 0 AND (" +
|
||||
qualifyColumn(TABLE_BOOKMARKS, Bookmarks.TYPE) + " IS NULL OR " +
|
||||
qualifyColumn(TABLE_BOOKMARKS, Bookmarks.TYPE) + " = " + Bookmarks.TYPE_BOOKMARK + ")" +
|
||||
") LEFT OUTER JOIN " + Obsolete.TABLE_IMAGES +
|
||||
" ON " + Combined.URL + " = " + qualifyColumn(Obsolete.TABLE_IMAGES, Obsolete.Images.URL));
|
||||
}
|
||||
|
||||
private void createCombinedWithImagesViewOn9(SQLiteDatabase db) {
|
||||
debug("Creating " + Obsolete.VIEW_COMBINED_WITH_IMAGES + " view");
|
||||
|
||||
db.execSQL("CREATE VIEW IF NOT EXISTS " + Obsolete.VIEW_COMBINED_WITH_IMAGES + " AS" +
|
||||
" SELECT " + Combined.BOOKMARK_ID + ", " +
|
||||
Combined.HISTORY_ID + ", " +
|
||||
// We need to return an _id column because CursorAdapter requires it for its
|
||||
// default implementation for the getItemId() method. However, since
|
||||
// we're not using this feature in the parts of the UI using this view,
|
||||
// we can just use 0 for all rows.
|
||||
"0 AS " + Combined._ID + ", " +
|
||||
Combined.URL + ", " +
|
||||
Combined.TITLE + ", " +
|
||||
Combined.VISITS + ", " +
|
||||
Obsolete.Combined.DISPLAY + ", " +
|
||||
Combined.DATE_LAST_VISITED + ", " +
|
||||
qualifyColumn(Obsolete.TABLE_IMAGES, Obsolete.Images.FAVICON) + " AS " + Combined.FAVICON + ", " +
|
||||
qualifyColumn(Obsolete.TABLE_IMAGES, Obsolete.Images.THUMBNAIL) + " AS " + Obsolete.Combined.THUMBNAIL +
|
||||
" FROM (" +
|
||||
// Bookmarks without history.
|
||||
" SELECT " + qualifyColumn(TABLE_BOOKMARKS, Bookmarks._ID) + " AS " + Combined.BOOKMARK_ID + ", " +
|
||||
qualifyColumn(TABLE_BOOKMARKS, Bookmarks.URL) + " AS " + Combined.URL + ", " +
|
||||
qualifyColumn(TABLE_BOOKMARKS, Bookmarks.TITLE) + " AS " + Combined.TITLE + ", " +
|
||||
"CASE " + qualifyColumn(TABLE_BOOKMARKS, Bookmarks.PARENT) + " WHEN " +
|
||||
Bookmarks.FIXED_READING_LIST_ID + " THEN " + Obsolete.Combined.DISPLAY_READER + " ELSE " +
|
||||
Obsolete.Combined.DISPLAY_NORMAL + " END AS " + Obsolete.Combined.DISPLAY + ", " +
|
||||
"-1 AS " + Combined.HISTORY_ID + ", " +
|
||||
"-1 AS " + Combined.VISITS + ", " +
|
||||
"-1 AS " + Combined.DATE_LAST_VISITED +
|
||||
" FROM " + TABLE_BOOKMARKS +
|
||||
" WHERE " + qualifyColumn(TABLE_BOOKMARKS, Bookmarks.TYPE) + " = " + Bookmarks.TYPE_BOOKMARK + " AND " +
|
||||
qualifyColumn(TABLE_BOOKMARKS, Bookmarks.IS_DELETED) + " = 0 AND " +
|
||||
qualifyColumn(TABLE_BOOKMARKS, Bookmarks.URL) +
|
||||
" NOT IN (SELECT " + History.URL + " FROM " + TABLE_HISTORY + ")" +
|
||||
" UNION ALL" +
|
||||
// History with and without bookmark.
|
||||
" SELECT " + qualifyColumn(TABLE_BOOKMARKS, Bookmarks._ID) + " AS " + Combined.BOOKMARK_ID + ", " +
|
||||
qualifyColumn(TABLE_HISTORY, History.URL) + " AS " + Combined.URL + ", " +
|
||||
// Prioritize bookmark titles over history titles, since the user may have
|
||||
// customized the title for a bookmark.
|
||||
"COALESCE(" + qualifyColumn(TABLE_BOOKMARKS, Bookmarks.TITLE) + ", " +
|
||||
qualifyColumn(TABLE_HISTORY, History.TITLE) +")" + " AS " + Combined.TITLE + ", " +
|
||||
"CASE " + qualifyColumn(TABLE_BOOKMARKS, Bookmarks.PARENT) + " WHEN " +
|
||||
Bookmarks.FIXED_READING_LIST_ID + " THEN " + Obsolete.Combined.DISPLAY_READER + " ELSE " +
|
||||
Obsolete.Combined.DISPLAY_NORMAL + " END AS " + Obsolete.Combined.DISPLAY + ", " +
|
||||
qualifyColumn(TABLE_HISTORY, History._ID) + " AS " + Combined.HISTORY_ID + ", " +
|
||||
qualifyColumn(TABLE_HISTORY, History.VISITS) + " AS " + Combined.VISITS + ", " +
|
||||
qualifyColumn(TABLE_HISTORY, History.DATE_LAST_VISITED) + " AS " + Combined.DATE_LAST_VISITED +
|
||||
" FROM " + TABLE_HISTORY + " LEFT OUTER JOIN " + TABLE_BOOKMARKS +
|
||||
" ON " + qualifyColumn(TABLE_BOOKMARKS, Bookmarks.URL) + " = " + qualifyColumn(TABLE_HISTORY, History.URL) +
|
||||
" WHERE " + qualifyColumn(TABLE_HISTORY, History.URL) + " IS NOT NULL AND " +
|
||||
qualifyColumn(TABLE_HISTORY, History.IS_DELETED) + " = 0 AND (" +
|
||||
qualifyColumn(TABLE_BOOKMARKS, Bookmarks.TYPE) + " IS NULL OR " +
|
||||
qualifyColumn(TABLE_BOOKMARKS, Bookmarks.TYPE) + " = " + Bookmarks.TYPE_BOOKMARK + ")" +
|
||||
") LEFT OUTER JOIN " + Obsolete.TABLE_IMAGES +
|
||||
" ON " + Combined.URL + " = " + qualifyColumn(Obsolete.TABLE_IMAGES, Obsolete.Images.URL));
|
||||
}
|
||||
|
||||
private void createCombinedWithImagesViewOn10(SQLiteDatabase db) {
|
||||
debug("Creating " + Obsolete.VIEW_COMBINED_WITH_IMAGES + " view");
|
||||
|
||||
db.execSQL("CREATE VIEW IF NOT EXISTS " + Obsolete.VIEW_COMBINED_WITH_IMAGES + " AS" +
|
||||
" SELECT " + Combined.BOOKMARK_ID + ", " +
|
||||
Combined.HISTORY_ID + ", " +
|
||||
// We need to return an _id column because CursorAdapter requires it for its
|
||||
// default implementation for the getItemId() method. However, since
|
||||
// we're not using this feature in the parts of the UI using this view,
|
||||
// we can just use 0 for all rows.
|
||||
"0 AS " + Combined._ID + ", " +
|
||||
Combined.URL + ", " +
|
||||
Combined.TITLE + ", " +
|
||||
Combined.VISITS + ", " +
|
||||
Obsolete.Combined.DISPLAY + ", " +
|
||||
Combined.DATE_LAST_VISITED + ", " +
|
||||
qualifyColumn(Obsolete.TABLE_IMAGES, Obsolete.Images.FAVICON) + " AS " + Combined.FAVICON + ", " +
|
||||
qualifyColumn(Obsolete.TABLE_IMAGES, Obsolete.Images.THUMBNAIL) + " AS " + Obsolete.Combined.THUMBNAIL +
|
||||
" FROM (" +
|
||||
// Bookmarks without history.
|
||||
" SELECT " + qualifyColumn(TABLE_BOOKMARKS, Bookmarks._ID) + " AS " + Combined.BOOKMARK_ID + ", " +
|
||||
qualifyColumn(TABLE_BOOKMARKS, Bookmarks.URL) + " AS " + Combined.URL + ", " +
|
||||
qualifyColumn(TABLE_BOOKMARKS, Bookmarks.TITLE) + " AS " + Combined.TITLE + ", " +
|
||||
"CASE " + qualifyColumn(TABLE_BOOKMARKS, Bookmarks.PARENT) + " WHEN " +
|
||||
Bookmarks.FIXED_READING_LIST_ID + " THEN " + Obsolete.Combined.DISPLAY_READER + " ELSE " +
|
||||
Obsolete.Combined.DISPLAY_NORMAL + " END AS " + Obsolete.Combined.DISPLAY + ", " +
|
||||
"-1 AS " + Combined.HISTORY_ID + ", " +
|
||||
"-1 AS " + Combined.VISITS + ", " +
|
||||
"-1 AS " + Combined.DATE_LAST_VISITED +
|
||||
" FROM " + TABLE_BOOKMARKS +
|
||||
" WHERE " + qualifyColumn(TABLE_BOOKMARKS, Bookmarks.TYPE) + " = " + Bookmarks.TYPE_BOOKMARK + " AND " +
|
||||
qualifyColumn(TABLE_BOOKMARKS, Bookmarks.IS_DELETED) + " = 0 AND " +
|
||||
qualifyColumn(TABLE_BOOKMARKS, Bookmarks.URL) +
|
||||
" NOT IN (SELECT " + History.URL + " FROM " + TABLE_HISTORY + ")" +
|
||||
" UNION ALL" +
|
||||
// History with and without bookmark.
|
||||
" SELECT " + "CASE " + qualifyColumn(TABLE_BOOKMARKS, Bookmarks.IS_DELETED) + " WHEN 0 THEN " +
|
||||
qualifyColumn(TABLE_BOOKMARKS, Bookmarks._ID) + " ELSE NULL END AS " + Combined.BOOKMARK_ID + ", " +
|
||||
qualifyColumn(TABLE_HISTORY, History.URL) + " AS " + Combined.URL + ", " +
|
||||
// Prioritize bookmark titles over history titles, since the user may have
|
||||
// customized the title for a bookmark.
|
||||
"COALESCE(" + qualifyColumn(TABLE_BOOKMARKS, Bookmarks.TITLE) + ", " +
|
||||
qualifyColumn(TABLE_HISTORY, History.TITLE) +")" + " AS " + Combined.TITLE + ", " +
|
||||
"CASE " + qualifyColumn(TABLE_BOOKMARKS, Bookmarks.PARENT) + " WHEN " +
|
||||
Bookmarks.FIXED_READING_LIST_ID + " THEN " + Obsolete.Combined.DISPLAY_READER + " ELSE " +
|
||||
Obsolete.Combined.DISPLAY_NORMAL + " END AS " + Obsolete.Combined.DISPLAY + ", " +
|
||||
qualifyColumn(TABLE_HISTORY, History._ID) + " AS " + Combined.HISTORY_ID + ", " +
|
||||
qualifyColumn(TABLE_HISTORY, History.VISITS) + " AS " + Combined.VISITS + ", " +
|
||||
qualifyColumn(TABLE_HISTORY, History.DATE_LAST_VISITED) + " AS " + Combined.DATE_LAST_VISITED +
|
||||
" FROM " + TABLE_HISTORY + " LEFT OUTER JOIN " + TABLE_BOOKMARKS +
|
||||
" ON " + qualifyColumn(TABLE_BOOKMARKS, Bookmarks.URL) + " = " + qualifyColumn(TABLE_HISTORY, History.URL) +
|
||||
" WHERE " + qualifyColumn(TABLE_HISTORY, History.URL) + " IS NOT NULL AND " +
|
||||
qualifyColumn(TABLE_HISTORY, History.IS_DELETED) + " = 0 AND (" +
|
||||
qualifyColumn(TABLE_BOOKMARKS, Bookmarks.TYPE) + " IS NULL OR " +
|
||||
qualifyColumn(TABLE_BOOKMARKS, Bookmarks.TYPE) + " = " + Bookmarks.TYPE_BOOKMARK + ")" +
|
||||
") LEFT OUTER JOIN " + Obsolete.TABLE_IMAGES +
|
||||
" ON " + Combined.URL + " = " + qualifyColumn(Obsolete.TABLE_IMAGES, Obsolete.Images.URL));
|
||||
}
|
||||
|
||||
private void createCombinedWithImagesViewOn11(SQLiteDatabase db) {
|
||||
debug("Creating " + Obsolete.VIEW_COMBINED_WITH_IMAGES + " view");
|
||||
|
||||
db.execSQL("CREATE VIEW IF NOT EXISTS " + Obsolete.VIEW_COMBINED_WITH_IMAGES + " AS" +
|
||||
" SELECT " + Combined.BOOKMARK_ID + ", " +
|
||||
Combined.HISTORY_ID + ", " +
|
||||
// We need to return an _id column because CursorAdapter requires it for its
|
||||
// default implementation for the getItemId() method. However, since
|
||||
// we're not using this feature in the parts of the UI using this view,
|
||||
// we can just use 0 for all rows.
|
||||
"0 AS " + Combined._ID + ", " +
|
||||
Combined.URL + ", " +
|
||||
Combined.TITLE + ", " +
|
||||
Combined.VISITS + ", " +
|
||||
Obsolete.Combined.DISPLAY + ", " +
|
||||
Combined.DATE_LAST_VISITED + ", " +
|
||||
qualifyColumn(Obsolete.TABLE_IMAGES, Obsolete.Images.FAVICON) + " AS " + Combined.FAVICON + ", " +
|
||||
qualifyColumn(Obsolete.TABLE_IMAGES, Obsolete.Images.THUMBNAIL) + " AS " + Obsolete.Combined.THUMBNAIL +
|
||||
" FROM (" +
|
||||
// Bookmarks without history.
|
||||
" SELECT " + qualifyColumn(TABLE_BOOKMARKS, Bookmarks._ID) + " AS " + Combined.BOOKMARK_ID + ", " +
|
||||
qualifyColumn(TABLE_BOOKMARKS, Bookmarks.URL) + " AS " + Combined.URL + ", " +
|
||||
qualifyColumn(TABLE_BOOKMARKS, Bookmarks.TITLE) + " AS " + Combined.TITLE + ", " +
|
||||
"CASE " + qualifyColumn(TABLE_BOOKMARKS, Bookmarks.PARENT) + " WHEN " +
|
||||
Bookmarks.FIXED_READING_LIST_ID + " THEN " + Obsolete.Combined.DISPLAY_READER + " ELSE " +
|
||||
Obsolete.Combined.DISPLAY_NORMAL + " END AS " + Obsolete.Combined.DISPLAY + ", " +
|
||||
"-1 AS " + Combined.HISTORY_ID + ", " +
|
||||
"-1 AS " + Combined.VISITS + ", " +
|
||||
"-1 AS " + Combined.DATE_LAST_VISITED +
|
||||
" FROM " + TABLE_BOOKMARKS +
|
||||
" WHERE " + qualifyColumn(TABLE_BOOKMARKS, Bookmarks.TYPE) + " = " + Bookmarks.TYPE_BOOKMARK + " AND " +
|
||||
qualifyColumn(TABLE_BOOKMARKS, Bookmarks.IS_DELETED) + " = 0 AND " +
|
||||
qualifyColumn(TABLE_BOOKMARKS, Bookmarks.URL) +
|
||||
" NOT IN (SELECT " + History.URL + " FROM " + TABLE_HISTORY + ")" +
|
||||
" UNION ALL" +
|
||||
// History with and without bookmark.
|
||||
" SELECT " + "CASE " + qualifyColumn(TABLE_BOOKMARKS, Bookmarks.IS_DELETED) + " WHEN 0 THEN " +
|
||||
qualifyColumn(TABLE_BOOKMARKS, Bookmarks._ID) + " ELSE NULL END AS " + Combined.BOOKMARK_ID + ", " +
|
||||
qualifyColumn(TABLE_HISTORY, History.URL) + " AS " + Combined.URL + ", " +
|
||||
// Prioritize bookmark titles over history titles, since the user may have
|
||||
// customized the title for a bookmark.
|
||||
"COALESCE(" + qualifyColumn(TABLE_BOOKMARKS, Bookmarks.TITLE) + ", " +
|
||||
qualifyColumn(TABLE_HISTORY, History.TITLE) +")" + " AS " + Combined.TITLE + ", " +
|
||||
qualifyColumn(TABLE_HISTORY, History._ID) + " AS " + Combined.HISTORY_ID + ", " +
|
||||
qualifyColumn(TABLE_HISTORY, History.VISITS) + " AS " + Combined.VISITS + ", " +
|
||||
qualifyColumn(TABLE_HISTORY, History.DATE_LAST_VISITED) + " AS " + Combined.DATE_LAST_VISITED +
|
||||
" FROM " + TABLE_HISTORY + " LEFT OUTER JOIN " + TABLE_BOOKMARKS +
|
||||
" ON " + qualifyColumn(TABLE_BOOKMARKS, Bookmarks.URL) + " = " + qualifyColumn(TABLE_HISTORY, History.URL) +
|
||||
" WHERE " + qualifyColumn(TABLE_HISTORY, History.URL) + " IS NOT NULL AND " +
|
||||
qualifyColumn(TABLE_HISTORY, History.IS_DELETED) + " = 0 AND (" +
|
||||
qualifyColumn(TABLE_BOOKMARKS, Bookmarks.TYPE) + " IS NULL OR " +
|
||||
qualifyColumn(TABLE_BOOKMARKS, Bookmarks.TYPE) + " = " + Bookmarks.TYPE_BOOKMARK + ") " +
|
||||
") LEFT OUTER JOIN " + Obsolete.TABLE_IMAGES +
|
||||
" ON " + Combined.URL + " = " + qualifyColumn(Obsolete.TABLE_IMAGES, Obsolete.Images.URL));
|
||||
}
|
||||
|
||||
private void createCombinedViewOn12(SQLiteDatabase db) {
|
||||
debug("Creating " + VIEW_COMBINED + " view");
|
||||
|
||||
db.execSQL("CREATE VIEW IF NOT EXISTS " + VIEW_COMBINED + " AS" +
|
||||
" SELECT " + Combined.BOOKMARK_ID + ", " +
|
||||
Combined.HISTORY_ID + ", " +
|
||||
// We need to return an _id column because CursorAdapter requires it for its
|
||||
// default implementation for the getItemId() method. However, since
|
||||
// we're not using this feature in the parts of the UI using this view,
|
||||
// we can just use 0 for all rows.
|
||||
"0 AS " + Combined._ID + ", " +
|
||||
Combined.URL + ", " +
|
||||
Combined.TITLE + ", " +
|
||||
Combined.VISITS + ", " +
|
||||
Obsolete.Combined.DISPLAY + ", " +
|
||||
Combined.DATE_LAST_VISITED +
|
||||
" FROM (" +
|
||||
// Bookmarks without history.
|
||||
" SELECT " + qualifyColumn(TABLE_BOOKMARKS, Bookmarks._ID) + " AS " + Combined.BOOKMARK_ID + ", " +
|
||||
qualifyColumn(TABLE_BOOKMARKS, Bookmarks.URL) + " AS " + Combined.URL + ", " +
|
||||
qualifyColumn(TABLE_BOOKMARKS, Bookmarks.TITLE) + " AS " + Combined.TITLE + ", " +
|
||||
"CASE " + qualifyColumn(TABLE_BOOKMARKS, Bookmarks.PARENT) + " WHEN " +
|
||||
Bookmarks.FIXED_READING_LIST_ID + " THEN " + Obsolete.Combined.DISPLAY_READER + " ELSE " +
|
||||
Obsolete.Combined.DISPLAY_NORMAL + " END AS " + Obsolete.Combined.DISPLAY + ", " +
|
||||
"-1 AS " + Combined.HISTORY_ID + ", " +
|
||||
"-1 AS " + Combined.VISITS + ", " +
|
||||
"-1 AS " + Combined.DATE_LAST_VISITED +
|
||||
" FROM " + TABLE_BOOKMARKS +
|
||||
" WHERE " + qualifyColumn(TABLE_BOOKMARKS, Bookmarks.TYPE) + " = " + Bookmarks.TYPE_BOOKMARK + " AND " +
|
||||
qualifyColumn(TABLE_BOOKMARKS, Bookmarks.IS_DELETED) + " = 0 AND " +
|
||||
qualifyColumn(TABLE_BOOKMARKS, Bookmarks.URL) +
|
||||
" NOT IN (SELECT " + History.URL + " FROM " + TABLE_HISTORY + ")" +
|
||||
" UNION ALL" +
|
||||
// History with and without bookmark.
|
||||
" SELECT " + "CASE " + qualifyColumn(TABLE_BOOKMARKS, Bookmarks.IS_DELETED) + " WHEN 0 THEN " +
|
||||
qualifyColumn(TABLE_BOOKMARKS, Bookmarks._ID) + " ELSE NULL END AS " + Combined.BOOKMARK_ID + ", " +
|
||||
qualifyColumn(TABLE_HISTORY, History.URL) + " AS " + Combined.URL + ", " +
|
||||
// Prioritize bookmark titles over history titles, since the user may have
|
||||
// customized the title for a bookmark.
|
||||
"COALESCE(" + qualifyColumn(TABLE_BOOKMARKS, Bookmarks.TITLE) + ", " +
|
||||
qualifyColumn(TABLE_HISTORY, History.TITLE) +")" + " AS " + Combined.TITLE + ", " +
|
||||
qualifyColumn(TABLE_HISTORY, History._ID) + " AS " + Combined.HISTORY_ID + ", " +
|
||||
qualifyColumn(TABLE_HISTORY, History.VISITS) + " AS " + Combined.VISITS + ", " +
|
||||
qualifyColumn(TABLE_HISTORY, History.DATE_LAST_VISITED) + " AS " + Combined.DATE_LAST_VISITED +
|
||||
" FROM " + TABLE_HISTORY + " LEFT OUTER JOIN " + TABLE_BOOKMARKS +
|
||||
" ON " + qualifyColumn(TABLE_BOOKMARKS, Bookmarks.URL) + " = " + qualifyColumn(TABLE_HISTORY, History.URL) +
|
||||
" WHERE " + qualifyColumn(TABLE_HISTORY, History.URL) + " IS NOT NULL AND " +
|
||||
qualifyColumn(TABLE_HISTORY, History.IS_DELETED) + " = 0 AND (" +
|
||||
qualifyColumn(TABLE_BOOKMARKS, Bookmarks.TYPE) + " IS NULL OR " +
|
||||
qualifyColumn(TABLE_BOOKMARKS, Bookmarks.TYPE) + " = " + Bookmarks.TYPE_BOOKMARK + ") " +
|
||||
")");
|
||||
|
||||
debug("Creating " + Obsolete.VIEW_COMBINED_WITH_IMAGES + " view");
|
||||
|
||||
db.execSQL("CREATE VIEW IF NOT EXISTS " + Obsolete.VIEW_COMBINED_WITH_IMAGES + " AS" +
|
||||
" SELECT *, " +
|
||||
qualifyColumn(Obsolete.TABLE_IMAGES, Obsolete.Images.FAVICON) + " AS " + Combined.FAVICON + ", " +
|
||||
qualifyColumn(Obsolete.TABLE_IMAGES, Obsolete.Images.THUMBNAIL) + " AS " + Obsolete.Combined.THUMBNAIL +
|
||||
" FROM " + VIEW_COMBINED + " LEFT OUTER JOIN " + Obsolete.TABLE_IMAGES +
|
||||
" ON " + Combined.URL + " = " + qualifyColumn(Obsolete.TABLE_IMAGES, Obsolete.Images.URL));
|
||||
}
|
||||
|
||||
private void createCombinedViewOn13(SQLiteDatabase db) {
|
||||
debug("Creating " + VIEW_COMBINED + " view");
|
||||
|
||||
db.execSQL("CREATE VIEW IF NOT EXISTS " + VIEW_COMBINED + " AS" +
|
||||
" SELECT " + Combined.BOOKMARK_ID + ", " +
|
||||
Combined.HISTORY_ID + ", " +
|
||||
// We need to return an _id column because CursorAdapter requires it for its
|
||||
// default implementation for the getItemId() method. However, since
|
||||
// we're not using this feature in the parts of the UI using this view,
|
||||
// we can just use 0 for all rows.
|
||||
"0 AS " + Combined._ID + ", " +
|
||||
Combined.URL + ", " +
|
||||
Combined.TITLE + ", " +
|
||||
Combined.VISITS + ", " +
|
||||
Obsolete.Combined.DISPLAY + ", " +
|
||||
Combined.DATE_LAST_VISITED + ", " +
|
||||
Combined.FAVICON_ID +
|
||||
" FROM (" +
|
||||
// Bookmarks without history.
|
||||
" SELECT " + qualifyColumn(TABLE_BOOKMARKS, Bookmarks._ID) + " AS " + Combined.BOOKMARK_ID + ", " +
|
||||
qualifyColumn(TABLE_BOOKMARKS, Bookmarks.URL) + " AS " + Combined.URL + ", " +
|
||||
qualifyColumn(TABLE_BOOKMARKS, Bookmarks.TITLE) + " AS " + Combined.TITLE + ", " +
|
||||
"CASE " + qualifyColumn(TABLE_BOOKMARKS, Bookmarks.PARENT) + " WHEN " +
|
||||
Bookmarks.FIXED_READING_LIST_ID + " THEN " + Obsolete.Combined.DISPLAY_READER + " ELSE " +
|
||||
Obsolete.Combined.DISPLAY_NORMAL + " END AS " + Obsolete.Combined.DISPLAY + ", " +
|
||||
"-1 AS " + Combined.HISTORY_ID + ", " +
|
||||
"-1 AS " + Combined.VISITS + ", " +
|
||||
"-1 AS " + Combined.DATE_LAST_VISITED + ", " +
|
||||
qualifyColumn(TABLE_BOOKMARKS, Bookmarks.FAVICON_ID) + " AS " + Combined.FAVICON_ID +
|
||||
" FROM " + TABLE_BOOKMARKS +
|
||||
" WHERE " + qualifyColumn(TABLE_BOOKMARKS, Bookmarks.TYPE) + " = " + Bookmarks.TYPE_BOOKMARK + " AND " +
|
||||
qualifyColumn(TABLE_BOOKMARKS, Bookmarks.IS_DELETED) + " = 0 AND " +
|
||||
qualifyColumn(TABLE_BOOKMARKS, Bookmarks.URL) +
|
||||
" NOT IN (SELECT " + History.URL + " FROM " + TABLE_HISTORY + ")" +
|
||||
" UNION ALL" +
|
||||
// History with and without bookmark.
|
||||
" SELECT " + "CASE " + qualifyColumn(TABLE_BOOKMARKS, Bookmarks.IS_DELETED) + " WHEN 0 THEN " +
|
||||
qualifyColumn(TABLE_BOOKMARKS, Bookmarks._ID) + " ELSE NULL END AS " + Combined.BOOKMARK_ID + ", " +
|
||||
qualifyColumn(TABLE_HISTORY, History.URL) + " AS " + Combined.URL + ", " +
|
||||
// Prioritize bookmark titles over history titles, since the user may have
|
||||
// customized the title for a bookmark.
|
||||
"COALESCE(" + qualifyColumn(TABLE_BOOKMARKS, Bookmarks.TITLE) + ", " +
|
||||
qualifyColumn(TABLE_HISTORY, History.TITLE) +")" + " AS " + Combined.TITLE + ", " +
|
||||
// Only use DISPLAY_READER if the matching bookmark entry inside reading
|
||||
// list folder is not marked as deleted.
|
||||
"CASE " + qualifyColumn(TABLE_BOOKMARKS, Bookmarks.IS_DELETED) + " WHEN 0 THEN CASE " +
|
||||
qualifyColumn(TABLE_BOOKMARKS, Bookmarks.PARENT) + " WHEN " + Bookmarks.FIXED_READING_LIST_ID +
|
||||
" THEN " + Obsolete.Combined.DISPLAY_READER + " ELSE " + Obsolete.Combined.DISPLAY_NORMAL + " END ELSE " +
|
||||
Obsolete.Combined.DISPLAY_NORMAL + " END AS " + Obsolete.Combined.DISPLAY + ", " +
|
||||
qualifyColumn(TABLE_HISTORY, History._ID) + " AS " + Combined.HISTORY_ID + ", " +
|
||||
qualifyColumn(TABLE_HISTORY, History.VISITS) + " AS " + Combined.VISITS + ", " +
|
||||
qualifyColumn(TABLE_HISTORY, History.DATE_LAST_VISITED) + " AS " + Combined.DATE_LAST_VISITED + ", " +
|
||||
qualifyColumn(TABLE_HISTORY, History.FAVICON_ID) + " AS " + Combined.FAVICON_ID +
|
||||
" FROM " + TABLE_HISTORY + " LEFT OUTER JOIN " + TABLE_BOOKMARKS +
|
||||
" ON " + qualifyColumn(TABLE_BOOKMARKS, Bookmarks.URL) + " = " + qualifyColumn(TABLE_HISTORY, History.URL) +
|
||||
" WHERE " + qualifyColumn(TABLE_HISTORY, History.URL) + " IS NOT NULL AND " +
|
||||
qualifyColumn(TABLE_HISTORY, History.IS_DELETED) + " = 0 AND (" +
|
||||
qualifyColumn(TABLE_BOOKMARKS, Bookmarks.TYPE) + " IS NULL OR " +
|
||||
qualifyColumn(TABLE_BOOKMARKS, Bookmarks.TYPE) + " = " + Bookmarks.TYPE_BOOKMARK + ") " +
|
||||
")");
|
||||
|
||||
debug("Creating " + VIEW_COMBINED_WITH_FAVICONS + " view");
|
||||
|
||||
db.execSQL("CREATE VIEW IF NOT EXISTS " + VIEW_COMBINED_WITH_FAVICONS + " AS" +
|
||||
" SELECT " + qualifyColumn(VIEW_COMBINED, "*") + ", " +
|
||||
qualifyColumn(TABLE_FAVICONS, Favicons.URL) + " AS " + Combined.FAVICON_URL + ", " +
|
||||
qualifyColumn(TABLE_FAVICONS, Favicons.DATA) + " AS " + Combined.FAVICON +
|
||||
" FROM " + VIEW_COMBINED + " LEFT OUTER JOIN " + TABLE_FAVICONS +
|
||||
" ON " + Combined.FAVICON_ID + " = " + qualifyColumn(TABLE_FAVICONS, Favicons._ID));
|
||||
}
|
||||
|
||||
private void createCombinedViewOn19(SQLiteDatabase db) {
|
||||
/*
|
||||
The v19 combined view removes the redundant subquery from the v16
|
||||
|
@ -725,6 +270,7 @@ final class BrowserDatabaseHelper extends SQLiteOpenHelper {
|
|||
qualifyColumn(TABLE_FAVICONS, Favicons.DATA) + " AS " + Combined.FAVICON +
|
||||
" FROM " + VIEW_COMBINED + " LEFT OUTER JOIN " + TABLE_FAVICONS +
|
||||
" ON " + Combined.FAVICON_ID + " = " + qualifyColumn(TABLE_FAVICONS, Favicons._ID));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -735,8 +281,8 @@ final class BrowserDatabaseHelper extends SQLiteOpenHelper {
|
|||
table.onCreate(db);
|
||||
}
|
||||
|
||||
createBookmarksTableOn13(db);
|
||||
createHistoryTableOn13(db);
|
||||
createBookmarksTable(db);
|
||||
createHistoryTable(db);
|
||||
createFaviconsTable(db);
|
||||
createThumbnailsTable(db);
|
||||
|
||||
|
@ -777,7 +323,7 @@ final class BrowserDatabaseHelper extends SQLiteOpenHelper {
|
|||
ReadingListItems.IS_DELETED + " TINYINT DEFAULT 0, " +
|
||||
ReadingListItems.GUID + " TEXT UNIQUE NOT NULL, " +
|
||||
ReadingListItems.DATE_MODIFIED + " INTEGER NOT NULL, " +
|
||||
ReadingListItems.DATE_CREATED + " INTEGER NOT NULL, " +
|
||||
ReadingListItems.DATE_CREATED + " INTEGER NOT NULL, " +
|
||||
ReadingListItems.LENGTH + " INTEGER DEFAULT 0 ); ");
|
||||
|
||||
db.execSQL("CREATE INDEX reading_list_url ON " + TABLE_READING_LIST + "("
|
||||
|
@ -797,10 +343,8 @@ final class BrowserDatabaseHelper extends SQLiteOpenHelper {
|
|||
R.string.bookmarks_folder_tags, 3);
|
||||
createOrUpdateSpecialFolder(db, Bookmarks.UNFILED_FOLDER_GUID,
|
||||
R.string.bookmarks_folder_unfiled, 4);
|
||||
createOrUpdateSpecialFolder(db, Bookmarks.READING_LIST_FOLDER_GUID,
|
||||
R.string.bookmarks_folder_reading_list, 5);
|
||||
createOrUpdateSpecialFolder(db, Bookmarks.PINNED_FOLDER_GUID,
|
||||
R.string.bookmarks_folder_pinned, 6);
|
||||
R.string.bookmarks_folder_pinned, 5);
|
||||
}
|
||||
|
||||
private void createOrUpdateSpecialFolder(SQLiteDatabase db,
|
||||
|
@ -810,12 +354,11 @@ final class BrowserDatabaseHelper extends SQLiteOpenHelper {
|
|||
values.put(Bookmarks.TYPE, Bookmarks.TYPE_FOLDER);
|
||||
values.put(Bookmarks.POSITION, position);
|
||||
|
||||
if (guid.equals(Bookmarks.PLACES_FOLDER_GUID))
|
||||
if (guid.equals(Bookmarks.PLACES_FOLDER_GUID)) {
|
||||
values.put(Bookmarks._ID, Bookmarks.FIXED_ROOT_ID);
|
||||
else if (guid.equals(Bookmarks.READING_LIST_FOLDER_GUID))
|
||||
values.put(Bookmarks._ID, Bookmarks.FIXED_READING_LIST_ID);
|
||||
else if (guid.equals(Bookmarks.PINNED_FOLDER_GUID))
|
||||
} else if (guid.equals(Bookmarks.PINNED_FOLDER_GUID)) {
|
||||
values.put(Bookmarks._ID, Bookmarks.FIXED_PINNED_LIST_ID);
|
||||
}
|
||||
|
||||
// Set the parent to 0, which sync assumes is the root
|
||||
values.put(Bookmarks.PARENT, Bookmarks.FIXED_ROOT_ID);
|
||||
|
@ -841,8 +384,9 @@ final class BrowserDatabaseHelper extends SQLiteOpenHelper {
|
|||
|
||||
private boolean isSpecialFolder(ContentValues values) {
|
||||
String guid = values.getAsString(Bookmarks.GUID);
|
||||
if (guid == null)
|
||||
if (guid == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return guid.equals(Bookmarks.MOBILE_FOLDER_GUID) ||
|
||||
guid.equals(Bookmarks.MENU_FOLDER_GUID) ||
|
||||
|
@ -958,7 +502,6 @@ final class BrowserDatabaseHelper extends SQLiteOpenHelper {
|
|||
" RENAME TO " + TABLE_BOOKMARKS_TMP);
|
||||
|
||||
debug("Dropping views and indexes related to " + TABLE_BOOKMARKS);
|
||||
db.execSQL("DROP VIEW IF EXISTS " + Obsolete.VIEW_BOOKMARKS_WITH_IMAGES);
|
||||
|
||||
db.execSQL("DROP INDEX IF EXISTS bookmarks_url_index");
|
||||
db.execSQL("DROP INDEX IF EXISTS bookmarks_type_deleted_index");
|
||||
|
@ -966,7 +509,6 @@ final class BrowserDatabaseHelper extends SQLiteOpenHelper {
|
|||
db.execSQL("DROP INDEX IF EXISTS bookmarks_modified_index");
|
||||
|
||||
createBookmarksTable(db);
|
||||
createBookmarksWithImagesView(db);
|
||||
|
||||
createOrUpdateSpecialFolder(db, Bookmarks.PLACES_FOLDER_GUID,
|
||||
R.string.bookmarks_folder_places, 0);
|
||||
|
@ -981,15 +523,16 @@ final class BrowserDatabaseHelper extends SQLiteOpenHelper {
|
|||
db.execSQL("DROP TABLE IF EXISTS " + TABLE_BOOKMARKS_TMP);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Migrate a history table from some old version to the newest one by creating the new table and
|
||||
* copying all the data over.
|
||||
*/
|
||||
private void migrateHistoryTable(SQLiteDatabase db) {
|
||||
debug("Renaming history table to " + TABLE_HISTORY_TMP);
|
||||
db.execSQL("ALTER TABLE " + TABLE_HISTORY +
|
||||
" RENAME TO " + TABLE_HISTORY_TMP);
|
||||
|
||||
debug("Dropping views and indexes related to " + TABLE_HISTORY);
|
||||
db.execSQL("DROP VIEW IF EXISTS " + Obsolete.VIEW_HISTORY_WITH_IMAGES);
|
||||
db.execSQL("DROP VIEW IF EXISTS " + Obsolete.VIEW_COMBINED_WITH_IMAGES);
|
||||
|
||||
db.execSQL("DROP INDEX IF EXISTS history_url_index");
|
||||
db.execSQL("DROP INDEX IF EXISTS history_guid_index");
|
||||
|
@ -997,8 +540,6 @@ final class BrowserDatabaseHelper extends SQLiteOpenHelper {
|
|||
db.execSQL("DROP INDEX IF EXISTS history_visited_index");
|
||||
|
||||
createHistoryTable(db);
|
||||
createHistoryWithImagesView(db);
|
||||
createCombinedWithImagesView(db);
|
||||
|
||||
db.execSQL("INSERT INTO " + TABLE_HISTORY + " SELECT * FROM " + TABLE_HISTORY_TMP);
|
||||
|
||||
|
@ -1006,86 +547,16 @@ final class BrowserDatabaseHelper extends SQLiteOpenHelper {
|
|||
db.execSQL("DROP TABLE IF EXISTS " + TABLE_HISTORY_TMP);
|
||||
}
|
||||
|
||||
private void migrateImagesTable(SQLiteDatabase db) {
|
||||
debug("Renaming images table to " + TABLE_IMAGES_TMP);
|
||||
db.execSQL("ALTER TABLE " + Obsolete.TABLE_IMAGES +
|
||||
" RENAME TO " + TABLE_IMAGES_TMP);
|
||||
|
||||
debug("Dropping views and indexes related to " + Obsolete.TABLE_IMAGES);
|
||||
db.execSQL("DROP VIEW IF EXISTS " + Obsolete.VIEW_HISTORY_WITH_IMAGES);
|
||||
db.execSQL("DROP VIEW IF EXISTS " + Obsolete.VIEW_COMBINED_WITH_IMAGES);
|
||||
|
||||
db.execSQL("DROP INDEX IF EXISTS images_url_index");
|
||||
db.execSQL("DROP INDEX IF EXISTS images_guid_index");
|
||||
db.execSQL("DROP INDEX IF EXISTS images_modified_index");
|
||||
|
||||
createImagesTable(db);
|
||||
createHistoryWithImagesView(db);
|
||||
createCombinedWithImagesView(db);
|
||||
|
||||
db.execSQL("INSERT INTO " + Obsolete.TABLE_IMAGES + " SELECT * FROM " + TABLE_IMAGES_TMP);
|
||||
|
||||
debug("Dropping images temporary table");
|
||||
db.execSQL("DROP TABLE IF EXISTS " + TABLE_IMAGES_TMP);
|
||||
}
|
||||
|
||||
private void upgradeDatabaseFrom1to2(SQLiteDatabase db) {
|
||||
migrateBookmarksTable(db);
|
||||
}
|
||||
|
||||
private void upgradeDatabaseFrom2to3(SQLiteDatabase db) {
|
||||
debug("Dropping view: " + Obsolete.VIEW_BOOKMARKS_WITH_IMAGES);
|
||||
db.execSQL("DROP VIEW IF EXISTS " + Obsolete.VIEW_BOOKMARKS_WITH_IMAGES);
|
||||
|
||||
createBookmarksWithImagesView(db);
|
||||
|
||||
debug("Dropping view: " + Obsolete.VIEW_HISTORY_WITH_IMAGES);
|
||||
db.execSQL("DROP VIEW IF EXISTS " + Obsolete.VIEW_HISTORY_WITH_IMAGES);
|
||||
|
||||
createHistoryWithImagesView(db);
|
||||
}
|
||||
|
||||
private void upgradeDatabaseFrom3to4(SQLiteDatabase db) {
|
||||
migrateBookmarksTable(db, new BookmarkMigrator3to4());
|
||||
}
|
||||
|
||||
private void upgradeDatabaseFrom4to5(SQLiteDatabase db) {
|
||||
createCombinedWithImagesView(db);
|
||||
}
|
||||
|
||||
private void upgradeDatabaseFrom5to6(SQLiteDatabase db) {
|
||||
debug("Dropping view: " + Obsolete.VIEW_COMBINED_WITH_IMAGES);
|
||||
db.execSQL("DROP VIEW IF EXISTS " + Obsolete.VIEW_COMBINED_WITH_IMAGES);
|
||||
|
||||
createCombinedWithImagesView(db);
|
||||
}
|
||||
|
||||
private void upgradeDatabaseFrom6to7(SQLiteDatabase db) {
|
||||
debug("Removing history visits with NULL GUIDs");
|
||||
db.execSQL("DELETE FROM " + TABLE_HISTORY + " WHERE " + History.GUID + " IS NULL");
|
||||
|
||||
debug("Update images with NULL GUIDs");
|
||||
String[] columns = new String[] { Obsolete.Images._ID };
|
||||
Cursor cursor = null;
|
||||
try {
|
||||
cursor = db.query(Obsolete.TABLE_IMAGES, columns, Obsolete.Images.GUID + " IS NULL", null, null ,null, null, null);
|
||||
ContentValues values = new ContentValues();
|
||||
if (cursor.moveToFirst()) {
|
||||
do {
|
||||
values.put(Obsolete.Images.GUID, Utils.generateGuid());
|
||||
db.update(Obsolete.TABLE_IMAGES, values, Obsolete.Images._ID + " = ?", new String[] {
|
||||
cursor.getString(cursor.getColumnIndexOrThrow(Obsolete.Images._ID))
|
||||
});
|
||||
} while (cursor.moveToNext());
|
||||
}
|
||||
} finally {
|
||||
if (cursor != null)
|
||||
cursor.close();
|
||||
}
|
||||
|
||||
migrateBookmarksTable(db);
|
||||
migrateHistoryTable(db);
|
||||
migrateImagesTable(db);
|
||||
}
|
||||
|
||||
private void upgradeDatabaseFrom7to8(SQLiteDatabase db) {
|
||||
|
@ -1122,157 +593,38 @@ final class BrowserDatabaseHelper extends SQLiteOpenHelper {
|
|||
db.execSQL("DROP TABLE " + TABLE_DUPES);
|
||||
}
|
||||
|
||||
private void upgradeDatabaseFrom8to9(SQLiteDatabase db) {
|
||||
createOrUpdateSpecialFolder(db, Bookmarks.READING_LIST_FOLDER_GUID,
|
||||
R.string.bookmarks_folder_reading_list, 5);
|
||||
|
||||
debug("Dropping view: " + Obsolete.VIEW_COMBINED_WITH_IMAGES);
|
||||
db.execSQL("DROP VIEW IF EXISTS " + Obsolete.VIEW_COMBINED_WITH_IMAGES);
|
||||
|
||||
createCombinedWithImagesViewOn9(db);
|
||||
}
|
||||
|
||||
private void upgradeDatabaseFrom9to10(SQLiteDatabase db) {
|
||||
debug("Dropping view: " + Obsolete.VIEW_COMBINED_WITH_IMAGES);
|
||||
db.execSQL("DROP VIEW IF EXISTS " + Obsolete.VIEW_COMBINED_WITH_IMAGES);
|
||||
|
||||
createCombinedWithImagesViewOn10(db);
|
||||
}
|
||||
|
||||
private void upgradeDatabaseFrom10to11(SQLiteDatabase db) {
|
||||
debug("Dropping view: " + Obsolete.VIEW_COMBINED_WITH_IMAGES);
|
||||
db.execSQL("DROP VIEW IF EXISTS " + Obsolete.VIEW_COMBINED_WITH_IMAGES);
|
||||
|
||||
db.execSQL("CREATE INDEX bookmarks_type_deleted_index ON " + TABLE_BOOKMARKS + "("
|
||||
+ Bookmarks.TYPE + ", " + Bookmarks.IS_DELETED + ")");
|
||||
|
||||
createCombinedWithImagesViewOn11(db);
|
||||
}
|
||||
|
||||
private void upgradeDatabaseFrom11to12(SQLiteDatabase db) {
|
||||
debug("Dropping view: " + Obsolete.VIEW_COMBINED_WITH_IMAGES);
|
||||
db.execSQL("DROP VIEW IF EXISTS " + Obsolete.VIEW_COMBINED_WITH_IMAGES);
|
||||
|
||||
createCombinedViewOn12(db);
|
||||
}
|
||||
|
||||
private void upgradeDatabaseFrom12to13(SQLiteDatabase db) {
|
||||
// Update images table with favicon URLs
|
||||
SQLiteDatabase faviconsDb = null;
|
||||
Cursor c = null;
|
||||
try {
|
||||
final String FAVICON_TABLE = "favicon_urls";
|
||||
final String FAVICON_URL = "favicon_url";
|
||||
final String FAVICON_PAGE = "page_url";
|
||||
|
||||
String dbPath = mContext.getDatabasePath(Obsolete.FAVICON_DB).getPath();
|
||||
faviconsDb = SQLiteDatabase.openDatabase(dbPath, null, SQLiteDatabase.OPEN_READONLY);
|
||||
String[] columns = new String[] { FAVICON_URL, FAVICON_PAGE };
|
||||
c = faviconsDb.query(FAVICON_TABLE, columns, null, null, null, null, null, null);
|
||||
int faviconIndex = c.getColumnIndexOrThrow(FAVICON_URL);
|
||||
int pageIndex = c.getColumnIndexOrThrow(FAVICON_PAGE);
|
||||
while (c.moveToNext()) {
|
||||
ContentValues values = new ContentValues(1);
|
||||
String faviconUrl = c.getString(faviconIndex);
|
||||
String pageUrl = c.getString(pageIndex);
|
||||
values.put(FAVICON_URL, faviconUrl);
|
||||
db.update(Obsolete.TABLE_IMAGES, values, Obsolete.Images.URL + " = ?", new String[] { pageUrl });
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
// If we can't read from the database for some reason, we won't
|
||||
// be able to import the favicon URLs. This isn't a fatal
|
||||
// error, so continue the upgrade.
|
||||
Log.e(LOGTAG, "Exception importing from " + Obsolete.FAVICON_DB, e);
|
||||
} finally {
|
||||
if (c != null)
|
||||
c.close();
|
||||
if (faviconsDb != null)
|
||||
faviconsDb.close();
|
||||
}
|
||||
|
||||
createFaviconsTable(db);
|
||||
|
||||
// Import favicons into the favicons table
|
||||
db.execSQL("ALTER TABLE " + TABLE_HISTORY
|
||||
+ " ADD COLUMN " + History.FAVICON_ID + " INTEGER");
|
||||
db.execSQL("ALTER TABLE " + TABLE_BOOKMARKS
|
||||
+ " ADD COLUMN " + Bookmarks.FAVICON_ID + " INTEGER");
|
||||
|
||||
// Add favicon_id column to the history/bookmarks tables. We wrap this in a try-catch
|
||||
// because the column *may* already exist at this point (depending on how many upgrade
|
||||
// steps have been performed in this operation). In which case these queries will throw,
|
||||
// but we don't care.
|
||||
try {
|
||||
c = db.query(Obsolete.TABLE_IMAGES,
|
||||
new String[] {
|
||||
Obsolete.Images.URL,
|
||||
Obsolete.Images.FAVICON_URL,
|
||||
Obsolete.Images.FAVICON,
|
||||
Obsolete.Images.DATE_MODIFIED,
|
||||
Obsolete.Images.DATE_CREATED
|
||||
},
|
||||
Obsolete.Images.FAVICON + " IS NOT NULL",
|
||||
null, null, null, null);
|
||||
|
||||
while (c.moveToNext()) {
|
||||
long faviconId = -1;
|
||||
int faviconUrlIndex = c.getColumnIndexOrThrow(Obsolete.Images.FAVICON_URL);
|
||||
String faviconUrl = null;
|
||||
if (!c.isNull(faviconUrlIndex)) {
|
||||
faviconUrl = c.getString(faviconUrlIndex);
|
||||
Cursor c2 = null;
|
||||
try {
|
||||
c2 = db.query(TABLE_FAVICONS,
|
||||
new String[] { Favicons._ID },
|
||||
Favicons.URL + " = ?",
|
||||
new String[] { faviconUrl },
|
||||
null, null, null);
|
||||
if (c2.moveToFirst()) {
|
||||
faviconId = c2.getLong(c2.getColumnIndexOrThrow(Favicons._ID));
|
||||
}
|
||||
} finally {
|
||||
if (c2 != null)
|
||||
c2.close();
|
||||
}
|
||||
}
|
||||
|
||||
if (faviconId == -1) {
|
||||
ContentValues values = new ContentValues(4);
|
||||
values.put(Favicons.URL, faviconUrl);
|
||||
values.put(Favicons.DATA, c.getBlob(c.getColumnIndexOrThrow(Obsolete.Images.FAVICON)));
|
||||
values.put(Favicons.DATE_MODIFIED, c.getLong(c.getColumnIndexOrThrow(Obsolete.Images.DATE_MODIFIED)));
|
||||
values.put(Favicons.DATE_CREATED, c.getLong(c.getColumnIndexOrThrow(Obsolete.Images.DATE_CREATED)));
|
||||
faviconId = db.insert(TABLE_FAVICONS, null, values);
|
||||
}
|
||||
|
||||
ContentValues values = new ContentValues(1);
|
||||
values.put(FaviconColumns.FAVICON_ID, faviconId);
|
||||
db.update(TABLE_HISTORY, values, History.URL + " = ?",
|
||||
new String[] { c.getString(c.getColumnIndexOrThrow(Obsolete.Images.URL)) });
|
||||
db.update(TABLE_BOOKMARKS, values, Bookmarks.URL + " = ?",
|
||||
new String[] { c.getString(c.getColumnIndexOrThrow(Obsolete.Images.URL)) });
|
||||
}
|
||||
} finally {
|
||||
if (c != null)
|
||||
c.close();
|
||||
db.execSQL("ALTER TABLE " + TABLE_HISTORY +
|
||||
" ADD COLUMN " + History.FAVICON_ID + " INTEGER");
|
||||
db.execSQL("ALTER TABLE " + TABLE_BOOKMARKS +
|
||||
" ADD COLUMN " + Bookmarks.FAVICON_ID + " INTEGER");
|
||||
} catch (SQLException e) {
|
||||
// Don't care.
|
||||
debug("Exception adding favicon_id column. We're probably fine." + e);
|
||||
}
|
||||
|
||||
createThumbnailsTable(db);
|
||||
|
||||
// Import thumbnails into the thumbnails table
|
||||
db.execSQL("INSERT INTO " + TABLE_THUMBNAILS + " ("
|
||||
+ Thumbnails.URL + ", "
|
||||
+ Thumbnails.DATA + ") "
|
||||
+ "SELECT " + Obsolete.Images.URL + ", " + Obsolete.Images.THUMBNAIL
|
||||
+ " FROM " + Obsolete.TABLE_IMAGES
|
||||
+ " WHERE " + Obsolete.Images.THUMBNAIL + " IS NOT NULL");
|
||||
|
||||
db.execSQL("DROP VIEW IF EXISTS " + Obsolete.VIEW_BOOKMARKS_WITH_IMAGES);
|
||||
db.execSQL("DROP VIEW IF EXISTS " + Obsolete.VIEW_HISTORY_WITH_IMAGES);
|
||||
db.execSQL("DROP VIEW IF EXISTS " + Obsolete.VIEW_COMBINED_WITH_IMAGES);
|
||||
db.execSQL("DROP VIEW IF EXISTS " + VIEW_COMBINED);
|
||||
db.execSQL("DROP VIEW IF EXISTS bookmarks_with_images");
|
||||
db.execSQL("DROP VIEW IF EXISTS history_with_images");
|
||||
db.execSQL("DROP VIEW IF EXISTS combined_with_images");
|
||||
|
||||
createBookmarksWithFaviconsView(db);
|
||||
createHistoryWithFaviconsView(db);
|
||||
createCombinedViewOn13(db);
|
||||
|
||||
db.execSQL("DROP TABLE IF EXISTS " + Obsolete.TABLE_IMAGES);
|
||||
db.execSQL("DROP TABLE IF EXISTS images");
|
||||
}
|
||||
|
||||
private void upgradeDatabaseFrom13to14(SQLiteDatabase db) {
|
||||
|
@ -1425,26 +777,10 @@ final class BrowserDatabaseHelper extends SQLiteOpenHelper {
|
|||
// database schema version.
|
||||
for (int v = oldVersion + 1; v <= newVersion; v++) {
|
||||
switch(v) {
|
||||
case 2:
|
||||
upgradeDatabaseFrom1to2(db);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
upgradeDatabaseFrom2to3(db);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
upgradeDatabaseFrom3to4(db);
|
||||
break;
|
||||
|
||||
case 5:
|
||||
upgradeDatabaseFrom4to5(db);
|
||||
break;
|
||||
|
||||
case 6:
|
||||
upgradeDatabaseFrom5to6(db);
|
||||
break;
|
||||
|
||||
case 7:
|
||||
upgradeDatabaseFrom6to7(db);
|
||||
break;
|
||||
|
@ -1453,22 +789,10 @@ final class BrowserDatabaseHelper extends SQLiteOpenHelper {
|
|||
upgradeDatabaseFrom7to8(db);
|
||||
break;
|
||||
|
||||
case 9:
|
||||
upgradeDatabaseFrom8to9(db);
|
||||
break;
|
||||
|
||||
case 10:
|
||||
upgradeDatabaseFrom9to10(db);
|
||||
break;
|
||||
|
||||
case 11:
|
||||
upgradeDatabaseFrom10to11(db);
|
||||
break;
|
||||
|
||||
case 12:
|
||||
upgradeDatabaseFrom11to12(db);
|
||||
break;
|
||||
|
||||
case 13:
|
||||
upgradeDatabaseFrom12to13(db);
|
||||
break;
|
||||
|
@ -1507,14 +831,12 @@ final class BrowserDatabaseHelper extends SQLiteOpenHelper {
|
|||
table.onUpgrade(db, oldVersion, newVersion);
|
||||
}
|
||||
|
||||
// If an upgrade after 12->13 fails, the entire upgrade is rolled
|
||||
// back, but we can't undo the deletion of favicon_urls.db if we
|
||||
// delete this in step 13; therefore, we wait until all steps are
|
||||
// complete before removing it.
|
||||
if (oldVersion < 13 && newVersion >= 13
|
||||
&& mContext.getDatabasePath(Obsolete.FAVICON_DB).exists()
|
||||
&& !mContext.deleteDatabase(Obsolete.FAVICON_DB)) {
|
||||
throw new SQLException("Could not delete " + Obsolete.FAVICON_DB);
|
||||
// Delete the obsolete favicon database after all other upgrades complete.
|
||||
// This can probably equivalently be moved into upgradeDatabaseFrom12to13.
|
||||
if (oldVersion < 13 && newVersion >= 13) {
|
||||
if (mContext.getDatabasePath("favicon_urls.db").exists()) {
|
||||
mContext.deleteDatabase("favicon_urls.db");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1559,10 +881,6 @@ final class BrowserDatabaseHelper extends SQLiteOpenHelper {
|
|||
}
|
||||
}
|
||||
|
||||
private static final String qualifyColumn(String table, String column) {
|
||||
return DBUtils.qualifyColumn(table, column);
|
||||
}
|
||||
|
||||
// Calculate these once, at initialization. isLoggable is too expensive to
|
||||
// have in-line in each log call.
|
||||
private static final boolean logDebug = Log.isLoggable(LOGTAG, Log.DEBUG);
|
||||
|
|
|
@ -37,7 +37,6 @@ public class AndroidBrowserBookmarksDataAccessor extends AndroidBrowserRepositor
|
|||
private static final String GUID_SHOULD_TRACK = BrowserContract.SyncColumns.GUID + " NOT IN ('" +
|
||||
BrowserContract.Bookmarks.TAGS_FOLDER_GUID + "', '" +
|
||||
BrowserContract.Bookmarks.PLACES_FOLDER_GUID + "', '" +
|
||||
BrowserContract.Bookmarks.READING_LIST_FOLDER_GUID + "', '" +
|
||||
BrowserContract.Bookmarks.PINNED_FOLDER_GUID + "')";
|
||||
|
||||
private static final String EXCLUDE_SPECIAL_GUIDS_WHERE_CLAUSE;
|
||||
|
|
|
@ -203,8 +203,6 @@ public class AndroidBrowserBookmarksRepositorySession extends AndroidBrowserRepo
|
|||
*/
|
||||
public static boolean forbiddenGUID(final String recordGUID) {
|
||||
return recordGUID == null ||
|
||||
// Temporarily exclude reading list items (Bug 762118; re-enable in Bug 762109.)
|
||||
BrowserContract.Bookmarks.READING_LIST_FOLDER_GUID.equals(recordGUID) ||
|
||||
BrowserContract.Bookmarks.PINNED_FOLDER_GUID.equals(recordGUID) ||
|
||||
BrowserContract.Bookmarks.PLACES_FOLDER_GUID.equals(recordGUID) ||
|
||||
BrowserContract.Bookmarks.TAGS_FOLDER_GUID.equals(recordGUID);
|
||||
|
@ -221,8 +219,6 @@ public class AndroidBrowserBookmarksRepositorySession extends AndroidBrowserRepo
|
|||
*/
|
||||
public static boolean forbiddenParent(final String parentGUID) {
|
||||
return parentGUID == null ||
|
||||
// Temporarily exclude reading list items (Bug 762118; re-enable in Bug 762109.)
|
||||
BrowserContract.Bookmarks.READING_LIST_FOLDER_GUID.equals(parentGUID) ||
|
||||
BrowserContract.Bookmarks.PINNED_FOLDER_GUID.equals(parentGUID);
|
||||
}
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ public class testBrowserProvider extends ContentProviderTest {
|
|||
}
|
||||
|
||||
private void ensureEmptyDatabase() throws Exception {
|
||||
Cursor c = null;
|
||||
Cursor c;
|
||||
|
||||
String guid = BrowserContract.Bookmarks.GUID;
|
||||
|
||||
|
@ -50,18 +50,16 @@ public class testBrowserProvider extends ContentProviderTest {
|
|||
guid + " != ? AND " +
|
||||
guid + " != ? AND " +
|
||||
guid + " != ? AND " +
|
||||
guid + " != ? AND " +
|
||||
guid + " != ?",
|
||||
new String[] { BrowserContract.Bookmarks.PLACES_FOLDER_GUID,
|
||||
BrowserContract.Bookmarks.MOBILE_FOLDER_GUID,
|
||||
BrowserContract.Bookmarks.MENU_FOLDER_GUID,
|
||||
BrowserContract.Bookmarks.TAGS_FOLDER_GUID,
|
||||
BrowserContract.Bookmarks.TOOLBAR_FOLDER_GUID,
|
||||
BrowserContract.Bookmarks.UNFILED_FOLDER_GUID,
|
||||
BrowserContract.Bookmarks.READING_LIST_FOLDER_GUID });
|
||||
BrowserContract.Bookmarks.UNFILED_FOLDER_GUID });
|
||||
|
||||
c = mProvider.query(appendUriParam(BrowserContract.Bookmarks.CONTENT_URI, BrowserContract.PARAM_SHOW_DELETED, "1"), null, null, null, null);
|
||||
assertCountIsAndClose(c, 7, "All non-special bookmarks and folders were deleted");
|
||||
assertCountIsAndClose(c, 6, "All non-special bookmarks and folders were deleted");
|
||||
|
||||
mProvider.delete(appendUriParam(BrowserContract.History.CONTENT_URI, BrowserContract.PARAM_IS_SYNC, "1"), null, null);
|
||||
c = mProvider.query(appendUriParam(BrowserContract.History.CONTENT_URI, BrowserContract.PARAM_SHOW_DELETED, "1"), null, null, null, null);
|
||||
|
|
|
@ -50,7 +50,7 @@ public class TestBookmarks extends AndroidSyncTestCase {
|
|||
protected static final String LOG_TAG = "BookmarksTest";
|
||||
|
||||
/**
|
||||
* Trivial test that forbidden records (reading list prior to Bug 762109, pinned items…)
|
||||
* Trivial test that forbidden records such as pinned items
|
||||
* will be ignored if processed.
|
||||
*/
|
||||
public void testForbiddenItemsAreIgnored() {
|
||||
|
@ -58,32 +58,25 @@ public class TestBookmarks extends AndroidSyncTestCase {
|
|||
final long now = System.currentTimeMillis();
|
||||
final String bookmarksCollection = "bookmarks";
|
||||
|
||||
final BookmarkRecord toRead = new BookmarkRecord("daaaaaaaaaaa", "bookmarks", now - 1, false);
|
||||
final BookmarkRecord pinned = new BookmarkRecord("pinpinpinpin", "bookmarks", now - 1, false);
|
||||
final BookmarkRecord normal = new BookmarkRecord("baaaaaaaaaaa", "bookmarks", now - 2, false);
|
||||
|
||||
final BookmarkRecord readingList = new BookmarkRecord(Bookmarks.READING_LIST_FOLDER_GUID,
|
||||
bookmarksCollection, now - 3, false);
|
||||
final BookmarkRecord pinnedItems = new BookmarkRecord(Bookmarks.PINNED_FOLDER_GUID,
|
||||
bookmarksCollection, now - 4, false);
|
||||
|
||||
toRead.type = normal.type = pinned.type = "bookmark";
|
||||
readingList.type = "folder";
|
||||
normal.type = "bookmark";
|
||||
pinned.type = "bookmark";
|
||||
pinnedItems.type = "folder";
|
||||
|
||||
toRead.parentID = Bookmarks.READING_LIST_FOLDER_GUID;
|
||||
pinned.parentID = Bookmarks.PINNED_FOLDER_GUID;
|
||||
normal.parentID = Bookmarks.TOOLBAR_FOLDER_GUID;
|
||||
|
||||
readingList.parentID = Bookmarks.PLACES_FOLDER_GUID;
|
||||
pinnedItems.parentID = Bookmarks.PLACES_FOLDER_GUID;
|
||||
|
||||
inBegunSession(repo, new SimpleSuccessBeginDelegate() {
|
||||
@Override
|
||||
public void onBeginSucceeded(RepositorySession session) {
|
||||
assertTrue(((AndroidBrowserBookmarksRepositorySession) session).shouldIgnore(toRead));
|
||||
assertTrue(((AndroidBrowserBookmarksRepositorySession) session).shouldIgnore(pinned));
|
||||
assertTrue(((AndroidBrowserBookmarksRepositorySession) session).shouldIgnore(readingList));
|
||||
assertTrue(((AndroidBrowserBookmarksRepositorySession) session).shouldIgnore(pinnedItems));
|
||||
assertFalse(((AndroidBrowserBookmarksRepositorySession) session).shouldIgnore(normal));
|
||||
finishAndNotify(session);
|
||||
|
@ -115,24 +108,6 @@ public class TestBookmarks extends AndroidSyncTestCase {
|
|||
assertFalse(guids.contains("dapinneditem"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Trivial test that reading list records will be skipped if present in the DB.
|
||||
*/
|
||||
public void testReadingListIsNotRetrieved() {
|
||||
final AndroidBrowserBookmarksRepository repo = new AndroidBrowserBookmarksRepository();
|
||||
|
||||
// Ensure that it exists.
|
||||
setUpFennecReadingListRecord();
|
||||
|
||||
// It's there in the DB…
|
||||
final ArrayList<String> roots = fetchChildrenDirect(BrowserContract.Bookmarks.FIXED_ROOT_ID);
|
||||
Logger.info(LOG_TAG, "Roots: " + roots);
|
||||
assertTrue(roots.contains(Bookmarks.READING_LIST_FOLDER_GUID));
|
||||
|
||||
// … but not when we fetch.
|
||||
assertFalse(fetchGUIDs(repo).contains(Bookmarks.READING_LIST_FOLDER_GUID));
|
||||
}
|
||||
|
||||
public void testRetrieveFolderHasAccurateChildren() {
|
||||
AndroidBrowserBookmarksRepository repo = new AndroidBrowserBookmarksRepository();
|
||||
|
||||
|
@ -864,17 +839,6 @@ public class TestBookmarks extends AndroidSyncTestCase {
|
|||
return values;
|
||||
}
|
||||
|
||||
protected ContentValues fennecReadingListRecord() {
|
||||
final ContentValues values = specialFolder();
|
||||
final String title = getApplicationContext().getResources().getString(R.string.bookmarks_folder_reading_list);
|
||||
|
||||
values.put(BrowserContract.SyncColumns.GUID, Bookmarks.READING_LIST_FOLDER_GUID);
|
||||
values.put(Bookmarks._ID, Bookmarks.FIXED_READING_LIST_ID);
|
||||
values.put(Bookmarks.PARENT, Bookmarks.FIXED_ROOT_ID);
|
||||
values.put(Bookmarks.TITLE, title);
|
||||
return values;
|
||||
}
|
||||
|
||||
protected long setUpFennecMobileRecordWithoutTitle() {
|
||||
ContentResolver cr = getApplicationContext().getContentResolver();
|
||||
ContentValues values = fennecMobileRecordWithoutTitle();
|
||||
|
@ -897,10 +861,6 @@ public class TestBookmarks extends AndroidSyncTestCase {
|
|||
insertRow(fennecPinnedChildItemRecord());
|
||||
}
|
||||
|
||||
protected void setUpFennecReadingListRecord() {
|
||||
insertRow(fennecReadingListRecord());
|
||||
}
|
||||
|
||||
//
|
||||
// Fennec fake layer.
|
||||
//
|
||||
|
|
|
@ -4509,6 +4509,12 @@
|
|||
"n_values": 100,
|
||||
"description": "Security UI Telemetry"
|
||||
},
|
||||
"JS_TELEMETRY_ADDON_EXCEPTIONS" : {
|
||||
"expires_in_version" : "never",
|
||||
"kind": "count",
|
||||
"keyed" : true,
|
||||
"description" : "Exceptions thrown by add-ons"
|
||||
},
|
||||
"SEARCH_COUNTS": {
|
||||
"expires_in_version": "never",
|
||||
"kind": "count",
|
||||
|
|
|
@ -107,7 +107,7 @@ BreakpointStore.prototype = {
|
|||
* @returns Object aBreakpoint
|
||||
* The new or existing breakpoint.
|
||||
*/
|
||||
addBreakpoint: function (aBreakpoint) {
|
||||
addBreakpoint: function (aBreakpoint, aActor) {
|
||||
let { source: { actor }, line, column } = aBreakpoint;
|
||||
|
||||
if (column != null) {
|
||||
|
@ -119,7 +119,7 @@ BreakpointStore.prototype = {
|
|||
}
|
||||
|
||||
if (!this._breakpoints[actor][line][column]) {
|
||||
this._breakpoints[actor][line][column] = aBreakpoint;
|
||||
this._breakpoints[actor][line][column] = aActor;
|
||||
this._size++;
|
||||
}
|
||||
return this._breakpoints[actor][line][column];
|
||||
|
@ -130,7 +130,7 @@ BreakpointStore.prototype = {
|
|||
}
|
||||
|
||||
if (!this._wholeLineBreakpoints[actor][line]) {
|
||||
this._wholeLineBreakpoints[actor][line] = aBreakpoint;
|
||||
this._wholeLineBreakpoints[actor][line] = aActor;
|
||||
this._size++;
|
||||
}
|
||||
return this._wholeLineBreakpoints[actor][line];
|
||||
|
@ -178,53 +178,6 @@ BreakpointStore.prototype = {
|
|||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Move the breakpoint to the new location.
|
||||
*
|
||||
* @param Object aBreakpoint
|
||||
* The breakpoint being moved. See `addBreakpoint` for a description of
|
||||
* its expected properties.
|
||||
* @param Object aNewLocation
|
||||
* The location to move the breakpoint to. Properties:
|
||||
* - line
|
||||
* - column (optional; omission implies whole line breakpoint)
|
||||
*/
|
||||
moveBreakpoint: function (aBreakpoint, aNewLocation) {
|
||||
const existingBreakpoint = this.getBreakpoint(aBreakpoint);
|
||||
this.removeBreakpoint(existingBreakpoint);
|
||||
|
||||
const { line, column } = aNewLocation;
|
||||
existingBreakpoint.line = line;
|
||||
existingBreakpoint.column = column;
|
||||
this.addBreakpoint(existingBreakpoint);
|
||||
},
|
||||
|
||||
/**
|
||||
* Get a breakpoint from the breakpoint store. Will throw an error if the
|
||||
* breakpoint is not found.
|
||||
*
|
||||
* @param Object aLocation
|
||||
* The location of the breakpoint you are retrieving. It is an object
|
||||
* with the following properties:
|
||||
* - source
|
||||
* - line
|
||||
* - column (optional)
|
||||
*/
|
||||
getBreakpoint: function (aLocation) {
|
||||
let { source: { actor, url }, line, column } = aLocation;
|
||||
dbg_assert(actor != null);
|
||||
dbg_assert(line != null);
|
||||
|
||||
var foundBreakpoint = this.hasBreakpoint(aLocation);
|
||||
if (foundBreakpoint == null) {
|
||||
throw new Error("No breakpoint at = " + (url || actor)
|
||||
+ ", line = " + line
|
||||
+ ", column = " + column);
|
||||
}
|
||||
|
||||
return foundBreakpoint;
|
||||
},
|
||||
|
||||
/**
|
||||
* Checks if the breakpoint store has a requested breakpoint.
|
||||
*
|
||||
|
@ -236,16 +189,16 @@ BreakpointStore.prototype = {
|
|||
* - column (optional)
|
||||
* @returns The stored breakpoint if it exists, null otherwise.
|
||||
*/
|
||||
hasBreakpoint: function (aLocation) {
|
||||
getBreakpoint: function (aLocation) {
|
||||
let { source: { actor }, line, column } = aLocation;
|
||||
dbg_assert(actor != null);
|
||||
dbg_assert(line != null);
|
||||
for (let bp of this.findBreakpoints(aLocation)) {
|
||||
for (let actor of this.findBreakpoints(aLocation)) {
|
||||
// We will get whole line breakpoints before individual columns, so just
|
||||
// return the first one and if they didn't specify a column then they will
|
||||
// get the whole line breakpoint, and otherwise we will find the correct
|
||||
// one.
|
||||
return bp;
|
||||
return actor;
|
||||
}
|
||||
|
||||
return null;
|
||||
|
@ -275,7 +228,7 @@ BreakpointStore.prototype = {
|
|||
for (let actor of this._iterActors(actor)) {
|
||||
for (let line of this._iterLines(actor, aSearchParams.line)) {
|
||||
// Always yield whole line breakpoints first. See comment in
|
||||
// |BreakpointStore.prototype.hasBreakpoint|.
|
||||
// |BreakpointStore.prototype.getBreakpoint|.
|
||||
if (aSearchParams.column == null
|
||||
&& this._wholeLineBreakpoints[actor]
|
||||
&& this._wholeLineBreakpoints[actor][line]) {
|
||||
|
@ -1330,18 +1283,16 @@ ThreadActor.prototype = {
|
|||
for (let line = 0, n = offsets.length; line < n; line++) {
|
||||
if (offsets[line]) {
|
||||
let location = { line: line };
|
||||
let resp = sourceActor.createAndStoreBreakpoint(location);
|
||||
let resp = sourceActor._setBreakpoint(location);
|
||||
dbg_assert(!resp.actualLocation, "No actualLocation should be returned");
|
||||
if (resp.error) {
|
||||
reportError(new Error("Unable to set breakpoint on event listener"));
|
||||
return;
|
||||
}
|
||||
let bp = this.breakpointStore.getBreakpoint({
|
||||
let bpActor = this.breakpointStore.getBreakpoint({
|
||||
source: sourceActor.form(),
|
||||
line: location.line
|
||||
});
|
||||
let bpActor = bp.actor;
|
||||
dbg_assert(bp, "Breakpoint must exist");
|
||||
dbg_assert(bpActor, "Breakpoint actor must be created");
|
||||
this._hiddenBreakpoints.set(bpActor.actorID, bpActor);
|
||||
break;
|
||||
|
@ -1496,10 +1447,8 @@ ThreadActor.prototype = {
|
|||
* caches won't hold on to the Debugger.Script objects leaking memory.
|
||||
*/
|
||||
disableAllBreakpoints: function () {
|
||||
for (let bp of this.breakpointStore.findBreakpoints()) {
|
||||
if (bp.actor) {
|
||||
bp.actor.removeScripts();
|
||||
}
|
||||
for (let bpActor of this.breakpointStore.findBreakpoints()) {
|
||||
bpActor.removeScripts();
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -2153,11 +2102,11 @@ ThreadActor.prototype = {
|
|||
|
||||
let endLine = aScript.startLine + aScript.lineCount - 1;
|
||||
let source = this.sources.source({ source: aScript.source });
|
||||
for (let bp of this.breakpointStore.findBreakpoints(source.form())) {
|
||||
for (let bpActor of this.breakpointStore.findBreakpoints({ source: source.form() })) {
|
||||
// Limit the search to the line numbers contained in the new script.
|
||||
if (bp.line >= aScript.startLine
|
||||
&& bp.line <= endLine) {
|
||||
source._setBreakpoint(bp, aScript);
|
||||
if (bpActor.location.line >= aScript.startLine
|
||||
&& bpActor.location.line <= endLine) {
|
||||
source._setBreakpoint(bpActor.location, aScript);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2841,7 +2790,7 @@ SourceActor.prototype = {
|
|||
|
||||
_createBreakpoint: function(loc, originalLoc, condition) {
|
||||
return resolve(null).then(() => {
|
||||
return this.createAndStoreBreakpoint({
|
||||
return this._setBreakpoint({
|
||||
line: loc.line,
|
||||
column: loc.column,
|
||||
condition: condition
|
||||
|
@ -2904,23 +2853,6 @@ SourceActor.prototype = {
|
|||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Create a breakpoint at the specified location and store it in the
|
||||
* cache. Takes ownership of `aRequest`. This is the
|
||||
* generated location if this source is sourcemapped.
|
||||
* Used by the XPCShell test harness to set breakpoints in a script before
|
||||
* it has loaded.
|
||||
*
|
||||
* @param Object aRequest
|
||||
* An object of the form { line[, column, condition] }. The
|
||||
* location is in the generated source, if sourcemapped.
|
||||
*/
|
||||
createAndStoreBreakpoint: function (aRequest) {
|
||||
let bp = update({}, aRequest, { source: this.form() });
|
||||
this.breakpointStore.addBreakpoint(bp);
|
||||
return this._setBreakpoint(aRequest);
|
||||
},
|
||||
|
||||
/** Get or create the BreakpointActor for the breakpoint at the given location.
|
||||
*
|
||||
* NB: This will override a pre-existing BreakpointActor's condition with
|
||||
|
@ -2932,22 +2864,20 @@ SourceActor.prototype = {
|
|||
* @returns BreakpointActor
|
||||
*/
|
||||
_getOrCreateBreakpointActor: function (location) {
|
||||
let actor;
|
||||
const storedBp = this.breakpointStore.getBreakpoint(location);
|
||||
|
||||
if (storedBp.actor) {
|
||||
actor = storedBp.actor;
|
||||
actor.condition = location.condition;
|
||||
let actor = this.breakpointStore.getBreakpoint(location);
|
||||
if (!actor) {
|
||||
actor = new BreakpointActor(this.threadActor, {
|
||||
sourceActor: this,
|
||||
line: location.line,
|
||||
column: location.column,
|
||||
condition: location.condition
|
||||
});
|
||||
this.threadActor.threadLifetimePool.addActor(actor);
|
||||
this.breakpointStore.addBreakpoint(location, actor);
|
||||
return actor;
|
||||
}
|
||||
|
||||
storedBp.actor = actor = new BreakpointActor(this.threadActor, {
|
||||
sourceActor: this,
|
||||
line: location.line,
|
||||
column: location.column,
|
||||
condition: location.condition
|
||||
});
|
||||
this.threadActor.threadLifetimePool.addActor(actor);
|
||||
actor.condition = location.condition;
|
||||
return actor;
|
||||
},
|
||||
|
||||
|
@ -3112,12 +3042,12 @@ SourceActor.prototype = {
|
|||
// above is redundant and must be destroyed. If we do not have an existing
|
||||
// actor, we need to update the breakpoint store with the new location.
|
||||
|
||||
const existingBreakpoint = this.breakpointStore.hasBreakpoint(actualLocation);
|
||||
if (existingBreakpoint && existingBreakpoint.actor) {
|
||||
let existingActor = this.breakpointStore.getBreakpoint(actualLocation);
|
||||
if (existingActor) {
|
||||
actor.onDelete();
|
||||
this.breakpointStore.removeBreakpoint(location);
|
||||
return {
|
||||
actor: existingBreakpoint.actor.actorID,
|
||||
actor: existingActor.actorID,
|
||||
actualLocation
|
||||
};
|
||||
} else {
|
||||
|
@ -3126,7 +3056,8 @@ SourceActor.prototype = {
|
|||
sourceActor: this,
|
||||
line: actualLocation.line
|
||||
};
|
||||
this.breakpointStore.moveBreakpoint(location, actualLocation);
|
||||
this.breakpointStore.removeBreakpoint(location);
|
||||
this.breakpointStore.addBreakpoint(actualLocation, actor);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,15 +11,14 @@ function run_test()
|
|||
Cu.import("resource://gre/modules/jsdebugger.jsm");
|
||||
addDebuggerToGlobal(this);
|
||||
|
||||
test_has_breakpoint();
|
||||
test_get_breakpoint();
|
||||
test_add_breakpoint();
|
||||
test_remove_breakpoint();
|
||||
test_find_breakpoints();
|
||||
test_duplicate_breakpoints();
|
||||
test_move_breakpoint();
|
||||
}
|
||||
|
||||
function test_has_breakpoint() {
|
||||
function test_get_breakpoint() {
|
||||
let bpStore = new BreakpointStore();
|
||||
let location = {
|
||||
source: { actor: 'actor1' },
|
||||
|
@ -32,27 +31,27 @@ function test_has_breakpoint() {
|
|||
};
|
||||
|
||||
// Shouldn't have breakpoint
|
||||
do_check_eq(null, bpStore.hasBreakpoint(location),
|
||||
do_check_eq(null, bpStore.getBreakpoint(location),
|
||||
"Breakpoint not added and shouldn't exist.");
|
||||
|
||||
bpStore.addBreakpoint(location);
|
||||
do_check_true(!!bpStore.hasBreakpoint(location),
|
||||
bpStore.addBreakpoint(location, {});
|
||||
do_check_true(!!bpStore.getBreakpoint(location),
|
||||
"Breakpoint added but not found in Breakpoint Store.");
|
||||
|
||||
bpStore.removeBreakpoint(location);
|
||||
do_check_eq(null, bpStore.hasBreakpoint(location),
|
||||
do_check_eq(null, bpStore.getBreakpoint(location),
|
||||
"Breakpoint removed but still exists.");
|
||||
|
||||
// Same checks for breakpoint with a column
|
||||
do_check_eq(null, bpStore.hasBreakpoint(columnLocation),
|
||||
do_check_eq(null, bpStore.getBreakpoint(columnLocation),
|
||||
"Breakpoint with column not added and shouldn't exist.");
|
||||
|
||||
bpStore.addBreakpoint(columnLocation);
|
||||
do_check_true(!!bpStore.hasBreakpoint(columnLocation),
|
||||
bpStore.addBreakpoint(columnLocation, {});
|
||||
do_check_true(!!bpStore.getBreakpoint(columnLocation),
|
||||
"Breakpoint with column added but not found in Breakpoint Store.");
|
||||
|
||||
bpStore.removeBreakpoint(columnLocation);
|
||||
do_check_eq(null, bpStore.hasBreakpoint(columnLocation),
|
||||
do_check_eq(null, bpStore.getBreakpoint(columnLocation),
|
||||
"Breakpoint with column removed but still exists in Breakpoint Store.");
|
||||
}
|
||||
|
||||
|
@ -64,8 +63,8 @@ function test_add_breakpoint() {
|
|||
line: 10,
|
||||
column: 9
|
||||
};
|
||||
bpStore.addBreakpoint(location);
|
||||
do_check_true(!!bpStore.hasBreakpoint(location),
|
||||
bpStore.addBreakpoint(location, {});
|
||||
do_check_true(!!bpStore.getBreakpoint(location),
|
||||
"We should have the column breakpoint we just added");
|
||||
|
||||
// Breakpoint without column (whole line breakpoint)
|
||||
|
@ -73,8 +72,8 @@ function test_add_breakpoint() {
|
|||
source: { actor: 'actor2' },
|
||||
line: 103
|
||||
};
|
||||
bpStore.addBreakpoint(location);
|
||||
do_check_true(!!bpStore.hasBreakpoint(location),
|
||||
bpStore.addBreakpoint(location, {});
|
||||
do_check_true(!!bpStore.getBreakpoint(location),
|
||||
"We should have the whole line breakpoint we just added");
|
||||
}
|
||||
|
||||
|
@ -86,9 +85,9 @@ function test_remove_breakpoint() {
|
|||
line: 10,
|
||||
column: 9
|
||||
};
|
||||
bpStore.addBreakpoint(location);
|
||||
bpStore.addBreakpoint(location, {});
|
||||
bpStore.removeBreakpoint(location);
|
||||
do_check_eq(bpStore.hasBreakpoint(location), null,
|
||||
do_check_eq(bpStore.getBreakpoint(location), null,
|
||||
"We should not have the column breakpoint anymore");
|
||||
|
||||
// Breakpoint without column (whole line breakpoint)
|
||||
|
@ -96,9 +95,9 @@ function test_remove_breakpoint() {
|
|||
source: { actor: 'actor2' },
|
||||
line: 103
|
||||
};
|
||||
bpStore.addBreakpoint(location);
|
||||
bpStore.addBreakpoint(location, {});
|
||||
bpStore.removeBreakpoint(location);
|
||||
do_check_eq(bpStore.hasBreakpoint(location), null,
|
||||
do_check_eq(bpStore.getBreakpoint(location), null,
|
||||
"We should not have the whole line breakpoint anymore");
|
||||
}
|
||||
|
||||
|
@ -117,7 +116,7 @@ function test_find_breakpoints() {
|
|||
let bpStore = new BreakpointStore();
|
||||
|
||||
for (let bp of bps) {
|
||||
bpStore.addBreakpoint(bp);
|
||||
bpStore.addBreakpoint(bp, bp);
|
||||
}
|
||||
|
||||
// All breakpoints
|
||||
|
@ -166,8 +165,8 @@ function test_duplicate_breakpoints() {
|
|||
line: 10,
|
||||
column: 9
|
||||
};
|
||||
bpStore.addBreakpoint(location);
|
||||
bpStore.addBreakpoint(location);
|
||||
bpStore.addBreakpoint(location, {});
|
||||
bpStore.addBreakpoint(location, {});
|
||||
do_check_eq(bpStore.size, 1, "We should have only 1 column breakpoint");
|
||||
bpStore.removeBreakpoint(location);
|
||||
|
||||
|
@ -176,36 +175,8 @@ function test_duplicate_breakpoints() {
|
|||
source: { actor: "foo-actor" },
|
||||
line: 15
|
||||
};
|
||||
bpStore.addBreakpoint(location);
|
||||
bpStore.addBreakpoint(location);
|
||||
bpStore.addBreakpoint(location, {});
|
||||
bpStore.addBreakpoint(location, {});
|
||||
do_check_eq(bpStore.size, 1, "We should have only 1 whole line breakpoint");
|
||||
bpStore.removeBreakpoint(location);
|
||||
}
|
||||
|
||||
function test_move_breakpoint() {
|
||||
let bpStore = new BreakpointStore();
|
||||
|
||||
let oldLocation = {
|
||||
source: { actor: "foo-actor" },
|
||||
line: 10
|
||||
};
|
||||
|
||||
let newLocation = {
|
||||
source: { actor: "foo-actor" },
|
||||
line: 12
|
||||
};
|
||||
|
||||
bpStore.addBreakpoint(oldLocation);
|
||||
bpStore.moveBreakpoint(oldLocation, newLocation);
|
||||
|
||||
equal(bpStore.size, 1, "Moving a breakpoint maintains the correct size.");
|
||||
|
||||
let bp = bpStore.getBreakpoint(newLocation);
|
||||
ok(bp, "We should be able to get a breakpoint at the new location.");
|
||||
equal(bp.line, newLocation.line,
|
||||
"We should get the moved line.");
|
||||
|
||||
equal(bpStore.hasBreakpoint({ source: { actor: "foo-actor" }, line: 10 }),
|
||||
null,
|
||||
"And we shouldn't be able to get any BP at the old location.");
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@ function test() {
|
|||
getInterface(SpecialPowers.Ci.nsIWebNavigation).
|
||||
QueryInterface(SpecialPowers.Ci.nsIDocShell);
|
||||
|
||||
webHandler.launchWithURI(uri, windowContext);
|
||||
webHandler.launchWithURI(uri, windowContext);
|
||||
|
||||
// if we get this far without an exception, we've at least partly passed
|
||||
// (remaining check in handlerApp.xhtml)
|
||||
|
|
Загрузка…
Ссылка в новой задаче