I'm currently working on a simple share function where I can share a news article via the URL (I.E. https://www.nrps.nl/Nieuws/Nieuwsitem.aspx?ID=812). I'm using React Native Share for this (code below). When sharing on Facebook it shows up as dnndev.me instead of nrps.nl, what I expected it to be. Clicking the dnndev.me link redirects to https://www.nrps.nl/Nieuws/Nieuwsitem.aspx?ID=812&fbclid=IwAR3Eq-j1wX8GUVvSEvhFNu85k8U_vjmV0l4_ycF-AUhoV61YBIieRGJgQg4 instead of https://www.nrps.nl/Nieuws/Nieuwsitem.aspx?ID=812, but the content is the same. (if I shouldn't show any of this, please edit it out. I don't know what the extra string means)
From what I can tell, dnndev.me seems to be a development environment.
The questions:
What is dnndev.me, besides some sort of host?
Can I do anything to work around it showing up as dnndev.me or can I only inform NRPS that they haven't done so already?
RN code:
let message = `${news.Title}\n${news.Image}\n${news.MessageUrl}`
news.title is a simple string. news.image is a URL to an image, news.MessageUrl is the URL of the news article itself. I've tested it with only the MessageUrl and it has the same result.
try {
const result = await Share.share({
message: `${message}`,
});
if (result.action === Share.sharedAction) {
if (result.activityType) {
// shared with activity type of result.activityType
} else {
// shared
}
} else if (result.action === Share.dismissedAction) {
// dismissed
console.log("Sharing dismissed")
}
} catch (e) {
console.log(e);
}
EDIT:
What I want to happen is to have the auto generated square / content field (or however it's called) like follows:
https://imgur.com/EalEbmZ
dnndev.me is a web server. As a web server, it notifies facebook of any problems in managing and operating facebook data and also solves any problems.
webSite of dnndev.me
And the fbclid behind the existing parameters is the visitor tracking system ID.
The acronym for fbclid is: "Facebook Click Identifier". It means a
Facebook click identifier.
It's about Facebook clicks.
These are parameters introduced for accurate statistics from this data.
We're also going to exchange data with Google Annalysis and AdSense.
Make more accurate estimates of visitors.
To share Facebook, you can use the following modules to work around it: This solution is contained in the Facebook developer's official document.
$yarn add react-native-fbsdk or npm install --save react-native-fbsdk
$ react-native link react-native-fbsdk
Note For iOS using cocoapods, run:
$ cd ios/ && pod install
Usage
import { ShareDialog } from 'react-native-fbsdk';
let message = `${news.Title}\n${news.Image}\n${news.MessageUrl}`
const shareLinkContent = {
contentType: 'link',
contentUrl: "https://www.nrps.nl/Nieuws/Nieuwsitem.aspx?ID=812",
contentDescription: message,
};
...
this.state = {shareLinkContent: shareLinkContent,};
...
shareLinkWithShareDialog() {
var tmp = this;
ShareDialog.canShow(this.state.shareLinkContent).then(
function(canShow) {
if (canShow) {
return ShareDialog.show(tmp.state.shareLinkContent);
}
}
).then(
function(result) {
if (result.isCancelled) {
alert('Share operation was cancelled');
} else {
alert('Share was successful with postId: '
+ result.postId);
}
},
function(error) {
alert('Share failed with error: ' + error.message);
}
);
}
I'm trying to use the desktopCapture API in the following manner.
chrome.desktopCapture.chooseDesktopMedia(
["screen", "window"], onAccessApproved);
chrome.desktopCapture shows as undefined when I set a breakpoint and inspect it. Permissions in my manifest file are as follows:-
"permissions": ["desktopCapture", "notifications" ]
Common causes for failure of this API are listed here as
a permission is missing in the application's manifest.json file
the API is defined on a newer version of Chrome then the current runtime
docs inherited from ChromeApi
And I don't have those problems.
My Chrome version is 43.0.2357.124 m
Pepper version is 43
FYI, I am trying to develop a Chrome extension to capture the screen using PNacl, and have borrowed from the media_stream_video example downloaded from here. But I haven't even gotten to sending a message to the pexe side yet. I'm still stuck at chrome.desktopCapture.chooseDesktopMedia returning undefined.
You need to call chrome.desktopCapture.chooseDesktopMedia from the background script running in the context of the extension. This Sample shows a simple method to use the extension to get screen media.
Keep in mind that this is callback based, so you get access to the stream id from the callback.
This runs in the context of your page (see full example here):
// check that the extension is installed
if (sessionStorage.getScreenMediaJSExtensionId) {
// send a message to your extension requesting media
chrome.runtime.sendMessage(sessionStorage.getScreenMediaJSExtensionId,
{type:'getScreen', id: 1}, null,
function (data) {
if (data.sourceId === '') { // user canceled
// handle error
} else {
constraints.video.mandatory.chromeMediaSourceId = data.sourceId;
getUserMedia(constraints, callback);
}
}
);
}
And this run in the context of your extension (see full example here):
chrome.runtime.onMessageExternal.addListener(function (message, sender, callback) {
switch(message.type) {
case 'getScreen':
var pending = chrome.desktopCapture.chooseDesktopMedia(message.options || ['screen', 'window'],
sender.tab, function (streamid) {
// communicate this string to the app so it can call getUserMedia with it
message.type = 'gotScreen';
message.sourceId = streamid;
callback(message);
return false;
});
return true; // retain callback for chooseDesktopMedia result
}
});
I am in the process of building a Chrome extension, and for the whole thing to work the way I would like it to, I need an external JavaScript script to be able to detect if a user has my extension installed.
For example: A user installs my plugin, then goes to a website with my script on it. The website detects that my extension is installed and updates the page accordingly.
Is this possible?
Chrome now has the ability to send messages from the website to the extension.
So in the extension background.js (content.js will not work) add something like:
chrome.runtime.onMessageExternal.addListener(
function(request, sender, sendResponse) {
if (request) {
if (request.message) {
if (request.message == "version") {
sendResponse({version: 1.0});
}
}
}
return true;
});
This will then let you make a call from the website:
var hasExtension = false;
chrome.runtime.sendMessage(extensionId, { message: "version" },
function (reply) {
if (reply) {
if (reply.version) {
if (reply.version >= requiredVersion) {
hasExtension = true;
}
}
}
else {
hasExtension = false;
}
});
You can then check the hasExtension variable. The only drawback is the call is asynchronous, so you have to work around that somehow.
Edit:
As mentioned below, you'll need to add an entry to the manifest.json listing the domains that can message your addon. Eg:
"externally_connectable": {
"matches": ["*://localhost/*", "*://your.domain.com/*"]
},
2021 Update:
chrome.runtime.sendMessage will throw the following exception in console if the extension isn't installed or it's disabled.
Unchecked runtime.lastError: Could not establish connection. Receiving end does not exist
To fix this, add this validation inside the sendMessage callback
if (chrome.runtime.lastError) {
// handle error
}
I am sure there is a direct way (calling functions on your extension directly, or by using the JS classes for extensions), but an indirect method (until something better comes along):
Have your Chrome extension look for a specific DIV or other element on your page, with a very specific ID.
For example:
<div id="ExtensionCheck_JamesEggersAwesomeExtension"></div>
Do a getElementById and set the innerHTML to the version number of your extension or something. You can then read the contents of that client-side.
Again though, you should use a direct method if there is one available.
EDIT: Direct method found!!
Use the connection methods found here: https://developer.chrome.com/extensions/extension#global-events
Untested, but you should be able to do...
var myPort=chrome.extension.connect('yourextensionid_qwerqweroijwefoijwef', some_object_to_send_on_connect);
Another method is to expose a web-accessible resource, though this will allow any website to test if your extension is installed.
Suppose your extension's ID is aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, and you add a file (say, a transparent pixel image) as test.png in your extension's files.
Then, you expose this file to the web pages with web_accessible_resources manifest key:
"web_accessible_resources": [
"test.png"
],
In your web page, you can try to load this file by its full URL (in an <img> tag, via XHR, or in any other way):
chrome-extension://aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/test.png
If the file loads, then the extension is installed. If there's an error while loading this file, then the extension is not installed.
// Code from https://groups.google.com/a/chromium.org/d/msg/chromium-extensions/8ArcsWMBaM4/2GKwVOZm1qMJ
function detectExtension(extensionId, callback) {
var img;
img = new Image();
img.src = "chrome-extension://" + extensionId + "/test.png";
img.onload = function() {
callback(true);
};
img.onerror = function() {
callback(false);
};
}
Of note: if there is an error while loading this file, said network stack error will appear in the console with no possibility to silence it. When Chromecast used this method, it caused quite a bit of controversy because of this; with the eventual very ugly solution of simply blacklisting very specific errors from Dev Tools altogether by the Chrome team.
Important note: this method will not work in Firefox WebExtensions. Web-accessible resources inherently expose the extension to fingerprinting, since the URL is predictable by knowing the ID. Firefox decided to close that hole by assigning an instance-specific random URL to web accessible resources:
The files will then be available using a URL like:
moz-extension://<random-UUID>/<path/to/resource>
This UUID is randomly generated for every browser instance and is not your extension's ID. This prevents websites from fingerprinting the extensions a user has installed.
However, while the extension can use runtime.getURL() to obtain this address, you can't hard-code it in your website.
I thought I would share my research on this.
I needed to be able to detect if a specific extension was installed for some file:/// links to work.
I came across this article here
This explained a method of getting the manifest.json of an extension.
I adjusted the code a bit and came up with:
function Ext_Detect_NotInstalled(ExtName, ExtID) {
console.log(ExtName + ' Not Installed');
if (divAnnounce.innerHTML != '')
divAnnounce.innerHTML = divAnnounce.innerHTML + "<BR>"
divAnnounce.innerHTML = divAnnounce.innerHTML + 'Page needs ' + ExtName + ' Extension -- to intall the LocalLinks extension click here';
}
function Ext_Detect_Installed(ExtName, ExtID) {
console.log(ExtName + ' Installed');
}
var Ext_Detect = function (ExtName, ExtID) {
var s = document.createElement('script');
s.onload = function () { Ext_Detect_Installed(ExtName, ExtID); };
s.onerror = function () { Ext_Detect_NotInstalled(ExtName, ExtID); };
s.src = 'chrome-extension://' + ExtID + '/manifest.json';
document.body.appendChild(s);
}
var is_chrome = navigator.userAgent.toLowerCase().indexOf('chrome') > -1;
if (is_chrome == true) {
window.onload = function () { Ext_Detect('LocalLinks', 'jllpkdkcdjndhggodimiphkghogcpida'); };
}
With this you should be able to use Ext_Detect(ExtensionName,ExtensionID) to detect the installation of any number of extensions.
Another possible solution if you own the website is to use inline installation.
if (chrome.app.isInstalled) {
// extension is installed.
}
I know this an old question but this way was introduced in Chrome 15 and so I thought Id list it for anyone only now looking for an answer.
Here is an other modern approach:
const checkExtension = (id, src, callback) => {
let e = new Image()
e.src = 'chrome-extension://'+ id +'/'+ src
e.onload = () => callback(1), e.onerror = () => callback(0)
}
// "src" must be included to "web_accessible_resources" in manifest.json
checkExtension('gighmmpiobklfepjocnamgkkbiglidom', 'icons/icon24.png', (ok) => {
console.log('AdBlock: %s', ok ? 'installed' : 'not installed')
})
checkExtension('bhlhnicpbhignbdhedgjhgdocnmhomnp', 'images/checkmark-icon.png', (ok) => {
console.log('ColorZilla: %s', ok ? 'installed' : 'not installed')
})
I used the cookie method:
In my manifest.js file I included a content script that only runs on my site:
"content_scripts": [
{
"matches": [
"*://*.mysite.co/*"
],
"js": ["js/mysite.js"],
"run_at": "document_idle"
}
],
in my js/mysite.js I have one line:
document.cookie = "extension_downloaded=True";
and in my index.html page I look for that cookie.
if (document.cookie.indexOf('extension_downloaded') != -1){
document.getElementById('install-btn').style.display = 'none';
}
You could have the extension set a cookie and have your websites JavaScript check if that cookie is present and update accordingly. This and probably most other methods mentioned here could of course be cirvumvented by the user, unless you try and have the extension create custom cookies depending on timestamps etc, and have your application analyze them server side to see if it really is a user with the extension or someone pretending to have it by modifying his cookies.
There's another method shown at this Google Groups post. In short, you could try detecting whether the extension icon loads successfully. This may be helpful if the extension you're checking for isn't your own.
Webpage interacts with extension through background script.
manifest.json:
"background": {
"scripts": ["background.js"],
"persistent": true
},
"externally_connectable": {
"matches": ["*://(domain.ext)/*"]
},
background.js:
chrome.runtime.onMessageExternal.addListener(function(msg, sender, sendResponse) {
if ((msg.action == "id") && (msg.value == id))
{
sendResponse({id : id});
}
});
page.html:
<script>
var id = "some_ext_id";
chrome.runtime.sendMessage(id, {action: "id", value : id}, function(response) {
if(response && (response.id == id)) //extension installed
{
console.log(response);
}
else //extension not installed
{
console.log("Please consider installig extension");
}
});
</script>
Your extension could interact with the website (e.g. changing variables) and your website could detect this.
But there should be a better way to do this. I wonder how Google is doing it on their extension gallery (already installed applications are marked).
Edit:
The gallery use the chrome.management.get function. Example:
chrome.management.get("mblbciejcodpealifnhfjbdlkedplodp", function(a){console.log(a);});
But you can only access the method from pages with the right permissions.
A lot of the answers here so far are Chrome only or incur an HTTP overhead penalty. The solution that we are using is a little different:
1. Add a new object to the manifest content_scripts list like so:
{
"matches": ["https://www.yoursite.com/*"],
"js": [
"install_notifier.js"
],
"run_at": "document_idle"
}
This will allow the code in install_notifier.js to run on that site (if you didn't already have permissions there).
2. Send a message to every site in the manifest key above.
Add something like this to install_notifier.js (note that this is using a closure to keep the variables from being global, but that's not strictly necessary):
// Dispatch a message to every URL that's in the manifest to say that the extension is
// installed. This allows webpages to take action based on the presence of the
// extension and its version. This is only allowed for a small whitelist of
// domains defined in the manifest.
(function () {
let currentVersion = chrome.runtime.getManifest().version;
window.postMessage({
sender: "my-extension",
message_name: "version",
message: currentVersion
}, "*");
})();
Your message could say anything, but it's useful to send the version so you know what you're dealing with. Then...
3. On your website, listen for that message.
Add this to your website somewhere:
window.addEventListener("message", function (event) {
if (event.source == window &&
event.data.sender &&
event.data.sender === "my-extension" &&
event.data.message_name &&
event.data.message_name === "version") {
console.log("Got the message");
}
});
This works in Firefox and Chrome, and doesn't incur HTTP overhead or manipulate the page.
You could also use a cross-browser method what I have used.
Uses the concept of adding a div.
in your content script (whenever the script loads, it should do this)
if ((window.location.href).includes('*myurl/urlregex*')) {
$('html').addClass('ifextension');
}
in your website you assert something like,
if (!($('html').hasClass('ifextension')){}
And throw appropriate message.
If you have control over the Chrome extension, you can try what I did:
// Inside Chrome extension
var div = document.createElement('div');
div.setAttribute('id', 'myapp-extension-installed-div');
document.getElementsByTagName('body')[0].appendChild(div);
And then:
// On web page that needs to detect extension
if ($('#myapp-extension-installed-div').length) {
}
It feels a little hacky, but I couldn't get the other methods to work, and I worry about Chrome changing its API here. It's doubtful this method will stop working any time soon.
If you're trying to detect any extension from any website,
This post helped: https://ide.hey.network/post/5c3b6c7aa7af38479accc0c7
Basically, the solution would be to simply try to get a specific file (manifest.json or an image) from the extension by specifying its path. Here's what I used. Definitely working:
const imgExists = function(_f, _cb) {
const __i = new Image();
__i.onload = function() {
if (typeof _cb === 'function') {
_cb(true);
}
}
__i.onerror = function() {
if (typeof _cb === 'function') {
_cb(false);
}
}
__i.src = _f;
__i = null;
});
try {
imgExists("chrome-extension://${CHROME_XT_ID}/xt_content/assets/logo.png", function(_test) {
console.log(_test ? 'chrome extension installed !' : 'chrome extension not installed..');
ifrm.xt_chrome = _test;
// use that information
});
} catch (e) {
console.log('ERROR', e)
}
Here is how you can detect a specific Extension installed and show a warning message.
First you need to open the manifest file of the extension by going to chrome-extension://extension_id_here_hkdppipefbchgpohn/manifest.json and look for any file name within "web_accessible_resources" section.
<div class="chromewarning" style="display:none">
<script type="text/javascript">
$.get("chrome-extension://extension_id_here_hkdppipefbchgpohn/filename_found_in_ web_accessible_resources.png").done(function () {
$(".chromewarning").show();
}).fail(function () {
// alert("failed.");
});
</script>
<p>We have detected a browser extension that conflicts with learning modules in this course.</p>
</div>
Chrome Extension Manifest v3:
const isFirefox = chrome.runtime.OnInstalledReason.CHROME_UPDATE != "chrome_update";
For FireFox, I believe chrome.runtime.OnInstalledReason.BROWSER_UPDATE will be "browser_update": https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/OnInstalledReason
I am using Selenium 1.7.2 on Firefox 11 running on Ubuntu 11.10. Until yesterday, we didn't use the document.domain javascript. We needed to add it to our generated HTML and in one of our javascript file.
Now when we run Selenium IDE Test Suite, we get the following error:
Error: Permission denied for <http://dev.example.com> to get property Location.href
dev.example.com is our application server (Glassfish 3.1.2 behind Apache+mod_jk)
If I comment out document.domain everything works well (at least in Firefox, because the document.domain is to prevent IE to block PIE.htc script... sigh )
I tried adding a user extension script found here:
function setdom(str,doc,dom) {
doc.domain = dom;
}
Selenium.prototype.doDocumentDomain = function(domain) {
var lw;
setdom('ts',frames['testSuiteFrame'].document, domain);
setdom('tf', getTestFrame().contentWindow.document, domain);
setdom('my', frames['myiframe'].document, domain);
lw = LOG.getLogWindow();
if (lw) {
setdom('log', lw.document, domain);
}
setdom('doc', document, domain);
}
but this looks pretty old and probably not compatible any more. It returns an error at the first call to the setdom('ts',frames['testSuiteFrame'].document,domain); line
I am not browsing back and forth between HTTP and HTTPS, I have read many StackOverflow and Google Group related questions, to no result.
I can modify our codes to include document.domain only for IE but it is not very clean...
Question: How to make Selenium IDE working without security issue when document.domain is set? Or how can I fix he above user extension to work in Selenium IDE 1.7.2? Thank you.
So I decided to change Selenium javascript to allow me to set the document.domain using this:
In `chrome/content/selenium-core/scripts/selenium-browserbot.js on line 920 (for version 1.7.2):
//Samit: Fix: open command sometimes fails if current url is chrome and new is not
windowObject = core.firefox.unwrap(windowObject);
// -------------- Start My Change ----------------
updateDomain(windowObject.document);
// -------------- End My Change ----------------
if (this._windowClosed(windowObject)) {
LOG.debug("pollForLoad WINDOW CLOSED (" + marker + ")");
delete this.pollingForLoad[marker];
return;
}
Then in user-extensions.js:
var validDomain = null;
Selenium.prototype.doDocumentDomain = function(domain) {
validDomain = domain;
}
function updateDomain(doc) {
if(validDomain==null) {
return;
}
LOG.info("Current domain: " + doc.domain);
if(doc.domain != validDomain && (doc.domain+"").indexOf(validDomain)>0 ) {
doc.domain = validDomain;
}
LOG.info("New domain: " + doc.domain);
}
I check prior to setting the new domain that it is a subdomain of the one I want to set. I use it in Selenium IDE:
documentDomain | example.com
So when it opens dev.example.com and static.example.com, it finds example.com in the domain and replace the domain.
I'm using the Firefox Addon SDK to build something that monitors and displays the HTTP traffic in the browser. Similar to HTTPFox or Live HTTP Headers. I am interested in identifying which tab in the browser (if any) generated the request
Using the observer-service I am monitoring for "http-on-examine-response" events. I have code like the following to identify the nsIDomWindow that generated the request:
const observer = require("observer-service"),
{Ci} = require("chrome");
function getTabFromChannel(channel) {
try {
var noteCB= channel.notificationCallbacks ? channel.notificationCallbacks : channel.loadGroup.notificationCallbacks;
if (!noteCB) { return null; }
var domWin = noteCB.getInterface(Ci.nsIDOMWindow);
return domWin.top;
} catch (e) {
dump(e + "\n");
return null;
}
}
function logHTTPTraffic(sub, data) {
sub.QueryInterface(Ci.nsIHttpChannel);
var ab = getTabFromChannel(sub);
console.log(tab);
}
observer.add("http-on-examine-response", logHTTPTraffic);
Mostly cribbed from the documentation for how to identify the browser that generated the request. Some is also taken from the Google PageSpeed Firefox addon.
Is there a recommended or preferred way to go from the nsIDOMWindow object domWin to a tab element in the SDK tabs module?
I've considered something hacky like scanning the tabs list for one with a URL that matches the URL for domWin, but then I have to worry about multiple tabs having the same URL.
You have to keep using the internal packages. From what I can tell, getTabForWindow() function in api-utils/lib/tabs/tab.js package does exactly what you want. Untested code:
var tabsLib = require("sdk/tabs/tab.js");
return tabsLib.getTabForWindow(domWin.top);
The API has changed since this was originally asked/answered...
It should now (as of 1.15) be:
return require("sdk/tabs/utils").getTabForWindow(domWin.top);
As of Addon SDK version 1.13 change:
var tabsLib = require("tabs/tab.js");
to
var tabsLib = require("sdk/tabs/helpers.js");
If anyone still cares about this:
Although the Addon SDK is being deprecated in support of the newer WebExtensions API, I want to point out that
var a_tab = require("sdk/tabs/utils").getTabForContentWindow(window)
returns a different 'tab' object than the one you would typically get by using
worker.tab in a PageMod.
For example, a_tab will not have the 'id' attribute, but would have linkedPanel property that's similar to the 'id' attribute.