Merge m-i and f-t to m-c, a=merge

This commit is contained in:
Phil Ringnalda 2014-09-01 22:45:56 -07:00
commit 3b25cb1121
11 changed files with 124 additions and 43 deletions

View File

@ -101,7 +101,7 @@ loop.Client = (function($) {
* Callback parameters:
* - err null on successful registration, non-null otherwise.
* - callUrlData an object of the obtained call url data if successful:
* -- call_url: The url of the call
* -- callUrl: The url of the call
* -- expiresAt: The amount of hours until expiry of the url
*
* @param {String} simplepushUrl a registered Simple Push URL
@ -120,8 +120,6 @@ loop.Client = (function($) {
var urlData = JSON.parse(responseText);
cb(null, this._validate(urlData, expectedCallUrlProperties));
this.mozLoop.noteCallUrlExpiry(urlData.expiresAt);
} catch (err) {
console.log("Error requesting call info", err);
cb(err);
@ -159,8 +157,6 @@ loop.Client = (function($) {
try {
cb(null);
this.mozLoop.noteCallUrlExpiry((new Date()).getTime() / 1000);
} catch (err) {
console.log("Error deleting call info", err);
cb(err);
@ -175,7 +171,7 @@ loop.Client = (function($) {
* Callback parameters:
* - err null on successful registration, non-null otherwise.
* - callUrlData an object of the obtained call url data if successful:
* -- call_url: The url of the call
* -- callUrl: The url of the call
* -- expiresAt: The amount of hours until expiry of the url
*
* @param {String} simplepushUrl a registered Simple Push URL

View File

@ -259,16 +259,18 @@ loop.panel = (function(_, mozL10n) {
var CallUrlResult = React.createClass({displayName: 'CallUrlResult',
propTypes: {
callUrl: React.PropTypes.string,
notifier: React.PropTypes.object.isRequired,
client: React.PropTypes.object.isRequired
callUrl: React.PropTypes.string,
callUrlExpiry: React.PropTypes.number,
notifier: React.PropTypes.object.isRequired,
client: React.PropTypes.object.isRequired
},
getInitialState: function() {
return {
pending: false,
copied: false,
callUrl: this.props.callUrl || ""
callUrl: this.props.callUrl || "",
callUrlExpiry: 0
};
},
@ -307,7 +309,9 @@ loop.panel = (function(_, mozL10n) {
var token = callUrlData.callToken ||
callUrl.pathname.split('/').pop();
this.setState({pending: false, copied: false, callUrl: callUrl.href});
this.setState({pending: false, copied: false,
callUrl: callUrl.href,
callUrlExpiry: callUrlData.expiresAt});
} catch(e) {
console.log(e);
this.props.notifier.errorL10n("unable_retrieve_url");
@ -324,17 +328,26 @@ loop.panel = (function(_, mozL10n) {
},
handleEmailButtonClick: function(event) {
this.handleLinkExfiltration(event);
// Note: side effect
document.location = event.target.dataset.mailto;
},
handleCopyButtonClick: function(event) {
this.handleLinkExfiltration(event);
// XXX the mozLoop object should be passed as a prop, to ease testing and
// using a fake implementation in UI components showcase.
navigator.mozLoop.copyString(this.state.callUrl);
this.setState({copied: true});
},
handleLinkExfiltration: function(event) {
// TODO Bug 1015988 -- Increase link exfiltration telemetry count
if (this.state.callUrlExpiry) {
navigator.mozLoop.noteCallUrlExpiry(this.state.callUrlExpiry);
}
},
render: function() {
// XXX setting elem value from a state (in the callUrl input)
// makes it immutable ie read only but that is fine in our case.
@ -351,6 +364,7 @@ loop.panel = (function(_, mozL10n) {
PanelLayout({summary: __("share_link_header_text")},
React.DOM.div({className: "invite"},
React.DOM.input({type: "url", value: this.state.callUrl, readOnly: "true",
onCopy: this.handleLinkExfiltration,
className: inputCSSClass}),
React.DOM.p({className: "btn-group url-actions"},
React.DOM.button({className: "btn btn-email", disabled: !this.state.callUrl,

View File

@ -259,16 +259,18 @@ loop.panel = (function(_, mozL10n) {
var CallUrlResult = React.createClass({
propTypes: {
callUrl: React.PropTypes.string,
notifier: React.PropTypes.object.isRequired,
client: React.PropTypes.object.isRequired
callUrl: React.PropTypes.string,
callUrlExpiry: React.PropTypes.number,
notifier: React.PropTypes.object.isRequired,
client: React.PropTypes.object.isRequired
},
getInitialState: function() {
return {
pending: false,
copied: false,
callUrl: this.props.callUrl || ""
callUrl: this.props.callUrl || "",
callUrlExpiry: 0
};
},
@ -307,7 +309,9 @@ loop.panel = (function(_, mozL10n) {
var token = callUrlData.callToken ||
callUrl.pathname.split('/').pop();
this.setState({pending: false, copied: false, callUrl: callUrl.href});
this.setState({pending: false, copied: false,
callUrl: callUrl.href,
callUrlExpiry: callUrlData.expiresAt});
} catch(e) {
console.log(e);
this.props.notifier.errorL10n("unable_retrieve_url");
@ -324,17 +328,26 @@ loop.panel = (function(_, mozL10n) {
},
handleEmailButtonClick: function(event) {
this.handleLinkExfiltration(event);
// Note: side effect
document.location = event.target.dataset.mailto;
},
handleCopyButtonClick: function(event) {
this.handleLinkExfiltration(event);
// XXX the mozLoop object should be passed as a prop, to ease testing and
// using a fake implementation in UI components showcase.
navigator.mozLoop.copyString(this.state.callUrl);
this.setState({copied: true});
},
handleLinkExfiltration: function(event) {
// TODO Bug 1015988 -- Increase link exfiltration telemetry count
if (this.state.callUrlExpiry) {
navigator.mozLoop.noteCallUrlExpiry(this.state.callUrlExpiry);
}
},
render: function() {
// XXX setting elem value from a state (in the callUrl input)
// makes it immutable ie read only but that is fine in our case.
@ -351,6 +364,7 @@ loop.panel = (function(_, mozL10n) {
<PanelLayout summary={__("share_link_header_text")}>
<div className="invite">
<input type="url" value={this.state.callUrl} readOnly="true"
onCopy={this.handleLinkExfiltration}
className={inputCSSClass} />
<p className="btn-group url-actions">
<button className="btn btn-email" disabled={!this.state.callUrl}

View File

@ -84,20 +84,6 @@ describe("loop.Client", function() {
sinon.assert.calledWithExactly(callback, null);
});
it("should reset all url expiry when the request succeeds", function() {
// Sets up the hawkRequest stub to trigger the callback with no error
// and the url.
var dateInMilliseconds = new Date(2014,7,20).getTime();
hawkRequestStub.callsArgWith(3, null);
sandbox.useFakeTimers(dateInMilliseconds);
client.deleteCallUrl(fakeToken, callback);
sinon.assert.calledOnce(mozLoop.noteCallUrlExpiry);
sinon.assert.calledWithExactly(mozLoop.noteCallUrlExpiry,
dateInMilliseconds / 1000);
});
it("should send an error when the request fails", function() {
// Sets up the hawkRequest stub to trigger the callback with
// an error
@ -153,7 +139,7 @@ describe("loop.Client", function() {
sinon.assert.calledWithExactly(callback, null, callUrlData);
});
it("should note the call url expiry when the request succeeds",
it("should not update call url expiry when the request succeeds",
function() {
var callUrlData = {
"callUrl": "fakeCallUrl",
@ -167,9 +153,7 @@ describe("loop.Client", function() {
client.requestCallUrl("foo", callback);
sinon.assert.calledOnce(mozLoop.noteCallUrlExpiry);
sinon.assert.calledWithExactly(mozLoop.noteCallUrlExpiry,
6000);
sinon.assert.notCalled(mozLoop.noteCallUrlExpiry);
});
it("should send an error when the request fails", function() {

View File

@ -49,7 +49,8 @@ describe("loop.panel", function() {
},
setLoopCharPref: sandbox.stub(),
getLoopCharPref: sandbox.stub().returns("unseen"),
copyString: sandbox.stub()
copyString: sandbox.stub(),
noteCallUrlExpiry: sinon.spy()
};
document.mozL10n.initialize(navigator.mozLoop);
@ -412,7 +413,8 @@ describe("loop.panel", function() {
view.setState({
pending: false,
copied: false,
callUrl: "http://example.com"
callUrl: "http://example.com",
callUrlExpiry: 6000
});
TestUtils.Simulate.click(view.getDOMNode().querySelector(".btn-copy"));
@ -422,6 +424,68 @@ describe("loop.panel", function() {
view.state.callUrl);
});
it("should note the call url expiry when the url is copied via button",
function() {
var view = TestUtils.renderIntoDocument(loop.panel.CallUrlResult({
notifier: notifier,
client: fakeClient
}));
view.setState({
pending: false,
copied: false,
callUrl: "http://example.com",
callUrlExpiry: 6000
});
TestUtils.Simulate.click(view.getDOMNode().querySelector(".btn-copy"));
sinon.assert.calledOnce(navigator.mozLoop.noteCallUrlExpiry);
sinon.assert.calledWithExactly(navigator.mozLoop.noteCallUrlExpiry,
6000);
});
it("should note the call url expiry when the url is emailed",
function() {
var view = TestUtils.renderIntoDocument(loop.panel.CallUrlResult({
notifier: notifier,
client: fakeClient
}));
view.setState({
pending: false,
copied: false,
callUrl: "http://example.com",
callUrlExpiry: 6000
});
view.getDOMNode().querySelector(".btn-email").dataset.mailto = "#";
TestUtils.Simulate.click(view.getDOMNode().querySelector(".btn-email"));
sinon.assert.calledOnce(navigator.mozLoop.noteCallUrlExpiry);
sinon.assert.calledWithExactly(navigator.mozLoop.noteCallUrlExpiry,
6000);
});
it("should note the call url expiry when the url is copied manually",
function() {
var view = TestUtils.renderIntoDocument(loop.panel.CallUrlResult({
notifier: notifier,
client: fakeClient
}));
view.setState({
pending: false,
copied: false,
callUrl: "http://example.com",
callUrlExpiry: 6000
});
var urlField = view.getDOMNode().querySelector("input[type='url']");
TestUtils.Simulate.copy(urlField);
sinon.assert.calledOnce(navigator.mozLoop.noteCallUrlExpiry);
sinon.assert.calledWithExactly(navigator.mozLoop.noteCallUrlExpiry,
6000);
});
it("should notify the user when the operation failed", function() {
fakeClient.requestCallUrl = function(_, cb) {
cb("fake error");

View File

@ -374,7 +374,7 @@
#ifdef MOZ_ANDROID_SHARE_OVERLAY
<!-- Share overlay activity -->
<activity android:name="org.mozilla.gecko.overlays.ui.ShareDialog"
android:label="@string/overlay_share_header"
android:label="@string/overlay_share_label"
android:theme="@style/ShareOverlayActivity"
android:configChanges="keyboard|keyboardHidden|mcc|mnc|locale|layoutDirection"
android:windowSoftInputMode="stateAlwaysHidden|adjustResize">

View File

@ -951,7 +951,10 @@ public class LocalBrowserDB {
private void addBookmarkItem(ContentResolver cr, String title, String uri, long folderId) {
final long now = System.currentTimeMillis();
ContentValues values = new ContentValues();
values.put(Browser.BookmarkColumns.TITLE, title);
if (title != null) {
values.put(Browser.BookmarkColumns.TITLE, title);
}
values.put(Bookmarks.URL, uri);
values.put(Bookmarks.PARENT, folderId);
values.put(Bookmarks.DATE_MODIFIED, now);

View File

@ -90,12 +90,16 @@
to display browser chrome. -->
<!ENTITY locale_system_default "System default">
<!-- Localization note (overlay_share_label) : This is the label that appears
in Android's intent chooser when sending a link to Firefox to bookmark,
send to another device, or add to Reading List. -->
<!ENTITY overlay_share_label "Add to &brandShortName;">
<!-- Localization note (overlay_share_bookmark_btn_label) : This string is
used in the share overlay menu to select an action. It is the verb
"to bookmark", not the noun "a bookmark". -->
<!ENTITY overlay_share_bookmark_btn_label "Bookmark">
<!ENTITY overlay_share_reading_list_btn_label "Add to Reading List">
<!ENTITY overlay_share_header "Send to &brandShortName;">
<!ENTITY overlay_share_send_other "Send to other devices">
<!-- Localization note (overlay_share_send_tab_btn_label) : Used on the

View File

@ -19,7 +19,7 @@ public class AddBookmark extends ShareMethod {
ContentResolver resolver = context.getContentResolver();
LocalBrowserDB browserDB = new LocalBrowserDB(GeckoProfile.DEFAULT_PROFILE);
browserDB.addBookmark(resolver, url, title);
browserDB.addBookmark(resolver, title, url);
return Result.SUCCESS;
}

View File

@ -111,7 +111,7 @@
<string name="media_stop">&media_stop;</string>
<string name="overlay_share_send_other">&overlay_share_send_other;</string>
<string name="overlay_share_header">&overlay_share_header;</string>
<string name="overlay_share_label">&overlay_share_label;</string>
<string name="overlay_share_bookmark_btn_label">&overlay_share_bookmark_btn_label;</string>
<string name="overlay_share_reading_list_btn_label">&overlay_share_reading_list_btn_label;</string>
<string name="overlay_share_send_tab_btn_label">&overlay_share_send_tab_btn_label;</string>

View File

@ -81,8 +81,10 @@ else
MOZ_ANDROID_SEARCH_ACTIVITY=
fi
# Don't enable the share overlay.
# MOZ_ANDROID_SHARE_OVERLAY=1
# Enable the share handler in pre-release builds.
if test ! "$RELEASE_BUILD"; then
MOZ_ANDROID_SHARE_OVERLAY=1
fi
# Don't enable the Mozilla Location Service stumbler.
# MOZ_ANDROID_MLS_STUMBLER=1