PiSquared Blog
Blog about geeky stuff, computers, physics and life.
Auto adapting signal to day-night scheme
Tags: English, hacksCreated on Mon, 02 Apr 2018
So I wanted to automatically change the day/night theme of my brand new Signal desktop app. The way that it is manually done is through the File -> Preferences...
menu. Now that's not convinient for programatic person like me. Let's investigate!
.config
folder
My first stab is looking into the mostly standard ~/.config
folder in Linux for Signal if one actually exists. It turns out it does. Let's see. It even has a ~/.config/Signal/config.json
file. Unfortunately, that file doesn't contain the settings for the theme, just window positions.
grep -r
ing in the folder for any of android
or theme
just returns the logfile that Signal is writing to.
...
./logs/log.log.1:{..."theme-setting changed to android-dark",...}
...
No luck.
Another stab is at /opt/Signal
directory. Again - no luck. And the app is a binary ELF executable
$ file signal-desktop
signal-desktop: ELF 64-bit LSB executable,...
strace
-ing
My next attempt is to attach to attach to the Signal process via strace
. Find the process by ps aux|grep signal
, attach by strace -p <pid>
and try to change the . Boy, this does a lot of stuff! Let's filter by writing:
strace -e write -p 12345
Still, too much but I saw something hapenning amid the writing to 40
and 71
file descriptors (fd).
```bash
...
write(40, "!", 1) = 1 write(71, "\0", 1) = 1 write(40, "!", 1) = 1 write(1, "{\"name\":\"log\",\"hostname\":\"pi2-ho"..., 147) = 147 write(12, "\1\0\0\0\0\0\0\0", 8) = 8 write(71, "\0", 1) = 1 write(40, "!", 1) = 1
...
```
All right, the 1
fd is the log that is being written that I already saw. How about that 12 fd? Let's explore within the proc
fs:
```bash $ cd /proc/1234/fd $ ls -la
...
lrwx------ 1 pi2 pi2 64 Mar 29 23:23 12 -> anon_inode:[eventfd]
...
```
Oh boy, some wierd anonymous inode. So we are definately not dealing with a good old filesystem file but rather some on the fly created fd. Let's explore a bit more...
Signal is an Electron app
Taking a look at the github repo of the project. Searching for dark
and theme
reveals css, sass files. Okay
Looking at the menus there is View -> Toggle Developer Tools
and BAM - a good old Chrome developer tools console pops up! Inspecting the elements, it's pretty clear what is happening:
```html
``` Brilliant, the change of theme just changes the class on the `body` element. Let's see if we have jquery or I have to go to the dark ages of javascript's `findElementByTagName`: ```javascript > $ < function ( selector, context ) { // The jQuery object is actually just the init constructor 'enhanced' ... ``` Good, we have. Now I "just" have to find a way to connect to chrome console via a good old terminal in some way... ## Chrome remote debugging Searching the Internets, I find a [post](https://blog.chromium.org/2011/05/remote-debugging-with-chrome-developer.html) in Chromium blog from way back in 2011 that I can run Chrome with `--remote-debugging-port` flag which enables some sort of a remote console. Would the electron app do the same? ```bash signal-desktop --remote-debugging-port=9222 ``` Indeed it does. This console however is not just a simple tcp connection to the javascript console. Running `echo "alert('echo'); | netcat localhost 9222` does nothing. More reading to go... Turns out, Chrome DevTools has its [own protocol](https://chromedevtools.github.io/devtools-protocol/) that among other things exposes websockets. Let's see what clients exist for that [Quite a lot](https://github.com/ChromeDevTools/awesome-chrome-devtools). Any pythonic ones? [pychrome](https://github.com/fate0/pychrome) seems simple enough. Let's be modern, do python3: ```bash pip3 install pychrome ``` And I will use my favourite repl, `ipython` and follow the Getting started tutorial: ```python import pychrome browser = pychrome.Browser(url="http://127.0.0.1:9222") ``` Awesome, I have a connection. The tutorial goes into opening a tab. I don't want that, I assume I should alread have a tab. Exploring `browser` object (via my favourite [ipython repl](http://ipython.org/)): ```python In [3]: dir(browser) Out[3]: [... _private_stuff 'activate_tab', 'close_tab', 'dev_url', 'list_tab', 'new_tab', 'version'] In [4]: browser.list_tab() Out[4]: [