_I'm not sure if this is the right place to post this, but i feel like this will be the place everyone will check after figuring out they couldn't install addons so this might be more helpful than other places._
So, i just installed ungoogled-chromium and not being able to install extensions from the store was pretty disappointing. So i searched around and found the FAQ which gives a nice workaround to use. So i quickly made a PHP script and a little userscript that connected to the php script to automatically get the CRX of a url. I am posting the script here if any of you want to use it.
So, you can get the userscript at: http://chromium-crx.stuff.admicos.cf/get.user.js (now fully clientside)
And a PHP API(?) that it uses can be found on the same domain as: http://chromium-crx.stuff.admicos.cf (GET request with _?u=
(For the userscript to show the Get CRX button, you might want to reload the extension page after you open it as it doesn't work with Google's soft reload-y thing.)
This is pretty neat and it's very generous of you to share this with the community. However I would prefer a solution that has all of the logic in the client, like #83. Given that privacy and openness are some of the fundamental goals of this project, I don't think involving another blackbox (i.e. the server you setup) would help reach this goal. This is not to say that you have malicious intentions, but I think a number of users would not prefer your solution.
However, a script or extension that adds or modifies a button on the Chrome Webstore to download and install the CRX file wouldn't be a bad idea; it would be a little more elegant than one of the buttons proposed in #83.
After reading your reply, i think it's better to do everything clientside than send a request to my server. It's just a couple of string replaces, should be easy to port over. I'll still leave the PHP script up for convenience though.
Also, the PHP script's source available here if anyone wants to look at how i did it.
EDIT: The userscript has been updated to do everything clientside.
Oh that's neat. Is there some JavaScript API to read the actual browser version in place of the hardcoded version in the URL?
I don't think there is, unless i try to extract it from the user agent, but most people will probably change it so that won't be effective.
@Admicos I've added your userscript to the FAQ now. Had to workaround some weird glitch that GitHub gave me when pushing though...
My 2c:
#! /usr/bin/env bash
set -e
readonly URL_EXT_DL='https://clients2.google.com/service/update2/crx?response=redirect&prodversion=48.0&x=id%3D{id_ext}%26installsource%3Dondemand%26uc'
readonly PATH_EXTENSIONS="${XDG_CONFIG_HOME:-${HOME}/.config}/chromium/Extensions"
readonly PATH_TMP_DIR=$(mktemp -d)
trap "rm -rf '${PATH_TMP_DIR}'" ERR
fatal() {
echo "$@" >&2
exit 1
}
get_json_value() {
grep "\"$2\":" "$1" \
| sed 's/^[[:space:]]*[^[:space:]]*[[:space:]]*"\(.*\)".*$/\1/'
}
main() {
if [ $# -lt 1 ]; then
fatal "Usage: $0 <extension id>"
fi
readonly ID_EXT="$1"
mkdir -p "${PATH_EXTENSIONS}"
url=$(printf %s "${URL_EXT_DL}" | sed "s/{id_ext}/${ID_EXT}/g")
wget -O "${PATH_TMP_DIR}/extension.crx" "${url}"
7z x -o"${PATH_TMP_DIR}" "${PATH_TMP_DIR}/extension.crx"
rm -r "${PATH_TMP_DIR}/_metadata" "${PATH_TMP_DIR}/extension.crx"
name_ext=$(get_json_value "${PATH_TMP_DIR}/manifest.json" "name" \
| sed 's/[^[:alnum:]]/-/g')
version_ext=$(get_json_value "${PATH_TMP_DIR}/manifest.json" "version")
path_ext="${PATH_EXTENSIONS}/${name_ext}_${version_ext}"
mv -f "${PATH_TMP_DIR}" "${path_ext}"
printf %s\\n "Extension installed at ${path_ext}"
}
main "$@"
how does that script work? i don't see any button on store's extension page.
@perfect7gentleman Are you using Tampermonkey to install it? If not then you should. If you are using Tampermonkey, try this:
If you are opening the extension details from the store and not from a external link, try refreshing since Tampermonkey doesn't play well with the soft-reload thing Google is doing.
The button should appear where the original "Install Extension" button would be.
@Admicos, i don't use Tampermonkey, but uMatrix. I've disabled it but it won't help.
http://pasteboard.co/6ZCkE9TTv.png
@perfect7gentleman I don't think uMatrix blocks it. But i only tested it using Tampermonkey so yeah.
Can you tell me how you installed the script?
@Admicos, I've just drap&drop it into the extensions tab.
http://pasteboard.co/HnHzwEhK.png
@perfect7gentleman You'll want to use Tampermonkey to install the script as currently it requires it to do its thing. I'll look into making it work with Chrome's own userscript loader.
@Admicos, still no luck :(
I just checked with "normal" Chromium and it doesn't work here too. This is getting weird.
EDIT: It looks like either Chrome (or Tampermonkey) disables extensions at the Chrome Web Store or i screwed up my URL matches
@Admicos Ah yeah they do. I ran into that problem with Disable HTML5 Autoplay ages ago (about over a year). It's annoying, but it's a security measure to prevent hacking for oblivious users.
Also I wasn't aware that there was any other user script loader other than Chromium's for Chromium. I guess that means the Chromium sourcecode has to be modified.
What's funny is that it actually works without any issues on my Windows partition (that i developed the userscript in).
heh
With the latest realease, I'm unable to drag anything into the extensions page. As such, I can't even install Tampermonkey, nor can I install this natively (that is possible, right?).
@mikerockett I can still drag extensions onto the extensions page to install them on Linux. What platform are you using?
@Eloston I'm Win10 64-bit. I'd installed all my current extensions with the v54 through chrome-extension-downloader.com, and now it appears I can't.
Update: Interesting -- just tried it again, and it worked... Not sure what could possibly have blocked it. Yesterday, after several attempts, dragging the crx into the extensions tab didn't show the drop-to-install box and, upon release, Chrome would simply re-download the crx file... But it is working now...
@mikerockett I usually drag extensions from the file manager, so there's no chance that Chromium would interpret the dropped content as a URL.
@Eloston I didn't try from file explorer, dragged it directly from the download-bar... Something must've been interfering - perhaps a browser restart was the solution, for some weird reason.
Could this user script be included in ungoogled-chromium?
@szepeviktor We haven't confirmed if the script actually works everywhere yet. Even if it did, I would probably just link to it from the FAQ.
The problem with this userscript is that it uses @require to add jquery while built-in userscript executor in Chromium does not support this directive:
http://www.chromium.org/developers/design-documents/user-scripts
So you need Greasemonkey to use it and can't install by simply dragging the file into extenstions.
Here is the simple modified version without @require, jquery and need for Greasemonkey:
// ==UserScript==
// @name Get CRX
// @description Get crx of extension for Chrome
// @match https://chrome.google.com/webstore/detail/*
// @grant none
// ==/UserScript==
window.setTimeout( function () {
var href = 'https://clients2.google.com/service/update2/crx?response=redirect&prodversion=48.0&x=id%3D[EXTENSION_ID]%26installsource%3Dondemand%26uc';
var id = window.location.href;
id = id.replace( 'https://chrome.google.com/webstore/detail/', '' );
id = id.split( '/' )[ 1 ];
id = id.split( '?' )[ 0 ];
href = href.replace( '[EXTENSION_ID]', id );
var link = document.createElement( 'a' );
link.href = href;
link.innerHTML = 'Get CRX';
document.querySelector( 'div.h-e-f-Ra-c.e-f-oh-Md-zb-k' ).appendChild( link );
}, 4000 );
@vonagam Interesting hack. Does this actually work? I was certain that Google added a restriction so that no extension or user script could touch the Chrome Web Store. (On second thought, maybe domain substitution made that checking function match against the wrong domain...)
FYI, it's a lot easier to modify URLs with HTMLAnchorElement
Yes, it works. I installed fresh setup with brew cask, couldn't install extensions, so went looking into issues, find this script, installed by dragging into extensions, saw errors about jquery, fixed it, and it worked.
You click the link, a crx file gets downloaded, which you can drop into extensions. As simple as it intended to be.
URL manipulation code is from original userscript, i just removed dependency on jquery. Also increased timeout to 4 seconds. Yeah, the script can be impoved a little bit ( to wait until .h-e-f-Ra-c.e-f-oh-Md-zb-k appears instead of timeout, for example ), but it gets job done.
My attempt to improve the script even further beyond:
1) Uses interval waiting for potential button container to appear.
2) Uses web store classes for button, so that it appears as official one.
3) Simplified id retrieval from location.
// ==UserScript==
// @name Get CRX
// @description Download CRX of extension from Chrome Web Store
// @match https://chrome.google.com/webstore/detail/*
// @grant none
// ==/UserScript==
var HREF_TEMPLATE = 'https://clients2.google.com/service/update2/crx?response=redirect&prodversion=48.0&x=id%3D[EXTENSION_ID]%26installsource%3Dondemand%26uc';
var BUTTON_TEMPLATE = '<a href="[HREF]" role="button" class="dd-Va g-c g-c-wb g-eg-ua-Uc-c-za" aria-label="Download CTX" tabindex="0" style="user-select: none;">Download CTX</a>';
var CONTAINER_SELECTOR = '.h-e-f-Ra-c.e-f-oh-Md-zb-k';
var pathnameParts = window.location.pathname.split( '/' );
if ( pathnameParts.length !== 5 ) return;
var id = pathnameParts[ 4 ];
var href = HREF_TEMPLATE.replace( '[EXTENSION_ID]', id );
var intervalId = setInterval( function () {
var container = document.querySelector( CONTAINER_SELECTOR );
if ( ! container ) return;
container.innerHTML = BUTTON_TEMPLATE.replace( '[HREF]', href );
clearInterval( intervalId );
}, 500 );
You may wrap the whole thing in a function to avoid collision with globals.
@szepeviktor That may not be necessary. For content scripts in extensions, the JS namespaces are isolated. Only the DOM tree is shared (with some writing methods disabled). I think userscripts are implemented as content scripts in Chromium.
OK-OK, I use JSLint.
Added handling of links in the search list.
Also, now the script never clears an interval, keeps looking for changes.
Published on gist:
https://gist.github.com/vonagam/51664e8a43b9f44a7e14be07a7c4d697
how does that script work? i don't see any button on store's extension page.
Same issue as @perfect7gentleman mentioned with ungoogled-chromium_55.0.2883.87-1_windows_x64 and the two versions of user scripts.
@perfect7gentleman @mapx Use the gist @vonagam linked.
@WIZARDISHUNGRY Thank you, but as I mentioned above, these two versions of user scripts, including what @vonagam linked, do not work with ungoogled-chromium_55.0.2883.87-1_windows_x64 at present.
I took your advice and tried again to say so.
@mapx how did you install the user script (by drag-and-dropping file into chrome://extensions/ or through some extension)? do you see any errors in javascript console on webstore page?
@vonagam Thanks!
It's installed through Tampermonkey when I clicked the Raw button at your gist page.
Javascript console on the webstore page (https://chrome.google.com/webstore/category/extensions) only shows the following irrelevant error:
GET https://ssl.google-analytics.com/ga.js net::ERR_BLOCKED_BY_CLIENT
On the extensions page, all extensions are marked as "Not from Chrome Web Store."
@mapx Can you try to install it by downloading user script as a file and drag-dropping it into chrome://extensions/?
I disabled Tampermonkey, did what you told me, and saw the same things on webstore and extensions pages.
Looks like the link is dead. ):
The current chrome version from the user agent string:
/Chrome\/([0-9.]+)/.exec(navigator.userAgent)[1]
Hopefully with that we can make get something working that doesn't need updating so often. Here's some stuff:
Save the following line of code as a bookmark and click it from any extension details page on chrome web store to download its crx. I prefer this solution to adding a search engine as suggested in the FAQ.
(SOURCE without the url formatting)
javascript:(function()%7Bwindow.location.href%3D%22https%3A%2F%2Fclients2.google.com%2Fservice%2Fupdate2%2Fcrx%3Fresponse%3Dredirect%26acceptformat%3Dcrx2%2Ccrx3%26prodversion%3D%22%2B%2FChrome%5C%2F(%5B0-9.%5D%2B)%2F.exec(navigator.userAgent)%5B1%5D%2B%22%26x%3Did%253D%22%2B%2F%5Ehttps%3A%5C%2F%5C%2Fchrome.google.com%5C%2Fwebstore%5C%2Fdetail%5C%2F.%2B%5C%2F(%5Ba-z%5D%2B)%2F.exec(window.location.href)%5B1%5D%2B%22%2526installsource%253Dondemand%2526uc%22%7D)()
HERE is an update of the script by @vonagam. It wasn't working for search results page. Also added the newer url, updated button style, and it gets chrome version from user agent string (and I just had to remove the line spacing to read it, sorry!).
The issue seemed to be google adjusted the layout of the html slightly. This script may be quite sensitive to that.
Thanks, updated gist of the script with same changes.
(You have typo in gist in url template: instead of [EXTENSION_ID] there is [EXTENSIONID])
The current chrome version from the user agent string:
(function()%7Bwindow.location.href%3D%22https%3A%2F%2Fclients2.google.com%2Fservice%2Fupdate2%2Fcrx%3Fresponse%3Dredirect%26acceptformat%3Dcrx2%2Ccrx3%26prodversion%3D%22%2B%2FChrome%5C%2F(%5B0-9.%5D%2B)%2F.exec(navigator.userAgent)%5B1%5D%2B%22%26x%3Did%253D%22%2B%2F%5Ehttps%3A%5C%2F%5C%2Fchrome.google.com%5C%2Fwebstore%5C%2Fdetail%5C%2F.%2B%5C%2F(%5Ba-z%5D%2B)%2F.exec(window.location.href)%5B1%5D%2B%22%2526installsource%253Dondemand%2526uc%22%7D)())
Bookmarklet does not seem to work for me. When I press it, nothing happens:

ungoogled chromium windows x64 v67.0.3396.87
@miklide You're right. I had an extra bracket at the end. Oops! Remove the last bracket or copy this:
javascript:(function()%7Bwindow.location.href%3D%22https%3A%2F%2Fclients2.google.com%2Fservice%2Fupdate2%2Fcrx%3Fresponse%3Dredirect%26acceptformat%3Dcrx2%2Ccrx3%26prodversion%3D%22%2B%2FChrome%5C%2F(%5B0-9.%5D%2B)%2F.exec(navigator.userAgent)%5B1%5D%2B%22%26x%3Did%253D%22%2B%2F%5Ehttps%3A%5C%2F%5C%2Fchrome.google.com%5C%2Fwebstore%5C%2Fdetail%5C%2F.%2B%5C%2F(%5Ba-z%5D%2B)%2F.exec(window.location.href)%5B1%5D%2B%22%2526installsource%253Dondemand%2526uc%22%7D)()
Most helpful comment
@miklide You're right. I had an extra bracket at the end. Oops! Remove the last bracket or copy this: