Mozilla addon loading too late to block a resource - request

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.

Related

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

Extendscript Debugging Arrays

My first question so be gentle...
Using Adobe Extendscript Toolkit CS6 3.8.0.12 to make a few scripts. Trying to see contents of an array in the Data Browser, specifically a pathItem in the pathItems array.
Can't seem to find a way to examine the contents of an array.
Any help is appreciated.
You can inspect elements by adding breakpoints to you script, but it seems like you cant see the contents of pathItems in the data browser. You will have to extract them into variables. E.g. like this:
var doc = app.documents.add();
var rect = doc.pathItems.rectangle(100,-100,100,100);
var pathItems = doc.pathItems;
See this image for some more hints
Here are some options I've used.
Option 1
Use Visual Studio Code with the ExtendScript Debugger. You can create ExtendScript/JSX files to run inside any Adobe product supporting ExtendScript and then set a watcher on the variable to inspect.
//foo.jsx
var myArray = ['foo', $.fileName, {a:1, b:'two'}];
'add code break here';
//.vscode/launch.json
{
"version": "1.0.0",
"configurations": [
{
"type": "extendscript-debug",
"request": "launch",
"name": "Foo Testing",
"program": "${workspaceFolder}/foo.jsx",
// "stopOnEntry": true,
// "trace": true, //debugging output
"targetSpecifier": "indesign-14.064",
"engineName": "main"
}
]
}
Option 2
Use a Logger that will output an object for inspection to a file. jasminejsx uses this Logger to do just that.

How to waive Xrays vision in latest Firefox WebExtension?

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).

Open URL in IBM Watson conversation

I am using a Blumix free account to develop a chat-bot using watson conversation.
How do I add a clickable URL in the response, or automatically call a URL in browser?
I have edited the "advanced response" using the suggestions as described on this page but could not get it work.
How can I achieve that?
I don't know if I understood your question correctly, but.. if you wants add some url inside flows Conversation Service (IBM Watson), try it:
1º: Add the url with tag <a target> and href= your URL inside flows. See the example:
JSON:
"output": {
"text": "This is a link <a target=\"_blank\" href= \"https://www.choosemyplate.gov\">Food and nutrition Guide</a>.\n<br/><br/>Talk to you later, bye for now!"
},
2º See that it did not work inside the Conversation, because it will be your browser that will render the html.
3º If you open with your browser, it works, see:
See that the link is showing up, and this will work for other things in html, like button, for example...
But if you can: based on user input should access a url:
This is done by using two features: Context.request skip_user_input
A request is a special context variable that has args, name and result. It is used to tell the calling app that it should do some action based on this variable.
Setting skip_user_input is optional. In many cases, you might want to execute some business logic in your application and then provide its results via result. Setting skip_user_input to true, will tell Watson Conversation to not wait for input from the user. Thus, your condition on the next node should be based on the content inside result.
{
"output": {},
"context": {
"request": {
"args": {
"url_to_invoke": "your_url"
},
"name": "Call_A_URL",
"result": "context.response"
},
"skip_user_input": true
}
}
Reference: IBM Professional #Dudi: here.

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.

Resources