detect.js

// copyright 2014, www.clickoncechrome.com

// API for web page owners to detect
// if ClickOnce is installed
window.CLICKONCE_EXTENSION_IS_INSTALLED = true;

HTMLEmbedElement.prototype.launchClickOnce = function (url) {
	var eventInitDict = {detail: {url: url}};
	var event = new CustomEvent('launchClickOnce', eventInitDict);
	document.dispatchEvent(event);
};


// For legacy apps detecting ClickOnce extension 
// by Plugin or MimeType support
(function() {

// Plugin

var p = Object.create(Plugin.prototype); // navigator.plugins[0].__proto__

definePropertyValues(p, {
	description: 'Provides ClickOnce support for Google Chrome',
	filename: 'npclickonce.dll',
	name: 'ClickOnce plugin for Chrome',
	length: 1
});

var pindex = navigator.plugins.length;
Object.defineProperty(navigator.plugins, 'length', {
  get: function() { return pindex + 1; }
});

navigator.plugins[pindex] = p;
navigator.plugins[p.name] = p;

var oldPluginsItem = navigator.plugins.item.bind(navigator.plugins);
navigator.plugins.item = function (i) {
	if (i == pindex) return p;
	return oldPluginsItem(i);
}

var oldPluginsNamedItem = navigator.plugins.namedItem.bind(navigator.plugins);
navigator.plugins.namedItem = function (i) {
	if (i == p.name) return p;
	return oldPluginsNamedItem(i);
}

// MimeType

var m = Object.create(MimeType.prototype); // navigator.plugins[0][0].__proto__

definePropertyValues(m, {
	description: 'ClickOnce Application',
	suffixes: 'application',
	type: 'application/x-ms-application',
	enabledPlugin: p
});

p[0] = m;

var mindex = navigator.mimeTypes.length;
Object.defineProperty(navigator.mimeTypes, 'length', {
  get: function() { return mindex + 1; }
});

navigator.mimeTypes[mindex] = m;
navigator.mimeTypes[m.type] = m; // m.type

var oldMimeTypesItem = navigator.mimeTypes.item.bind(navigator.mimeTypes);
navigator.mimeTypes.item = function (i) {
	if (i == mindex) return m;
	return oldMimeTypesItem(i);
}

var oldMimeTypesNamedItem = navigator.mimeTypes.namedItem.bind(navigator.mimeTypes);
navigator.mimeTypes.namedItem = function (i) {
	if (i == m.type) return m;
	return oldMimeTypesNamedItem(i);
}

// just some syntax sugar
function definePropertyValues(object, propertyValues) {
	Object.keys(propertyValues).forEach(function (property) {
		Object.defineProperty(object, property, { 
			value: propertyValues[property] 
		});
	});
}

})();

// if (details && details.url && details.requestHeaders && details.requestHeaders.length > 0) {