referring to recent Info provided by firefox that it is possible to access extension object in content safely. https://blog.mozilla.org/addons/2012/08/20/exposing-objects-to-content-safely/
I am trying to do this in the hello world extension downloaded from Firefox website.
var sharedObject = { foo : "Hello!" };
window.wrappedJSObject.sharedObject = sharedObject;
and in my webpage JS I have
alert(window.sharedObject.foo);
But it says window.sharedObject undefined. Any clues ? I want to do it safely too but first I intend to get it working.
Thanks,
It's the contentWindow you want to inject your object
var sharedObject = { foo : "Hello!" };
contentWindow.wrappedJSObject.sharedObject = sharedObject;
Keep in mind that without the __exposedProps__ property, foo will be undefined for the webpage code.
Related
I try to get the service metadata of a sapui5 v2 odata model.
Code:
var oModel = new sap.ui.model.odata.v2.ODataModel(someServiceURL);
var oMetadata = oModel.getServiceMetadata();
This should work according to this page:
https://openui5beta.hana.ondemand.com/docs/guide/6c47b2b39db9404582994070ec3d57a2.html
Anyhow I got "undefined" for oMetadata.
If I change code to:
var oModel = new sap.ui.model.odata.v2.ODataModel({
loadMetadataAsync : false,
serviceUrl : someServiceURL
});
Still oMetadata === undefined
According to SDK documentation metadata should be loaded in sync:
Return the metadata object. Please note that when using the model with
bLoadMetadataAsync = true then this function might return undefined
because the metadata has not been loaded yet. In this case attach to
the metadataLoaded event to get notified when the metadata is
available and then call this function.
What is wrong with my code?
I am using (1.28.11):
<script src="https://sapui5.netweaver.ondemand.com/resources/sap-ui-core.js" ...
I started debugging the UI5 code and detected following line:
this.bLoadMetadataAsync = true;
I started debugging of SAPUI5 code and detected following line (seems to be called each time):
this.bLoadMetadataAsync = true;
Is it a bug? Or is something wrong with my code?
Solution:
The following worked for me in an actual application environment. I guess it not being fired in my fiddle was due to no actual data request being made:
var oModel = new sap.ui.model.odata.v2.ODataModel(<ServiceURL>);
oModel.attachMetadataLoaded(null, function(){
var oMetadata = oModel.getServiceMetadata();
console.log(oMetadata);
},null);
Lead up to the solution:
Ok so I started playing around with this a bit and found the following:
.getServiceMetadata() worked fine with sap.ui.model.odata.ODataModel.
with the sap.ui.model.odata.v2.ODataModel the request for the metadata was sent through the network but somehow .getServiceMetadata() returned undefined.
I tried to sap.ui.model.odata.v2.ODataModel.attachMetadataLoaded() but the event was never fired. (This only applied in the jsbin I used)
I will edit this with any further findings I make. If you have anything that should be included in my findings/testing just tell me.
Edit:
The bLoadMetadataAsync is a parameter you can set on the sap.ui.model.odata.ODataModel. The parameter is not in the API for sap.ui.model.odata.v2.ODataModel anymore. I assume that the async loading has been choosen as default.
Edit:
#user3783327 Reported a bug here: https://github.com/SAP/openui5/issues/564
As sirion already mentioned, the ODataModel has now an API named metadataLoaded which returns a promise accordingly. In the resolve function, we can definitely get the service metadata via getServiceMetadata().
myODataModel.metadataLoaded()
.then(() =>/* Do something with */myODataModel.getServiceMetadata());
Alternatively, we can also make use of ODataMetaModel which can be set on any ManagedObject (including View) and provides several useful accessors related to the service metadata. In order to get the meta model, we need to use the appropriate API from the ODataModel instead of instantiating the model directly:
myODataModel.getMetaModel().loaded()
.then(() =>/* Do something with */myODataModel.getMetaModel()/*...*/);
Documentation: Meta Model for OData V2
I have an external application and I want it to display some information on top of the browser window. My bootstrapped extension needs to pass the browser window handle (native HWND) to my application, along with some other useful information about the window. I'm able to do the communication between them, the only thing that is missing is a way to get the native HWND of the Firefox window.
I read a lot about it and although I belive it's possible, I couldn't find a working solution. Here's what I've tried so far:
This one should give me nsIBaseWindow, so I could get nsIBaseWindow.nativeHandle or nsIBaseWindow.ParentNativeWindow, but no success:
var window = SomeDOMWindow; // Informative
var baseWindow = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIWebNavigation)
.QueryInterface(Components.interfaces.nsIDocShellTreeItem)
.treeOwner
.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIXULWindow)
.docShell
.QueryInterface(Components.interfaces.nsIBaseWindow);
The above code is widely spread on forums, but I couldn't get it to work for me.
The other one does not seem to be much accurate since it gets the HWND based on the window's class and title, which can lead to wrong results:
Components.utils.import("resource://gre/modules/ctypes.jsm");
var lib = ctypes.open("user32.dll");
var fww = lib.declare("FindWindowW", ctypes.winapi_abi,
ctypes.voidptr_t, ctypes.jschar.ptr, ctypes.jschar.ptr);
var sfw = lib.declare("SetForegroundWindow", ctypes.winapi_abi,
ctypes.int32_t, ctypes.voidptr_t);
var hwnd = fww("MozillaWindowClass", document.title);
setTimeout(function() {
sfw(hwnd);
lib.close();
}, 3000);
Any help would be appreciated.
window must be a root one (i.e. an instance of ChromeWindow)
The following code should work
var win = Cc["#mozilla.org/appshell/window-mediator;1"].getService(Ci.nsIWindowMediator).getMostRecentWindow("navigator:browser");
var basewindow = win.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIDocShellTreeItem)
.treeOwner
.QueryInterface(Ci.nsIInterfaceRequestor)
.nsIBaseWindow;
var nativehandle = basewindow.nativeHandle;
The problem was that I was querying the wrong interface from the subject param in the xul-window-registered observer. I need to get an nsIDOMWindow instead of an nsIXULWindow so the first code mentioned in my question works. So now I'm doing the following, with some piece of code #Noit suggested:
observe: function(subject, topic, data) {
var newWindow = subject.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowInternal || Ci.nsIDOMWindow);
var basewindow = newWindow.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIDocShellTreeItem)
.treeOwner
.QueryInterface(Ci.nsIInterfaceRequestor)
.nsIBaseWindow;
var nativehandle = basewindow.nativeHandle;
}
And it works!
Thank you very much for your help.
I also just came across this, it might be nice:
Cu.import("resource://gre/modules/ctypes.jsm");
/*start getcursorpos*/
var lib = ctypes.open("user32.dll");
/*foreground window stuff*/
var FindWindowA = lib.declare('FindWindowA', ctypes.winapi_abi, ctypes.uint32_t, ctypes.jschar.ptr, ctypes.jschar.ptr)
var GetForegroundWindow = lib.declare('GetForegroundWindow', ctypes.winapi_abi, ctypes.uint32_t)
function doFindWindow() {
var wm = Cc['#mozilla.org/appshell/window-mediator;1'].getService(Ci.nsIWindowMediator);
var title = wm.getMostRecentWindow('navigator:browser').gBrowser.contentDocument.title;
Cu.reportError('title=' + title)
var ret = FindWindowA('', title + ' - Mozilla Firefox');
//var ret = GetForegroundWindow();
Cu.reportError(ret);
}
/*end foreground window stuff*/
The code in the answer of user 'paa' worked until Firefox version 69.
If you execute it in Firefox 70 you will get an exception:
TypeError: win.QueryInterface is not a function
This is strange because the variable win has the same content in Firefox 69 and 70.
When I execute alert(win) I get: "[object ChromeWindow]" in both browsers.
And alert(win.document.title) displays correctly the title of the document in both browsers.
I downloaded the sourcecode of both Firefox versions to compare them and possibly find the cause. But the source code of Firefox is huge (2 Gigabyte) and nearly completely free of comments. I found that I'm wasting my time with that approach.
It is extremely difficult to understand sourcecode of Firefox which runs spread over multiple processes which communicate with each other. It seems that the content of the variable win corresponds to the C++ class mozIDOMWindowProxy or nsChromeOuterWindowProxy. But these seem to be only wrapper classes for other classes. Finally I gave up trying to understand Firefox sourcecode.
But playing around for some hours I finally found a solution by try and error.
It is even simpler:
var baseWindow = win.docShell
.treeOwner
.nsIBaseWindow;
It works on Firefox 70 up to 79 (which is currently the latest version). However this new code does not run on Firefox versions <= 62. On Firefox 62 or older you get the error
TypeError: win.docShell is undefined
So the Firefoxes from 63 to 69 allow both versions of code. Maybe in version 70 the QueryInterface() has been removed because it is not needed anymore and has become legacy?
NOTE: In Firefox 68 they made another change. Now there are 2 native windows: The toplevel 'MozillaWindowClass' now has a child window 'MozillaCompositorWindowClass' which runs in another process and draws the web content.
I am developing a mobile application using phonegap, Initially I have developed using WEBSQL but now I m planning to move it on INDEXDB. The problem is it does not have direct support on IOS , so on doing much R&D I came to know using IndexedDB Polyfil we can implement it on IOS too
http://blog.nparashuram.com/2012/10/indexeddb-example-on-cordova-phonegap.html
http://nparashuram.com/IndexedDBShim/
Can some please help me how to implement this as there are not enough documentation for this and I cannot figure out a any other solution / api except this
I have tested this on safari 5.1.7
Below is my code and Error Image
var request1 = indexedDB.open(dbName, 5);
request1.onsuccess = function (evt) {
db = request1.result;
var transaction = db.transaction(["AcceptedOrders"], "readwrite");
var objectStore = transaction.objectStore("AcceptedOrders");
for (var i in data) {
var request = objectStore.add(data[i]);
request.onsuccess = function (event) {
// alert("am again inserted")
// event.target.result == customerData[i].ssn;
};
}
};
request1.onerror = function (evt) {
alert("IndexedDB error: " + evt.target.errorCode);
};
Error Image
One blind guess
Maybe your dbName contains illegal characters for WebSQL database names. The polyfill doesn't translate your database names in any kind. So if you create a database called my-test, it would try to create a WebSQL database with the name my-test. This name is acceptable for an IndexedDB database, but in WebSQL you'll get in trouble because of the - character. So your database name has to match both, the IndexedDB and the WebSQL name conventions.
... otherwise use the debugger
You could set a break point onto your alert(...); line and use the debugger to look inside the evt object. This way you may get either more information about the error itself or more information to share with us.
To do so, enable the development menu in the Safari advanced settings, hit F10 and go to Developer > Start debugging JavaScript (something like that, my Safari is in a different language). Now open then "Scripts" tab in the developer window, select your script and set the break point by clicking on the line number. Reload the page and it should stop right in your error callback, where you can inspect the evt object.
If this doesn't help, you could get the non-minified version of the polyfill and try set some breakpoints around their open function to find the origin of this error.
You could try my open source library https://bitbucket.org/ytkyaw/ydn-db/wiki/Home. It works on iOS and Android.
I'm working on a Grails / Backbone / Handlebars application that's a front end to a much larger legacy Java system in which (for historical & customizability reasons) internationalization messages are deep in a database hidden behind a couple of SOAP services which are in turn hidden behind various internal Java libraries. Getting at these messages from the Grails layer is easy and works fine.
What I'm wondering, though, is how to get (for instance) internationalized labels into my Handlebars templates.
Right now, I'm using GSP fragments to generate the templates, including a custom tag that gets the message I'm interested in, something like:
<li><myTags:message msgKey="title"/> {{title}}</li>
However, for performance and code layout reasons I want to get away from GSP templates and get them into straight HTML. I've looked a little into client-side internationalization options such as i18n.js, but they seem to depend on the existence of a messages file I haven't got. (I could generate it, possibly, but it would be ginormous and expensive.)
So far the best thing I can think of is to wedge the labels into the Backbone model as well, so I'd end up with something like
<li>{{titleLabel}} {{title}}</li>
However, this really gets away from the ideal of building the Backbone models on top of a nice clean RESTful JSON API -- either the JSON returned by the RESTful service is cluttered up with presentation data (i.e., localized labels), or I have to do additional work to inject the labels into the Backbone model -- and cluttering up the Backbone model with presentation data seems wrong as well.
I think what I'd like to do, in terms of clean data and clean APIs, is write another RESTful service that takes a list of message keys and similar, and returns a JSON data structure containing all the localized messages. However, questions remain:
What's the best way to indicate (probably in the template) what message keys are needed for a given view?
What's the right format for the data?
How do I get the localized messages into the Backbone views?
Are there any existing Javascript libraries that will help, or should I just start making stuff up?
Is there a better / more standard alternative approach?
I think you could create quite an elegant solution by combining Handelbars helpers and some regular expressions.
Here's what I would propose:
Create a service which takes in a JSON array of message keys and returns an JSON object, where keys are the message keys and values are the localized texts.
Define a Handlebars helper which takes in a message key (which matches the message keys on the server) and outputs an translated text. Something like {{localize "messageKey"}}. Use this helper for all template localization.
Write a template preprocessor which greps the message keys from a template and makes a request for your service. The preprocessor caches all message keys it gets, and only requests the ones it doesn't already have.
You can either call this preprocessor on-demand when you need to render your templates, or call it up-front and cache the message keys, so they're ready when you need them.
To optimize further, you can persist the cache to browser local storage.
Here's a little proof of concept. It doesn't yet have local storage persistence or support for fetching the texts of multiple templates at once for caching purposes, but it was easy enough to hack together that I think with some further work it could work nicely.
The client API could look something like this:
var localizer = new HandlebarsLocalizer();
//compile a template
var html = $("#tmpl").html();
localizer.compile(html).done(function(template) {
//..template is now localized and ready to use
});
Here's the source for the lazy reader:
var HandlebarsLocalizer = function() {
var _templateCache = {};
var _localizationCache = {};
//fetches texts, adds them to cache, resolves deferred with template
var _fetch = function(keys, template, deferred) {
$.ajax({
type:'POST',
dataType:'json',
url: '/echo/json',
data: JSON.stringify({
keys: keys
}),
success: function(response) {
//handle response here, this is just dummy
_.each(keys, function(key) { _localizationCache[key] = "(" + key + ") localized by server"; });
console.log(_localizationCache);
deferred.resolve(template);
},
error: function() {
deferred.reject();
}
});
};
//precompiles html into a Handlebars template function and fetches all required
//localization keys. Returns a promise of template.
this.compile = function(html) {
var cacheObject = _templateCache[html],
deferred = new $.Deferred();
//cached -> return
if(cacheObject && cacheObject.ready) {
deferred.resolve(cacheObject.template);
return deferred.promise();
}
//grep all localization keys from template
var regex = /{{\s*?localize\s*['"](.*)['"]\s*?}}/g, required = [], match;
while((match = regex.exec(html))) {
var key = match[1];
//if we don't have this key yet, we need to fetch it
if(!_localizationCache[key]) {
required.push(key);
}
}
//not cached -> create
if(!cacheObject) {
cacheObject = {
template:Handlebars.compile(html),
ready: (required.length === 0)
};
_templateCache[html] = cacheObject;
}
//we have all the localization texts ->
if(cacheObject.ready) {
deferred.resolve(cacheObject.template);
}
//we need some more texts ->
else {
deferred.done(function() { cacheObject.ready = true; });
_fetch(required, cacheObject.template, deferred);
}
return deferred.promise();
};
//translates given key
this.localize = function(key) {
return _localizationCache[key] || "TRANSLATION MISSING:"+key;
};
//make localize function available to templates
Handlebars.registerHelper('localize', this.localize);
}
We use http://i18next.com for internationalization in a Backbone/Handlebars app. (And Require.js which also loads and compiles the templates via plugin.)
i18next can be configured to load resources dynamically. It supports JSON in a gettext format (supporting plural and context variants).
Example from their page on how to load remote resources:
var option = {
resGetPath: 'resources.json?lng=__lng__&ns=__ns__',
dynamicLoad: true
};
i18n.init(option);
(You will of course need more configuration like setting the language, the fallback language etc.)
You can then configure a Handlebars helper that calls i18next on the provided variable (simplest version, no plural, no context):
// namespace: "translation" (default)
Handlebars.registerHelper('_', function (i18n_key) {
i18n_key = Handlebars.compile(i18n_key)(this);
var result = i18n.t(i18n_key);
if (!result) {
console.log("ERROR : Handlebars-Helpers : no translation result for " + i18n_key);
}
return new Handlebars.SafeString(result);
});
And in your template you can either provide a dynamic variable that expands to the key:
<li>{{_ titleLabeli18nKey}} {{title}}</li>
or specify the key directly:
<li>{{_ "page.fancy.title"}} {{title}}</li>
For localization of datetime we use http://momentjs.com (conversion to local time, formatting, translation etc.).
I'm pretty inexperienced with actionscript, and I'm having the hardest time trying to figure out how to load variables from a file and send it to a dynamic text box.
The content of an external file, "varload.txt", is "name1=John".
Here is actionscript of my flash file:
myVars = new LoadVars();
myVars.onLoad = function(){
trace(this.name1); //prints "John" as expected
myname=this.name1;
}
myVars.sendAndLoad("varload.txt", myVars);
mytextbox.text=myname; //undefined
I'm guessing it's a scope issue, but I can't find much online about global variables in actionscript, so I'm not sure how to fix this.
How do I get mytextbox.text to equal John?
The issue is that onLoad is asynchronous (called once the file has loaded, not immediately).
You'll have to define the text within the onLoad function:
myVars = new LoadVars();
myVars.onLoad = function()
{
mytextbox.text = this.name1;
}
myVars.sendAndLoad("varload.txt", myVars);
With your code, you're trying to set the content of the text box to being data that doesn't exist / hasn't loaded yet.