[bug 1097168] AAQ - Use about:support API when available.

This commit is contained in:
Ricky Rosario 2014-12-16 18:12:24 -05:00
Родитель 7ceade3307
Коммит 58ad020ed5
7 изменённых файлов: 252 добавлений и 71 удалений

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

@ -32,3 +32,32 @@ the heavy lifting of providing automatic updates.
.. _on Github: https://github.com/0c0w3/troubleshooter
.. _on AMO: https://addons.mozilla.org/en-US/firefox/addon/troubleshooter/
about:support API
-----------------
The about:support API replaces the Troubleshooter Add-on and is available
starting in Firefox 35. To test this locally during development, you need
to run an ssl server and change some permissions in your browser.
To run the ssl server, first add sslserver to INSTALLED_APPS in
settings_local.py::
INSTALLED_APPS = list(INSTALLED_APPS) + ['sslserver']
Run the ssl server::
$ ./manage.py runsslserver
Then you need to run the following in the Browser Console:
Services.perms.add(Services.io.newURI("https://localhost:8000", null, null), "remote-troubleshooting", Services.perms.ALLOW_ACTION);
.. Note::
You need to Enable chrome debugging in developer console settings,
so that you can access the browser console.
See also https://developer.mozilla.org/en-US/docs/Tools/Browser_Console

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

@ -182,6 +182,7 @@ MINIFY_BUNDLES = {
'js/markup.js',
'js/ajaxvote.js',
'js/ajaxpreview.js',
'js/remote.js',
'js/aaq.js',
'js/questions.js',
'js/libs/jquery.tokeninput.js',

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

@ -187,43 +187,51 @@
{% macro troubleshooting_instructions(field) %}
<a href="{{ settings.TROUBLESHOOTER_ADDON_URL }}" class="btn btn-important" id="install-troubleshooting-addon">
{{ _('Automatically add') }}
</a>
<p class="help-text">{{ field.help_text|safe }}</p>
<p id="troubleshooting-manual">
{% trans url='#troubleshooting-help,#troubleshooting-field' %}
A window will open in the top corner. Click Allow, and then click
Install. If the automated way doesn't work,
<a class="expander" href="{{ url }}">try these manual steps</a>.
{% endtrans %}
</p>
<span id="troubleshooting-explanation" class="cf">
{{ _('This field was populated automatically with the add-on called <em>Troubleshooter</em>.') }}
<div id="addon-section">
<a href="{{ settings.TROUBLESHOOTER_ADDON_URL }}" class="btn btn-important" id="add-troubleshooting-info">
{{ _('Automatically add') }}
</a>
<p class="help-text">{{ field.help_text|safe }}</p>
<p id="troubleshooting-manual">
{% trans url='#troubleshooting-help,#troubleshooting-field' %}
A window will open in the top corner. Click Allow, and then click
Install. If the automated way doesn't work,
<a class="expander" href="{{ url }}">try these manual steps</a>.
{% endtrans %}
</p>
<ol id="troubleshooting-help">
<li>{{ _('Open <em>Help &gt; Troubleshooting Information</em>.') }}
<ul>
<li>{{ _('Look at the top of your screen, and click the menu item called <em>Help</em>.') }}</li>
<li>{{ _('A small box will open. Click on an item called <em>Troubleshooting Information</em>.') }}</li>
</ul>
</li>
<li>{{ _('A new window will open. Click on a button called <em>Copy text to clipboard</em>.') }}</li>
<li>{{ _('Paste the info in the text box below.') }}
<ul>
<li>{{ _('Click on the empty box above this text.') }}</li>
<li>{{ _('Look at the top of your screen, and click the menu item called <em>Edit</em>.') }}</li>
<li>
{% trans %}
A small box will open. Click on the item called <em>Paste</em>.
Alternatively, type <em>Ctrl+V</em> or <em>Command+V</em>.
{% endtrans %}
</li>
<li>{{ _('Some text will appear in the empty box.') }}</li>
</ul>
</li>
</ol>
</div>
<div id="api-section">
<a href="#" class="btn btn-important" id="share-data">
{{ _('Share Data') }}
</a>
<p class="help-text">{{ _('This information gives details about the internal workings of your browser that will help in answering your question.') }}</p>
</div>
<p id="troubleshooting-explanation" class="cf">
{{ _('This field was populated automatically.') }}
<a href="#troubleshooting-field" class="expander">{{ _('See the data') }}</a>.
</span>
<ol id="troubleshooting-help">
<li>{{ _('Open <em>Help &gt; Troubleshooting Information</em>.') }}
<ul>
<li>{{ _('Look at the top of your screen, and click the menu item called <em>Help</em>.') }}</li>
<li>{{ _('A small box will open. Click on an item called <em>Troubleshooting Information</em>.') }}</li>
</ul>
</li>
<li>{{ _('A new window will open. Click on a button called <em>Copy text to clipboard</em>.') }}</li>
<li>{{ _('Paste the info in the text box below.') }}
<ul>
<li>{{ _('Click on the empty box above this text.') }}</li>
<li>{{ _('Look at the top of your screen, and click the menu item called <em>Edit</em>.') }}</li>
<li>
{% trans %}
A small box will open. Click on the item called <em>Paste</em>.
Alternatively, type <em>Ctrl+V</em> or <em>Command+V</em>.
{% endtrans %}
</li>
<li>{{ _('Some text will appear in the empty box.') }}</li>
</ul>
</li>
</ol>
</p>
<p id="troubleshooting-field">
{{ field }}
</p>

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

@ -49,11 +49,6 @@ AAQSystemInfo.prototype = {
$(selector).fadeToggle();
});
$('#troubleshooting-install .btn').on('click', function(ev) {
// Do not prevent default.
$(this).toggleClass('btn-important btn-disable').html(gettext('Installing...'));
});
$('#show-login a').on('click', function(ev) {
$('#login-form').show();
$(this).remove();
@ -153,38 +148,66 @@ AAQSystemInfo.prototype = {
},
getTroubleshootingInfo: function(addEvent) {
var self = this;
var browserData;
if (addEvent === undefined) addEvent = true;
// If the troubleshoot input exists, try to find the extension.
// If the troubleshoot input exists, try to get the data.
if ($('#id_troubleshooting').length === 0) {
// No troubleshooting form, so no point in looking for the plugin.
// No troubleshooting form, so no point in trying to get the data.
return;
}
if ('mozTroubleshoot' in window) {
// Yeah! The user has the addon installed, let's use it.
$('#troubleshooting-install').remove();
window.mozTroubleshoot.snapshotJSON(function(json) {
// Parse the JSON, so we can modify it.
json = JSON.parse(json);
var modifiedPreferences = json.modifiedPreferences;
json.modifiedPreferences = {};
for (var key in modifiedPreferences) {
if (key.indexOf('print.') !== 0) {
json.modifiedPreferences[key] = modifiedPreferences[key];
// First we try to use the builtin API:
remoteTroubleshooting.available(function (yesno) {
if (yesno) {
remoteTroubleshooting.getData(function (data) {
browserData = data;
});
$('#addon-section').remove();
$('#share-data')
.click(function(e) { // The user must click button to save the data.
e.preventDefault();
handleData(browserData);
return false;
});
} else {
$('#api-section').remove();
// If the builtin API isn't available, we try with the addon.
if ('mozTroubleshoot' in window) {
// Yeah! The user has the addon installed, let's use it.
window.mozTroubleshoot.snapshotJSON(function(json) {
handleData(JSON.parse(json));
});
} else {
if (addEvent) {
// Well, the user might install it later, so set up a listener.
window.addEventListener('mozTroubleshootDidBecomeAvailable',
self.getTroubleshootingInfo.bind(self, false));
}
}
// The last two parameters cause this to pretty print,
// in case anyone looks at it.
json = JSON.stringify(json, null, " ");
$('#id_troubleshooting').val(json);
$('#troubleshooting-manual').remove();
$('#troubleshooting-explanation').show();
});
} else {
if (addEvent) {
// Well, the user might install it later, so set up a listener.
window.addEventListener('mozTroubleshootDidBecomeAvailable',
self.getTroubleshootingInfo.bind(self, false));
}
});
// Handle the troubleshooting JSON data.
function handleData(data) {
var modifiedPreferences = data.modifiedPreferences;
data.modifiedPreferences = {};
for (var key in modifiedPreferences) {
if (key.indexOf('print.') !== 0) {
data.modifiedPreferences[key] = modifiedPreferences[key];
}
}
// The last two parameters cause this to pretty print,
// in case anyone looks at it.
data = JSON.stringify(data, null, " ");
$('#addon-section').remove();
$('#api-section').remove();
$('#id_troubleshooting').val(data);
$('#troubleshooting-explanation').show();
}
}
};

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

@ -0,0 +1,116 @@
window.remoteTroubleshooting = window.remoteTroubleshooting || {};
(function(window, remoteTroubleshooting) {
'use strict';
var data;
/**
* Async method for retrieving remote-troubleshooting data.
*
* Tries to console.log problems to help diagnose issues.
*
* @param {function} callback - Callback function to call when
* the data arrives. It should take a single argument which
* will be the data packet.
*
* @param {integer} timeout - Timeout in milliseconds for calling
* the callback with {} if the event hasn't yet gotten dispatched.
* Defaults to 1000 ms (aka 1 second).
*
* @returns {object} with data in it or {}
*/
remoteTroubleshooting.getData = function(callback, timeout) {
var timeoutId;
// If we've already gotten the data, return that.
if (data) {
window.setTimeout(function() { callback(data); });
return;
}
// If the browser is missing certain features, then asking for
// remote-troubleshooting data is moot, so just drop out as
// soon as we know important things are missing.
if (!window.addEventListener) {
// console.log('remoteTroubleshooting: browser does not support addEventListener');
data = {};
window.setTimeout(function() { callback(data); });
return;
}
if (!(window.hasOwnProperty('CustomEvent') && typeof window.CustomEvent == 'function')) {
// console.log('remoteTroubleshooting: browser does not support CustomEvent');
data = {};
window.setTimeout(function() { callback(data); });
return;
}
timeout = timeout || 1000;
/**
* If the interval passes and the event listener hasn't kicked off then
* there's nothing listening, so we abort.
*/
function eject() {
// console.log('remoteTroubleshooting: interval ' + timeout + ' has passed.');
data = {};
callback(data);
}
// Listen to the WebChannelMessageToContent event and handle
// incoming remote-troubleshooting messages.
window.addEventListener("WebChannelMessageToContent", function (e) {
// FIXME: handle failure cases
if (e.detail.id === "remote-troubleshooting") {
window.clearTimeout(timeoutId);
data = e.detail.message;
if (data === undefined) {
// console.log('remoteTroubleshooting: data is {}. ' +
// 'permission error? using http instead of https?');
data = {};
}
window.setTimeout(function() { callback(data); });
}
});
// Create the remote-troubleshooting event requesting data and
// kick it off.
var event = new window.CustomEvent("WebChannelMessageToChrome", {
detail: {
id: "remote-troubleshooting",
message: {
command: "request"
}
}
});
window.dispatchEvent(event);
timeoutId = window.setTimeout(eject, timeout);
};
/**
* Returns whether or not the remote-troubleshooting data is
* available.
*
* @param {function} callback - Callback function to call when
* the data arrives. It should take a single argument which
* will be the data packet.
*
* @param {integer} timeout - Timeout in milliseconds for calling
* the callback with {} if the event hasn't yet gotten dispatched.
* Defaults to 1000 ms (aka 1 second).
*
* @returns {bool} true if it's available, false if it isn't
*/
remoteTroubleshooting.available = function(callback, timeout) {
remoteTroubleshooting.getData(function (data) {
// FIXME: This relies on the fact that 'application' is a
// valid key with data in it. If it's not then, this will
// be wrong.
callback(!!data.application);
}, timeout);
};
}(window, window.remoteTroubleshooting));

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

@ -1330,12 +1330,9 @@ h2 {
}
}
#troubleshooting-install {
margin: 10px 0;
}
#troubleshooting-manual,
#troubleshooting-explanation {
clear: both;
font-size: 13px;
margin: 10px 0;
}
@ -1625,7 +1622,7 @@ div.ans-attachments {
}
.edit-question {
#troubleshooting-install,
#add-troubleshooting-info,
#troubleshooting-manual {
display: none;
}
@ -1732,3 +1729,7 @@ div.ans-attachments {
.content-raw {
display: none;
}
.help-text {
clear: both;
}

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

@ -17,3 +17,6 @@ http://people.mozilla.org/~wkahngreene/pep8/pep8-1.6.0a0-willkg.1.tar.gz#egg=pep
# sha256: P6gKELNtUWhr93RPXcmWIs1cmM6O1kAi5imGiq_Bd2k
pyflakes==0.8.1
# sha256: Y6KG6ssDzV9kPX60WMbGK3DBEbRjT9jVnyfMrKS3yDo
django-sslserver==0.14