How can I replace Google Chrome's low resolution notification icon?

Google Chrome was recently upgraded to version 35.0.1916.114 on my Ubuntu 14.04 installation.

Since then the notification icon has begun to show up on the system tray. However it seems it's using a low resolution icon - it looks distorted:

enter image description here

How can I fix/replace it?


Edit: see below for update on replacing notification icon

If you're chrome binaries are installed in the typical location, you'll find them in /opt/google/chrome. In that folder you should find the file chrome_100_percent.pak which contains the notification icon. Here's the steps I used to extract it, using information from this stack overflow question:

  1. Checkout the code to the grit-i18n project with

    svn checkout http://grit-i18n.googlecode.com/svn/trunk/ grit-i18n-read-only

  2. This will give you a folder in your CWD called grit-i18n-read-only. CD into this folder

    cd grit-i18n-read-only

  3. Copy the data_pack python module to this folder

    cp grit/format/data_pack.py .

  4. Edit data_pack.py in your preferred editor. After the initial imports, add the following line:

    sys.path.append(os.getcwd())

  5. Towards the end of the file in the main function, remove the line

    print '%s: %s' % (resource_id, text)

    (the Stack Overflow answer states this occurs at line 160, in my experience the current version has it at line 201)

  6. In its place, insert the following lines indented appropriately (3 times):

    file = open(str(resource_id), "wb")

    file.write(text)

  7. Run the data_pack.py utility on the chrome pak file (I copied it to the grit-i18n-read-only folder first):

    ./data_pack.py ../chrome_100_percent.pak

This will result in a lot of new files in the current directory, all named as numbers with no extension. Your file browser (e.g. nautilus) should be able to determine the file types and show image thumbnails. I found the notification icons named as 6866 & 6867.


Edit

While there are some simpler answers below, I managed to hack together some code to re-package the resources which you could attempt after editing the icons. This would produce a new .pak file, which I haven't attempted to use myself, so I can't say for certain this would successfully result in new notification icons.

In the main function in data_pack.py, I commented out all the code in the else block and added the following lines:

# Read in the modified icon resource files
file = open('6864', 'r')
icon1 = file.read()
file.close()
file = open('6865', 'r')
icon2 = file.read()
file.close()
file = open('6866', 'r')
icon3 = file.read()
file.close()
file = open('6867', 'r')
icon4 = file.read()
file.close()

# Write resource pak of only notification icons
iconData = {6864: icon1, 6865: icon2, 6866: icon3, 6867: icon4}
WriteDataPack(iconData, 'tmp.pak', BINARY)

# Create copy of original pak without notification icons
dataPack = ReadDataPack('chrome_100_percent.pak')
# List of icon resources to remove
toRemove = set([6864,6865,6866,6867])
whiteList = set(dataPack.resources.keys()).difference(toRemove)
whiteListFile = open('whitelist.txt', 'w')
for i in whiteList:
  whiteListFile.write(str(i)+'\n')
whiteListFile.close()
newDataPack = RePack('tmp2.pak', ['chrome_100_percent.pak'], 'whitelist.txt')

# Merge the two paks together
combinedPack = RePack('chrome_100_percent_new.pak', ['tmp2.pak', 'tmp.pak'], None)

Then, just run ./data_pack.py. This assumes chrome_100_percent.pak is in the current directory, and should give you a new chrome_100_percent_new.pak file which you could attempt copying over /opt/google/chrome/chrome_100_percent.pak.

I believe some additional icons in the resource pak related to the notification icon have been identified; editing the above to include those should be pretty straightforward.


Final Edit

Now that I'm back home and had the chance to work on this some more, I managed to successfully replace chrome's notification icon. As @Glutanimate noted, you're stuck with 16x16 resolution, so I'm not sure how much improvement you can actually achieve, but I suppose that's subjective.

I simply opened the aforementioned icons (6864 - 6867) in GIMP, which detected them as Grayscale PNGs. I pasted a new icon into the same file in GIMP, thus attempting to keep the same image properties (e.g. grayscale). I then exported these as PNGs, unchecking ALL of the options that GIMP offers but maintaining a compression level of 9. The resulting files had .png extensions, so I removed those and replaced the originals. I then re-ran data_pack.py, having already made the modifications detailed above.

I kept a backup copy of the original pak with mv /opt/google/chrome/chrome_100_percent.pak /opt/google/chrome/chrome_100_percent.bak and moved my modified .pak file in its place. I would make sure chrome is closed when doing this, and double-check that there are no chrome processes running, and I believe chrome has a new setting to allow background processes even when the browser is closed by default now.

Lo and behold, my notification icons in Unity reflect my changes.

Finally-Final Edit: OK, I lied - I attempted a 32x32 PNG and it seems to have worked just fine. So, there you go. Here some result screenshots.

  • Original Icon: You'll probably recognize the default 'no unread notifications' icon in my panel here between my dropbox and weather icons:

Original Icon

  • New Icon: My 32x32px modified version in the same location:

New Icon

(Source: Batch icons from Adam Whitcroft)


Edit:

Looks like the issue was with node-chrome-pak. rocketman10404's modified data_pack.py is working fine, even with 32px icons:

enter image description here

Please use his instructions instead.


Original answer:

@rocketman10404's excellent answer lead me to node-chrome-pak, a node.js script that can pack, unpack and replace specific resources in Chrome/ium's .pak files.

Though I've managed to replace the notification icons in chrome_100_percent.pak with this tool, I have to report that I wasn't able to make the changes visible. Still I think it's worth effort to outline the steps I took to get this point. Hopefully someone else will take this up and find a way to actually make it work.

Installing node.js

node-chrome-pak will need node.js to run. You can install the latest version by adding Chris Lea's nodejs PPA:

sudo add-apt-repository ppa:chris-lea/node.js
sudo apt-get update
sudo apt-get install nodejs

Downloading the script and unpacking Chrome's resources

Download the script:

git clone https://bitbucket.org/hikipro/node-chrome-pak.git
cd node-chrome-pak

Copy your local chrome_100_percent.pak over:

cp /opt/google/chrome/chrome_100_percent.pak ./chrome_100_percent.pak

Unpack the .pak file:

node ./main.js unpack chrome_100_percent.pak

Identifying and modifying the notification icons

The last action will have created a new folder called ./extracted. In it you will find all resources contained in the pak file. They are named after their resource ID. You will want to preserve this name as it is important for repackaging the files.

The difficult part now lies in identifying the correct icons. If I am not completely mistaken the following files should be the ones used in the systray:

6864.png
6865.png
6866.png
6867.png

Having identified the icons you were looking for, you can proceed to modify and replace them. If you want you can use the icons I created for this purpose:

      

      

The source files and exported .pngs in different resolutions are hosted over at GitHub.

Here comes the first limitation I found: If you replace the icons with an image in any resolution higher than the original Google Chrome will get corrupted and stop working properly. For this particular project you will have to stay with a 16x16 resolution. In effect this means that you would not be able to significantly improve on the current systray icons, even if you were to get this method working.

Of course there's the possibility that this limitation was introduced by the way node-chrome-pak was designed. It might be possible to replace the icons with larger ones if you create a custom python script based on @rocketman10404's answer.

Repackaging the resources and replacing the existing ones

After modifying/replacing the existing icons you will have to create an updated pak file...

node ./main.js pack ./extracted ./chrome_100_percent_modified.pak

...and use it to replace the existing one:

sudo cp ./chrome_100_percent_modified.pak /opt/google/chrome/chrome_100_percent.pak

The crux of this method

In my attempts I have not been able to get Chrome to show the updated icons. Even if I made sure that all icons were replaced correctly and actually present in the modified pak file (by unpacking it again) I still wasn't able to replace the actual icon in the systray.

Unfortunately I have no idea why this is.