How to waive Xrays vision in latest Firefox WebExtension? - firefox-addon-webextensions

I am following the guide here:
I want to waive Xrays vision of an iframe:
var foo = $(Components.utils.waiveXrays($("#foobar").get(0).contentWindow.document));
The above is running in a content script with manifest.json like the following:
"content_scripts": [
{
"matches": /* something */,
"css": ["content.css"],
"js": ["jquery-3.2.1.js","content.js"]
}
]
But I will get an undefined object error:
[firefox/index.js][debug] Firefox stderr: JavaScript error: , line 0: Error: Components.utils is undefined
I think the guide on Mozilla website is outdated. It is not for pure WebExtension implementation.
What should be the correct latest method now?

After a couple of days of research (and asking in mozilla firefox mailing list). I already found out the solution. The correct guide is here (as of 2017 May 14):
In the SDK, content scripts can share objects with page scripts, using
techniques like unsafeWindow and createObjectIn. In WebExtensions, the
unsafeWindow is available via wrappedJSObject instead. All the export
helper functions are available, too.
If I want to access the waived xrays version of window object, I should use:
window.wrappedJSObject
If there is an iframe within the page and I want to access the object inside it. Here is one of the way:
document.getElementById("the_iframe").contentWindow.wrappedJSObject
However, I found that if the iframe is in cross-domain, the wrappedJSObject will be not accessible (as of Firefox version 51.0.1). I need to seek another method as follow:
Provide a content script that inject all child iframe and then implement a background script that provide a messaging bridge between the child iframe and the top page:
"background": {
"scripts": ["background.js"]
},
"content_scripts": [
{
"matches": ["*://*.something"],
"css": ["content.css"],
"all_frames": true, /* ADD THIS LINE */
"js": ["jquery-3.2.1.js","content.js"]
}
]
In content.js, do something like that:
if(window.top == window.self) { // main
main();
}
else if(window.name == "frameA") { // match frameA
  browser.runtime.onMessage.addListener(function(msg) {
/* Check the message msg and then access the waived X rays vision by window.wrappedJSObject */
if(msg matches something) {
var ret = window.wrappedJSObject.foobar(msg.data);
/* Send back the return value to background.js by browser.runtime.sendMessage */
browser.runtime.sendMessage({"returnVal": ret, "from": "frameA"});
}
}
});
}
In background.js, do some message forwarding:
function forward_to_all(r)
{
var forwardMessage = function(tabs) {
for(let tab of tabs) {
browser.tabs.sendMessage(tab.id,r);
}
}
browser.tabs.query({currentWindow:true, active:true}).then(forwardMessage);
}
browser.runtime.onMessage.addListener(function(msg) {
if(msg matches something) {
forward_to_all(msg);
}
});

You aren't meant to be able to waive xrays in firefox webextensions, if you are able to then it's a bug that would quickly be disabled.
I think the guide on Mozilla website is outdated.
Indeed.
What should be the correct latest method now?
what you want to do (ie waive xray wrappers) is not possible. Probably best to think about a new way to achieve what you want, whatever that is (I can't tell by the description).

Related

Mozilla addon loading too late to block a resource

I'm trying to cancel requests from studio.code.org to www.google.com/jsapi to help page loads go faster. In my locale, google is blocked, but the browser waits for 75 seconds before giving up. I'd like to prevent the delay by blocking the request (and the page seems to work fine without jsapi).
I followed the example from https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/webRequest/onBeforeRequest, installed the addon. I included a console.log statement to see that my code is called, but it only shows up after the browser waits another 75 seconds trying to load the resource that I hoped to block.
I'm open to other approaches if this isn't going to work.
manifest.json:
{
"manifest_version": 2,
"name": "cancel-google",
"version": "1.0",
"permissions": [
"webRequest",
"webRequestBlocking"
],
"content_scripts": [
{
"matches": ["https://studio.code.org/*"],
"js": ["cancel-google.js"]
}
]
}
cancel-google.js:
// match pattern for the URLs to block
var pattern = "*www.google.com/jsapi";
console.log("cancelator script loaded");
// cancel function returns an object
// which contains a property `cancel` set to `true`
function cancel(requestDetails) {
console.log("Cancelling: " + requestDetails.url);
return {cancel: true};
}
// add the listener,
// passing the filter argument and "blocking"
browser.webRequest.onBeforeRequest.addListener(
cancel,
{urls: [pattern]},
["blocking"]
);
cancel-google.js should be loaded as a background script, which is true for most of the WebExtension APIs.
{
"name": "Your Addon",
"manifest_version": 2,
"background": {
"scripts": ["cancel-google.js"]
}
}
Then it should work.
Smile4ever's answer is correct but I found some other issues with my original code.
First - the 'timing' issue of my original content-script was a red herring. Although the original content script will write to the log of the page, it has no effect on loading resources. The same script, as a background script, will not write anything (that I have noticed) into the console log, but it will work.
Second - the background script needs more permissions than I had originally (more than are described in the mozilla.org link).
"permissions": [
"http://*/*",
"https://*/*",
"webRequest",
"webRequestBlocking" ]
The above permissions are adequate/excessive; you can also replace "http(s)://*/*" with the actual urls of the pages requesting the resource and the resource to be blocked.

getting a Firefox plugin to detect and mimic attempts to check for Apple Pay support

Now that Apple's credit card offering is out, I can get 2% cash back on purchases on the web made with Apple Pay. Unfortunately, my browser of choice is Firefox, which doesn't yet support Apple Pay.
I'd like to detect attempts to check for Apple Pay support, so I can alert myself in some way and switch over Safari to complete my purchase. Per Apple's docs, this check is performed via window.ApplePaySession.
So, I've attempted the following in an extension:
manifest.json
{
"manifest_version": 2,
"name": "applepay",
"version": "1.0",
"content_scripts": [
{
"matches": [
"*://*/*"
],
"js": [
"applepay.js"
]
}
]
}
applepay.js
window.ApplePaySession = {
canMakePayments: function () {
console.log('canMakePayments');
return Promise.resolve(true);
},
canMakePaymentsWithActiveCard: function () {
console.log('canMakePaymentsWithActiveCard');
Promise.resolve(true);
},
};
I'm able to console.log(window) in applepay.js and get the whole object, but my changes to the object don't appear to take effect - it's acting like window is read-only. What am I missing?
In Firefox, content scripts (addon written in WebExtensions) don't share the same context as page scripts (website scripts).
In your content script, do something similar to this:
function notify(message) {
console.log("do something");
}
exportFunction(notify, window, {defineAs:'notify'});
After, the page script will see that window.notify exists.
https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Sharing_objects_with_page_scripts

Is including additional information in the output object a good idea?

I'm experimenting with a Conversation where I would like to modify the output in a couple of different ways:
different output for speech or text
different output depending on the tone of the conversation
It looks like I can add extra output details which make it through to the client ok. For example, adding speech alongside text...
{
"output": {
"speech": {
"Hi. Please see my website for details."
},
"link": "http://www.example.com",
"text": {
"Hi. Please see http://www.example.com for details."
}
}
}
For the tone, I wondered about making up a custom selection policy, unfortunately it seems to treat it the same as a random selection policy. For example...
{
"output": {
"text": {
"values": [
"Hello. Please see http://www.example.com for more details.",
"Hi. Please see http://www.example.com for details."
]
},
"append": false,
"selection_policy": "tone"
}
}
I could just add a separate tone-sensitive object to output though so that's not a big problem.
Would there be any issues adding things to output in this way?
You can definitely use the output field to specify custom variables you want your client app to see with the benefit that these variables will not persist across multiple dialog rounds (which they would if you would add them to the context field).
Now currently there is no "easy" way how to define your custom selection policy (apart from the random and sequential supported by the runtime right now) - but you could still return an array of possible answers to the client app with some attribute telling the client app which selection policy to use and you would implement this policy in the client app.

addEventListner for received SMS using mozMobileMessage in B2G

I have been teaching myself how to write apps in AngularJS for Firefox OS for a university assignment. This is my first attempt at writing an app in JS.
The aim of the app is to run commands based upon 'commands' sent via SMS (aka, 'ring loud', 'lock device', 'turn on wifi', and reply to an SMS command with GPS locations). At the moment, I'm just trying to do a simple $window.alert('Messaged Received'), to display when an SMS has been received.
My problem is, I am trying to create an addEventListener for incoming SMS, and for the moment, display an $window.alert(). Later, I will use a case switch.
I've referred to the MDN API to create the Event Listener.
var mozMM = navigator.mozMobileMessage;
mozMM.addEventListener('received', function addEventListener(evt) {
// Display a alert when a message is received
$window.alert('SMS received');
$window.alert(evt.message.body);
}, false);
My manifest.webapp has been set up to include all the relevant settings:
"type" : "certified",
"permissions": {
"backgroundservice":{},
"sms":{},
...
},
"messages": [
{ "sms-received": "/index.html" },
{ "notification": "/index.html" }
]
I am able to send SMS from my app without any issues. So I assume I have no problems with my permissions. I've also confirmed that I have full access to the mozMobileMessage object.
For testing, I am using a Geekphone, which has been rooted, and can install certified apps.
I have uploaded the source code to github:
https://github.com/s3069246/findmydevice/tree/master/app
Thanks to someone on Google Groups for giving me the correct solution. I thought I would also share it here.
The issue was that I was using the wrong Event Handler. I should have been using a system message handler instead
navigator.mozSetMessageHandler('sms-received', function onSMS(sms) {
/* here your code */
});
Combined with the "message": [] handler in the manifest, the system handler will alert the application that a message has been received, even if the app is running in the background.

Unable to access NameSpace.app variables with ST2?

I'm using the Sencha Command Line 3 tools with a newly generated Sencha Touch 2 application.
Assuming my app.js file looks like this:
Ext.application({
name: "CA",
event_code: "test123",
launch: function() {
console.log("application launched!");
}
});
My views and object stores depend on generating a URL based on CA.app.event_code equaling "test123";
During development in the browser, everything works fine, CA.app returns the variables I need.
When I compile my application with sencha app build and try to run the minified version in the browser, I get an error like this:
Error evaluating http://localhost:8888/app.js with message: TypeError: Cannot read property 'event_code' of undefined localhost:11
I'm not entirely sure why this is happening or how I can fix it. I am open to any and all ideas or suggestions, any pointers in the right direction will be greatly appreciated.
Ran into the exact same issue. You have no access to the namespaced app within the views... really sucks that they let you in development and not when built. Anyway, I got around it by adding a static helper class and using that all over my app:
In /app/util/Helper.js:
Ext.define('MyApp.util.Helper', {
singleton: true,
alternateClassName: 'Helper',
config: {
foo: "bar",
bat: "baz"
},
staticFunction: function() {
// whatever you need to do...
}
});
Then in your view or controller:
Ext.define('MyApp.view.SomeView', {
...
requires: ['Events.util.Helper'],
...
someViewFunction: function() {
var someValue = Helper.staticFunction();
// and you can use Helper.foo or Helper.bat in here
}
});
For reference, here's some documentation on Sencha Singletons. And one important note: make sure that your Helper singleton is in it's own file! If it's small, you may be inclined to put it at the bottom of your app.js, and things will work at first, and the build process will work, but the code will not. Don't worry, the build process puts all of your JS code in one big, compressed file anyway.

Resources