OK so I've got this addon where I'm trying to load a bitmap from a file:/// URI and draw it to canvas.
All that goes fine until I need to get the data off the canvas using getImageData, then I run into a security exception. I go to Moz Chat and am told that because I'm loading the image from a page modded HTML File, it's a cross domain policy issue and not allowed.
The solution, they say, is to go to the main module and load the image there, copy it to a canvas, then serialize the data with getImageData and send it back to the HTML doc.
One problem: Jetpack doesn't know what "Image" is because it doesn't have an HTML DOM, thus the operation seems to be rendered more or less impossible.
Why is this a cross domain policy issue in the first place? Beyond that, how do I load the image without access to the DOM?
The simpler and best example of communication between main.js module and a content script you can read is in Add-on SDK docs: look for the section under the title Communicating With Content Scripts.
Basically, this is how the main module tells the content script (the pagemod in your case) something:
worker.port.emit("getElements", tag);
and this is how it listens to whatever the content script tells him:
worker.port.on("gotElement", function(elementContent) {
console.log(elementContent);
});
On the other side, the content script listens to what the main module says to it this way:
self.port.on("getElements", ...
And finally, a case this example is missing is how the content script may emit an event to tell something to the main module:
self.port.emit("myCustomEvent", var1=someValue, var2=otherValue, ...)
But that's the idea. I also recommend you to tale a careful look at this more general explanation about how content script (pagemods, widgets, tabs, panels, etc) work because this is the mosst important concept to understand how sdk addons work.
Last, about the cross domain issue on content scripts you can read more here.
Related
This is probably a simple question but I can't for the life of me find the answer online. I'm using nw.js and you specify the main html file in the package file. However, how can I navigate in the same main window to a different html page? The Window object doesn't seem to have any way to do this. It has an open() function but that opens a new window which isn't what I want.
Similar to Ike10's answer, I was able to achieve this by simply coding:
location.href = './newHTMLDoc.html';
Maybe it is my version of NW, but my window object does not allow the code:
window.location.href
If you have a system Tray or other resources attached to the window, you'll still have those visually, but won't be able to use them anymore, forcing you to CTRL-ALT-DEL your way out of the mess. So be sure to remove resources as needed.
EDIT - Some added info for passing data from one HTML doc to the next
If you are like me and needed to pass data between pages, I found a simple solution for this. If we were creating a new window, you could use "emit" to pass data between windows. However, we are just changing .html documents, so we can't use that method.
Similar to a Singleton in Java, you can pass data between .html documents by creating a Javascript file with all the variables that you want to use throughout your application. As long as you have the Javascript file included in all the .html pages, these variables will be available to you.
I'm just learning Javascript, so this might be evident to many already, but just thought I would share this.
I am pretty new to nw.js, but I have found one solution. I believe the reason the window object does not work is because of javascript context. Nw.js has a node context and a webkit context. (More can be read here: https://github.com/nwjs/nw.js/wiki/Differences-of-JavaScript-contexts). However, I solved my similar problem by making a separate js file for setting up a button to change the page.
index.js:
document.getElementById("button").onclick = function(){
window.location.href = './OtherPage.html';
}
Make sure the require method is not used in the same js file as that would change the context.
Then load this into your html file.
index.html:
<script src="./path_to/index.js"></script>
Hope this helps. Feel free to ask for questions or elaboration. I will try my best to help.
I have a widget that I want to plug into my angular view. I'm not sure I'm explaining it right but the code I get from the site that makes/hosts the widget is below:
<script src="http://www.somesite.com/widgetfile.js"></script>
This works perfectly fine on a standard html site (just a simple html file loaded locally in my browser). It loads the external JS file and does a document.write onto my DOM as far as I can tell.
The problem I'm having is putting this on a view in an Angular app I've built. I thought it would be the same thing as just copy/pasting the single line of script that the site gave me, but it doesn't work... error i get is below (Chrome).
Failed to execute 'write' on 'Document': It isn't possible to write into a document from an asynchronously-loaded external script unless it is explicitly opened.
I can't use something other than document.write because I don't have access to the file itself, the site that generates the widget does that for me. I've tried doing $http get request in my controller than putting that to a scope variable to be put on the DOM, but I get an error about cross domain security.
Any thoughts? This seems super basic to me since there are thousands of sites that offer "One line of code to embed a widget"... and it works in basic HTML pages. Am I missing something stupid (keep in mind that yes, I did copy and paste the widget script directly from the site that hosts it).
Thanks for the help. I'm pretty new with coding and newer at angular, but this seems like something that should be borderline plug-n-play and not need some complex cross domain workaround.
Try these with these two links.
http://ngmodules.org/modules/angular-widget
https://github.com/cztomsik/ng-widgets
I have a project where we're using an iframe. However, project specs have changed and we can no longer use the iframe. Instead we need to request the html page in the background and display it on page when loaded.
Any ideas on how to do this via Ruby (rails). Thought best to ask for general direction before diving in.
Thanks!
load it with ajax, and do a body append
It depends on where you want to have the work occur, on the back-end in your Rails code, or in the user's browser via JavaScript, as #stunaz suggests.
Keeping it in the browser and loading via JavaScript will expose the HTML page's location to the user, which might not be desirable. Loading it from the back-end and including it in the HTML emitted to the browser will hide the source entirely.
If you want to do it on the back-end, the simplest thing is to either load the file from the local drive, if it is local using File.read. If it's on a different machine, you can use Open::URI to pull it in. Either way, you'd then insert it into the HTML in the right spot. How you do that depends on what you are using to generate the outgoing HTML.
I need to create a portable script to give to others to implement on their websites that will dynamically show content from my database (MySQL).
I know AJAX has a cross-site problem, but it seems that Google's ad's somehow manage the effect in a cross-browser / cross-site fashion.
Knowing that I have to give people a simple cut/paste snippet to put in their website...how can I achieve this? How did Google?
They use an <iframe>, so the ad is served from their server, and can talk to their database. I'm not actually sure that they use any sort of AJAX from their ads, though; they appear to just be mostly static content, with a few scripts for tweaking the formatting (which are optional, since they want their ads to be visible even if users have JS turned off).
Remember, you can always look into this on your own, and see what they did. On Firefox, use Firebug to explore the html, css, and scripts on a site. On WebKit based browsers (Safari, Chrome, and others), you can use the Web Inspector.
Google's ad code is loaded via a script tag that calls a remote javascript file. The AJAX restrictions that are generally enforced with xmlhttp, iframe, and similar AJAX requests don't apply when it comes to loading remote javascript files.
Once you've loaded the javascript file, you can create iframes in your page that link back to the actual hosted content on your server (and feed them any data about the current page that you wish).
jQuery has built in support for jsonp in their ajax calls. You may want to lookin in to using that if you are really needing to use ajax.
http://api.jquery.com/
http://docs.jquery.com/Ajax
You don't need iFrames and you don't need AJAX. It's really, really simple!
You pull in a remote JS file that is actually a constructed file from php/asp/whatever. In your JS file you have a document.write script that writes the content. It's that simple.
We do this all the time with media stored on separate sites. Here's an example.
YOUR SERVER: file.php (which outputs js)
<script>
document.write("I'm on a remote server");
</script>
OTHER SITE:
<script src='http://www.yourserver.com/file.php'></script>
And it will output the content generated by the script. To make the content customized you can put in script vars above the script call that will adjust what your file pulls out. From there it's pretty straightforward.
I realize this question is a year old, but I've written a library that can help with the document.write part of the problem (whether this is a TOS violation, I don't know) writeCapture.js. It's pretty simple:
$('#ads').writeCapture().html('<script src="whatever-your-adsense-code-is"> </script>');
The example uses jQuery, but you can use it standalone as well.
Can a firefox XPCOM component read and write page content across multiple pages?
Scenario:
A bunch of local HTML and javascript files. A "Main.html" file opens a window "pluginWindow", and creates a plugin using:
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
var obj = Components.classes[cid].createInstance();
plugin = obj.QueryInterface(Components.interfaces.IPlugin);
plugin.addObserver(handleEvent);
The plugin that has 3 methods.
IPlugin.Read - Read data from plugin
IPlugin.Write - Write data to the plugin
IPlugin.addObserver - Add a callback handler for reading.
The "Main.html" then calls into the pluginWindow and tries to call the plugin method Write.
I receive an error:
Permission denied to call method UnnamedClass.Write
First, is your C++ code really a plugin or an XPCOM component, possibly installed as part of an extension? Sounds like it's the later.
If so, it's not usable from untrusted JS code - any web page or a local HTML file. It's fully usable from privileged code, the most common type of which is the extension code.
You're working around this problem when creating the component using the enablePrivilege('UniversalXPConnect') call. This is not really recommended, unless this will not be distributed to users (since this call pops a confusing box and if you set a preference to always allow file:// scripts use XPCOM, it may be a security problem, since not all local pages are trusted - think saved web pages).
Your Write call fails for the same reason - file:// pages are not trusted to use XPCOM components. You probably can get it to work if you add another enablePrivilege call in the same function as the Write call itself.
Depending on the situation, there may be a better solution.
If your files must be treated as trusted, you may want to package them as an extension and access them via a chrome:// URL. This gives the code in those pages permissions to call any XPCOM component, including yours.
If the component's methods are safe to use from any page or if the environment is controlled and no untrusted pages are loaded in the browser, you could make your component accessible to content (search for nsSidebar in mozilla code for an example and also for nsISecurityCheckedComponent).
Oh, and when you don't get good answers here, you should definitely try the mozilla newsgroups/mailing lists.
[edit in reply to a comment] Consider putting the code that needs to call the component in a chrome:// script. Alternatively, you should be able to "bless" your pages with the chrome privileges using code like this (note that it does the opposite of what you need - stripping away the chrome privileges).
Does Main.html and that other window run with chrome privileges?
If you access Main.html "normally", just putting it on the location bar of Firefox, then it will have restrictions to what it can do (Otherwise, an arbitrary web page could do exactly the same).
If you are creating a firefox plugin, place your code in a XUL overlay.
If you really want to allow any web page to do whatever it is your plugin does, you can establish some mechanism through wich the page can ask the plugin to do the operation with its chrome privileges and send the result to the page afterwards.
If you are NOT making a firefox extension...then I am afraid I misunderstood something, could you explain it more?