Notify users when there's an error installing an app (bug 694414)
This commit is contained in:
Родитель
b4aebfbc20
Коммит
08020c28d9
|
@ -120,3 +120,7 @@
|
|||
{% endif %}
|
||||
{% endif %}
|
||||
</div> {# install-shell #}
|
||||
|
||||
{% if addon.is_webapp() %}
|
||||
{% include 'addons/includes/apps_error_msg.html' %}
|
||||
{% endif %}
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
<div class="apps-error-msg modal hidden popup error">
|
||||
<h2></h2>
|
||||
<p></p>
|
||||
</div>
|
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
Provides the apps module, a wrapper around navigator.mozApps
|
||||
*/
|
||||
(function(exports) {
|
||||
"use strict";
|
||||
|
||||
/*
|
||||
|
||||
apps.install(manifestUrl, options)
|
||||
|
||||
It's just like navigator.apps.install with the following enhancements:
|
||||
- If navigator.apps.install doesn't exist, an error is displayed
|
||||
- If the install resulted in errors, they are displayed to the user
|
||||
|
||||
This requires at least one apps-error-msg div to be present.
|
||||
|
||||
See also: https://developer.mozilla.org/en/Apps/Apps_JavaScript_API/navigator.mozApps.install
|
||||
|
||||
The recognized option attributes are as follows:
|
||||
|
||||
data
|
||||
Optional dict to pass as navigator.apps.install(url, data, ...)
|
||||
success
|
||||
Optional callback for when app installation was successful
|
||||
error
|
||||
Optional callback for when app installation resulted in error
|
||||
errModalCallback
|
||||
Callback to pass into $.modal(...)
|
||||
domContext
|
||||
Something other than document, useful for testing
|
||||
navigator
|
||||
Something other than the global navigator, useful for testing
|
||||
|
||||
*/
|
||||
exports.install = function(manifestUrl, opt) {
|
||||
opt = $.extend({'domContext': document,
|
||||
'navigator': navigator,
|
||||
'data': undefined,
|
||||
'success': undefined,
|
||||
'error': undefined,
|
||||
'errModalCallback': undefined}, opt || {});
|
||||
var self = this,
|
||||
errSummary,
|
||||
showError = true;
|
||||
/* Try and install the app. */
|
||||
if (opt.navigator.mozApps && opt.navigator.mozApps.install) {
|
||||
opt.navigator.mozApps.install(manifestUrl, opt.data, opt.success, function(errorOb) {
|
||||
switch (errorOb.code) {
|
||||
case 'denied':
|
||||
// User canceled installation.
|
||||
showError = false;
|
||||
break;
|
||||
case 'permissionDenied':
|
||||
errSummary = gettext('App installation not allowed');
|
||||
break;
|
||||
case 'manifestURLError':
|
||||
errSummary = gettext('App manifest is malformed');
|
||||
break;
|
||||
case 'networkError':
|
||||
errSummary = gettext('App host could not be reached');
|
||||
break;
|
||||
case 'manifestParseError':
|
||||
errSummary = gettext('App manifest is unparsable');
|
||||
break;
|
||||
case 'invalidManifest':
|
||||
errSummary = gettext('App manifest is invalid');
|
||||
break;
|
||||
default:
|
||||
errSummary = gettext('Unknown error');
|
||||
break;
|
||||
}
|
||||
if (showError) {
|
||||
self._showError(errSummary, errorOb.message, opt);
|
||||
}
|
||||
if (opt.error) {
|
||||
opt.error.call(this, errorOb);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
self._showError(gettext('App installation failed'),
|
||||
gettext('This system does not support installing apps'),
|
||||
opt);
|
||||
}
|
||||
};
|
||||
|
||||
exports._showError = function(errSummary, errMessage, opt) {
|
||||
var $errTarget = $('<a>'),
|
||||
$modal = $('.apps-error-msg:first', opt.domContext).modal(
|
||||
$errTarget,
|
||||
{width: '400px', close: true,
|
||||
callback: opt.errModalCallback});
|
||||
$errTarget.trigger('click'); // show the modal
|
||||
$('.apps-error-msg h2', opt.domContext).text(errSummary);
|
||||
$('.apps-error-msg p', opt.domContext).text(errMessage);
|
||||
$(opt.domContext).trigger('error_shown.apps');
|
||||
};
|
||||
|
||||
})(typeof exports === 'undefined' ? (this.apps = {}) : exports);
|
|
@ -127,16 +127,11 @@ var purchases = {
|
|||
}
|
||||
},
|
||||
install_app: function(url, receipt) {
|
||||
/* Try and install the app. */
|
||||
if (navigator.mozApps && navigator.mozApps.install) {
|
||||
var data = {};
|
||||
if(receipt) {
|
||||
data['receipt'] = receipt;
|
||||
}
|
||||
navigator.mozApps.install(url, data);
|
||||
} else {
|
||||
// Notify that it can't be installed.
|
||||
var data = {};
|
||||
if(receipt) {
|
||||
data['receipt'] = receipt;
|
||||
}
|
||||
apps.install(url, {data: data});
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -278,6 +278,10 @@
|
|||
|
||||
|
||||
function initWebapp() {
|
||||
//
|
||||
// TODO(Kumar) When this is fixed, integrate with
|
||||
// apps.install(manifestURL). See bug 699828
|
||||
//
|
||||
if (navigator.mozApps && navigator.mozApps.install) {
|
||||
dom.self.find('.button')
|
||||
.removeClass('disabled')
|
||||
|
|
|
@ -0,0 +1,162 @@
|
|||
$(document).ready(function(){
|
||||
|
||||
|
||||
module('apps errors', {
|
||||
setup: function() {
|
||||
this.sandbox = tests.createSandbox('#apps-error-msg');
|
||||
},
|
||||
teardown: function() {
|
||||
this.sandbox.remove();
|
||||
},
|
||||
installAppWithError: function(manifestUrl, errorOb, errModalCallback) {
|
||||
var sb = this.sandbox,
|
||||
nav = {};
|
||||
nav.mozApps = {
|
||||
install: function(manifestUrl, data, success, error) {
|
||||
error(errorOb);
|
||||
}
|
||||
};
|
||||
if (!errModalCallback) {
|
||||
errModalCallback = function() {
|
||||
// False tells the modal code not to execute all the dom
|
||||
// re-positioning for rendering. Otherwise this makes
|
||||
// verifying the sandbox hard.
|
||||
return false;
|
||||
};
|
||||
}
|
||||
apps.install('http://nice.com/nice.webapp', {domContext: sb,
|
||||
navigator: nav,
|
||||
errModalCallback: errModalCallback});
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
asyncTest('test permission error', function() {
|
||||
var sb = this.sandbox;
|
||||
$(sb).one('error_shown.apps', function() {
|
||||
equals($('.apps-error-msg h2', sb).text(),
|
||||
'App installation not allowed');
|
||||
equals($('.apps-error-msg p', sb).text(), 'detailed message');
|
||||
start();
|
||||
});
|
||||
this.installAppWithError('http://nice.com/nice.webapp',
|
||||
{code: 'permissionDenied',
|
||||
message: "detailed message"});
|
||||
});
|
||||
|
||||
|
||||
test('test user canceled', function() {
|
||||
var sb = this.sandbox,
|
||||
callback;
|
||||
callback = function() {
|
||||
ok(false, 'dialog should not be shown when a user cancels install');
|
||||
return false;
|
||||
};
|
||||
this.installAppWithError('http://nice.com/nice.webapp',
|
||||
{code: 'denied',
|
||||
message: 'user canceled installation'},
|
||||
callback);
|
||||
});
|
||||
|
||||
|
||||
asyncTest('test unexpected error', function() {
|
||||
var sb = this.sandbox;
|
||||
$(sb).one('error_shown.apps', function() {
|
||||
equals($('.apps-error-msg h2', sb).text(), 'Unknown error');
|
||||
equals($('.apps-error-msg p', sb).text(), 'surprise');
|
||||
start();
|
||||
});
|
||||
this.installAppWithError('http://nice.com/nice.webapp', {code: 'bogus',
|
||||
message: "surprise"});
|
||||
});
|
||||
|
||||
|
||||
test('test successful app install', function() {
|
||||
var sb = this.sandbox,
|
||||
nav = {},
|
||||
callback;
|
||||
nav.mozApps = {
|
||||
install: function(manifestUrl, data, success, error) {}
|
||||
};
|
||||
callback = function() {
|
||||
ok(false, 'dialog should not be shown on successful app install');
|
||||
return false;
|
||||
};
|
||||
apps.install('http://nice.com/nice.webapp', {domContext: sb,
|
||||
navigator: nav,
|
||||
errModalCallback: callback});
|
||||
});
|
||||
|
||||
|
||||
module('apps as wrapper', {
|
||||
setup: function() {
|
||||
this.sandbox = tests.createSandbox('#apps-error-msg');
|
||||
},
|
||||
teardown: function() {
|
||||
this.sandbox.remove();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
asyncTest('success callback', function() {
|
||||
var sb = this.sandbox,
|
||||
nav = {},
|
||||
callback;
|
||||
nav.mozApps = {
|
||||
install: function(manifestUrl, data, success, error) {
|
||||
success();
|
||||
}
|
||||
};
|
||||
callback = function() {
|
||||
ok(true, 'success was called');
|
||||
start();
|
||||
}
|
||||
apps.install('http://nice.com/nice.webapp', {domContext: sb,
|
||||
navigator: nav,
|
||||
success: callback});
|
||||
});
|
||||
|
||||
|
||||
asyncTest('data', function() {
|
||||
var sb = this.sandbox,
|
||||
nav = {},
|
||||
callback,
|
||||
dataReceived;
|
||||
nav.mozApps = {
|
||||
install: function(manifestUrl, data, success, error) {
|
||||
dataReceived = data;
|
||||
success();
|
||||
}
|
||||
};
|
||||
callback = function() {
|
||||
equals(dataReceived.receipt, '<receipt>');
|
||||
start();
|
||||
}
|
||||
apps.install('http://nice.com/nice.webapp', {domContext: sb,
|
||||
navigator: nav,
|
||||
success: callback,
|
||||
data: {receipt: '<receipt>'}});
|
||||
});
|
||||
|
||||
|
||||
asyncTest('error callback', function() {
|
||||
var sb = this.sandbox,
|
||||
nav = {},
|
||||
callback;
|
||||
nav.mozApps = {
|
||||
install: function(manifestUrl, data, success, error) {
|
||||
error({code: 'someCode', message: 'some message'});
|
||||
}
|
||||
};
|
||||
callback = function(errOb) {
|
||||
equals(errOb.code, 'someCode');
|
||||
start();
|
||||
}
|
||||
apps.install('http://nice.com/nice.webapp', {domContext: sb,
|
||||
navigator: nav,
|
||||
errModalCallback: function() { return false; },
|
||||
error: callback});
|
||||
});
|
||||
|
||||
|
||||
});
|
|
@ -536,7 +536,7 @@ MINIFY_BUNDLES = {
|
|||
),
|
||||
},
|
||||
'js': {
|
||||
# JS files common to the entire site.
|
||||
# JS files common to the entire site (pre-impala).
|
||||
'common': (
|
||||
'js/lib/jquery-1.6.4.js',
|
||||
'js/lib/underscore.js',
|
||||
|
@ -616,6 +616,7 @@ MINIFY_BUNDLES = {
|
|||
'js/zamboni/format.js',
|
||||
'js/lib/jquery.cookie.js',
|
||||
'js/zamboni/storage.js',
|
||||
'js/zamboni/apps.js',
|
||||
'js/zamboni/buttons.js',
|
||||
'js/lib/jquery.pjax.js',
|
||||
'js/impala/footer.js',
|
||||
|
@ -753,6 +754,7 @@ MINIFY_BUNDLES = {
|
|||
'js/lib/jquery.cookie.js',
|
||||
'js/lib/jquery.pjax.js',
|
||||
'js/impala/pjax.js',
|
||||
'js/zamboni/apps.js',
|
||||
'js/zamboni/browser.js',
|
||||
'js/zamboni/init.js',
|
||||
'js/impala/capabilities.js',
|
||||
|
|
|
@ -229,4 +229,9 @@
|
|||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div id="apps-error-msg">
|
||||
{% include 'addons/includes/apps_error_msg.html' %}
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
|
|
Загрузка…
Ссылка в новой задаче