NPP_New not getting called in few webpages (Chrome and Safari) - google-chrome-extension

I am trying to access NPAPI plugin from content/inject script of Chrome/Safari extensions.
The code to embed the plugin object and access methods.
var newElement = document.createElement("embed");
newElement.id = "myPluginID";
newElement.type = "application/x-mychrome-plugin";
var newAttr = document.createAttribute("hidden");
newAttr.nodeValue = "true"
newElement.setAttributeNode(newAttr);
newElement.style.zIndex = "-1";
newElement.style.position = "absolute";
newElement.style.top = "0px";
document.documentElement.appendChild(newElement);
plugin = document.getElementById("myPluginID"); //this shows as HTML element when evaluated in JavaScript console.
plugin.myPluginMethod() // this shows as undefined instead of native code(When evaluated in JavaScript console),for pages where NPP_New is not called.
This works for most of the webpages,but for few pages(eg:www.stumbleupon.com),NPP_New is not called(debugging using Xcode 4) and scriptable object is not created and all the plugin methods are undefined.
Any inputs.

Why are you putting your embed as a child of document.documentElement (i.e., <html>) instead of in the body? I wouldn't expect a plugin that's not going to be displayed to be instantiated.

Related

SPO Modern: How to inject and execute webpart programmatically, using js?

I have only the URL of webpart (example 'https://sitename.com/sites/site-colection/ClientSideAssets/hereisguid/webpartname.js') and I need to inject and run it programmatically via js, is it possible?
It's not officially supported but You can use global variable (available on every modern page) _spComponentLoader. The problem is - it requires You to provide WebPartContext which You cannot simply get outside of SPFx.
If You want to do it in SPFx here is a sample code:
webPartId = hereisguid from Your url
let component = await _spComponentLoader.loadComponentById(webPartId);
let manifest = _spComponentLoader.tryGetManifestById(webPartId);
let wpInstance = new component.default();
context.manifest = manifest;
//#ts-ignore
context._domElement = document.getElementById("<id-of-element-you-want-wp-to-render-in>")
await wpInstance._internalInitialize(context, {}, 1);
wpInstance._properties = webPart.properties;
await wpInstance.onInit();
wpInstance.render();
wpInstance._renderedOnce = true;
Again - I don't think it's supported so try it on Your own risk.
Note this web part must be available at the site You are going to execute this script.

Can navigator give you the language/languages in Angular Universal?

My question stems from the fact that navigator works for the browser but we don't have that on the server but in our codebase at work I have seen code like this:
navigator.language.slice(0, 2);
and of course we are using domino to provide these window objects
win.Object = Object;
win.Math = Math;
global["window"] = win;
global["document"] = win.document;
global["branch"] = null;
global["object"] = win.object;
global["HTMLElement"] = win.HTMLElement;
global["navigator"] = win.navigator;```
No it cannot, domino provides a fake DOM server side.
You will need to either use a separate url for each language of your website, and/or save user preferences in cookies so that you can use the right language during SSR.

Default Media Receiver limitations

Can I use the Default Media Receiver to display a web page or an HTML5 app? Using Javascript in the Chrome browser, I have no problem sending a single png image (content type image/png) to the Chromecast but it fails if I specify an html link (content type text/html). session.loadMedia will fire the error handler and e.code/e.description reports session_error/LOAD_FAILED. I used Google's home page for my test:
//var currentMediaURL = "https://www.google.com/images/srpr/logo11w.png";
//var currentMediaType = "image/png";
var currentMediaURL = "https://www.google.com";
var currentMediaType = "text/html";
function startApp()
{
var mediaInfo = new chrome.cast.media.MediaInfo(currentMediaURL, currentMediaType);
var request = new chrome.cast.media.LoadRequest(mediaInfo);
session.loadMedia(request, onMediaDiscovered.bind(this, 'loadMedia'), onMediaError);
};
I think you need to have custom receiver, just have it run your code accordingly...

Clean way to pass events to Titanium from webview?

A common explanation of how to pass events from a Titanium webview involves calling Ti.App.fireEvent() from the HTML in the webview. But, I would like to listen to the webview itself instead of the global Ti.App object, so that duplicate events from different webviews won't trigger inappropriate code for the context.
Eg. if I listen to Ti.App for the "OK_BUTTON" event, it will mean something different depending on where in the flow it is being called. So, I would have to remove and add new listeners for each context.
There is a documented way to pass events directly from the webview using a normal HTML anchor tag with the undefined protocol "xxxx://" and catching the ensuing error event in Titanium. Is there a cleaner way to do this yet? It would be nice to keep the "error" event for errors as intended.
I think you'll need to use Ti.App.fireEvent() from the webview but add data identifying the source webview to the event.
e.g. assign a unique id to each of your webviews and pass that into the webview by doing an 'evalJS()' in the webview's 'load' event handler. (Or by setting the id in your html if you have Titanium generating that)
Here is a basic utility module that assigns an id to a webview and provides a function fireEvent() to webview context that will trigger an event on the webView object in Titanium.
var listenerWebViews = {};
exports.createListenerWebView = function(config) {
var id = createRandomString();
var webView = Ti.UI.createWebView(config);
webView.listenerId = id;
webView.evalJS('function fireEvent(type, e) { var f = { originalType:type, listenerId:"'+id+'"}; Ti.App.fireEvent("WEBVIEW_LISTENER_EVENT", f); }');
listenerWebViews[id] = webView;
var oldRemoveFunction = webView.remove;
webView.remove = function(){
listenerWebViews[id] = null;
oldRemoveFunction();
}
return webView;
}
Ti.App.addEventListener("WEBVIEW_LISTENER_EVENT", function(e){
var webView = listenerWebViews[e.listenerId];
if (webView) {
webView.fireEvent(e.originalType, e);
}
});
With that module included, this works:
var view = module.createListenerWebView({
url: 'myPage.html'
});
view.addEventListener('my_type', function(){
alert('webview event!');
});
view.evalJS("fireEvent('my_type');");

firefox extension saving in preferences

I want to save a simple string into preferences in my firefox extension. The string should be accessible between separate browser sessions and after reboot. I found the following code but for some reason it is not working. I tried localStorage before but this was also not working:
Code for saving function:
var prefs = Components.classes["#mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefBranch);
var str = Components.classes["#mozilla.org/supports-string;1"]
.createInstance(Components.interfaces.nsISupportsString);
str.data = window['myglobalvariable'];
prefs.setComplexValue("myglobvar",
Components.interfaces.nsISupportsString, str);
Code for retrieval function:
var prefs = Components.classes["#mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefBranch);
var value = prefs.getComplexValue("myglobvar",
Components.interfaces.nsISupportsString).data;
I cannot figure out why is it not working.
if your preference is a integer or boolean getCharPref wont work you would have to use
getBoolPref() or getIntPref()
http://blog.mozilla.org/addons/2009/01/28/how-to-develop-a-firefox-extension/

Resources