Welcome to my personal blog. If you're looking for my academic profile page, click the UCD in the upper right corner. Or maybe you're looking for my open source development blog?

sassc-rails memo

17 Feb 2019

Initializing a rails project, the default sass-rails gem gives a warning that it’s reached end of life, so it’s a good idea to swap in a replacement:

gem 'sassc-rails', '~> 2.1.0'

This doesn’t run on its own, and the error doesn’t really make it obvious, but you’ll also need

gem 'sass', '~> 3.7.3'

Plans for 2019

14 Jan 2019

I made my resolutions on this tweet but it helps to repeat.

  1. Speak more Spanish/Chinese/Japanese/Vietnamese
  2. Make an Android app
  3. Do some NLP-related ML
  4. Get the resting heart rate back down to 60

How’s it going so far?

  1. I’m using Busuu/Memrise/Conjugato/Duolingo/Lingodeer as my daily lesson. I can comfortably put in 2 hours if I optimize my break/commute time to doing these. It’s just a matter of doing them routinely.
  2. For January I want to build a simple image annotator, first of all. February will probably be an extension to allow for audio annotation. By March, I’d like to be able to sync the data to a backend server. Today is a holiday Monday, so I’m downloading Android Studio.
  3. For work, there’s language detection and sentiment analysis. As a personal goal, I haven’t thought about this too much. I guess I would like to cluster and visualize my notes in a natural way. Topic modeling seems to be the right keyword. Recently I’ve been looking at WordNets as well. Also I think I might just be more interested in text retrieval and rudimentary search.
  4. I ruptured a tendon and I’m on crutches for at least a month, so this is going perfectly. No, really, I’m getting such a great workout just commuting.

Firefox 54 and Looking Ahead

20 Jun 2017

Apparently, the Firefox 54 release a week ago was a bigger deal than I had originally thought.

As I was toiling away on my WebExtensions addon, I took note that Firefox 54 was going to enable the sidebar API, so you can pull up a sidebar drawer from your extension. I mentioned last month in my rough plans of porting Perakun to WebExtensions that it’d be nice to have a drawer that holds the list of word lookups just like in the legacy Firefox addon, and theoretically, it is now possible to do that in WebExtensions. (By the way, I forked another Rikai-kun-based addon that looked further developed, called rikaigu, and the addon works in Firefox and Chrome: check out rikaigu.we.) But I also learned in that time that, while there was discussion of adding it to Chrome as well, in early 2016, they decided not to proceed with sidebar API. So looks like if the addon’s going to be cross-browser compatible, I’m going to have to ditch the idea of a sidebar.

But there’s a bigger reason to be excited about Firefox 54 and that’s the multiprocess architecture revamp! I’m looking forward to web development without the browser choking out because I toggled the DOM inspector while a monster of a page is loading…

Except multiprocess functionality is disabled if you make use of any addons that are “multiprocess incompatible”, i.e. utilizing deprecated APIs.

Perapera Japanese being deprecated is not so bad because our Rikaigu port is essentially a drop-in replacement. Woo!

TiddlyFox is a hard one to lose. I’m pretty dependent on Tiddlywiki for jotting notes, and without this, the Tiddlywiki can’t overwrite itself when you press save but prompts you to save the file to disk. You can just point it to the same file and it will function the same way as a workaround, though.

Also looming at the end of this year is Firefox 57 when some more addons are going to stop working because they’re not WebExtensions. I’m really worried about Tree Style Tab possibly going away in November.

So I’m excited about the changes that have been brought on at the expense of breaking API support for all these addons. I feel like there’s some vocal opposition from addon developers who are getting shafted for something they don’t necessarily agree with from an engineering perspective, and I really do feel for them. While I can see that there’s nothing that can be done if the WebExtensions API is incomplete and you just can’t rewrite what you have if it’s not supported, I believe it’s going to be continually improving, and I really hope that some addons end up living into next year.

I’m also looking to join in the fray with Rikaigu, but that progress report will have to wait until another blog post.

Figuring out Rails API calls via WebExtensions XHR

16 May 2017

One of the questions I had in my last post was about how to manage sessions and login to a Rails app from a WebExtensions client. For example, let’s say your Rails app provides a Profiles resource that you handle in Rails with a route GET /profiles/:id. Let’s say you provide an API endpoint as well, at GET /api/v1/profiles/:id. From your WebExtensions script, you would issue the XHR like so:

var url = "http://localhost:4000/api/v1/profiles/2";
var req = new XMLHttpRequest();
req.open('GET', url, false);

Most likely, the endpoint will be protected by some sort of authentication check. The nifty thing is if you happen to have cookies from, say, having logged in through the web interface of the app, those are automatically sent when you send the XHR, and you can potentially be authenticated that way. But more typically for an API, you might be using Rails token authentication. Rails provides authenticate_or_request_with_http_token, which will look at the Authorization request header for a token that will be used instead of cookies. So you’ll need to do two things:

  1. get the token, and
  2. set it in the request header.

Conventionally, you might see the token made available by the app through some sort of user settings page where the user can copy and paste it into the extension to use for authorization. There might be a more automated way to do this, though.

The second part can be achieved by adding the following to the above snippet:

  var url = "http://localhost:4000/api/v1/profiles/2";
  var req = new XMLHttpRequest();
  req.open('GET', url, false);
+ req.setRequestHeader('AUTHORIZATION', 'Token token=your_token_here');

With this, Rails should be able to pick out the token from the request header and use that to authenticate the request and get your JSON response.

What’s next?

So while you now theoretically have full access to the API, there’s another thing to consider called Cross Origin Resource Sharing (CORS). Basically, it’s a way for a server to specify access control to resources from cross-site scripts, which is what our browser extension is. For example, we don’t want a malicious script to be able to send DELETE requests or otherwise mess with your data. CORS is a way to permit or deny requests, based on where the originating script is coming from.

This may not be an issue because a malicious script would somehow have to get access to the authentication token. But this may mean extra server-side setup depending on how this protocol is enforced across browsers. I’ll investigate the details in the next few days.

Rough plan for Perakun port

13 May 2017

What is Perakun

Perakun is a Firefox extension that helps Japanese learners by providing dictionary lookups for mouseover text. A great feature is its ability to save lookups to a word list. This gif gives a good summary:

State of Perakun

As I mentioned previously, Chrome has taken the lion’s share of the browser market, and Firefox has plans to move to an addon subsystem based on WebExtensions, which will be compatible with Chrome.

Perakun exists as a legacy addon in Firefox for Japanese and Chinese, but only the Chinese WebExtensions addon exists in Chrome, with only a subset of the functionality.

In theory, an addon written in WebExtensions should plug and play in any supporting browser, but there is enough inconsistency in API support where the code will need some updating.

Rough plan of action

  1. Update the Chinese Perakun WebExtensions addon to be fully cross-browser compatible.
  2. Update the addon to support Japanese dictionary.
  3. Restore word list functionality missing from legacy addon.
  4. Add functionality to post to HiNative server for richer learning experience.


Currently, I’ve gotten started fixing up the WebExtensions addon, which you can find on github. I’ve made some simple replacements to some deprecated calls, but it still isn’t functional in Firefox.

Things I need to figure out still, are:

  1. document.caretRangeFromPoint has no equivalent function in Firefox but is being used in Chrome to get the mouseover text. It may be the case that the old way of doing it is still compatible and I will have to port it back in.
  2. Possibility of local SQLite database access? The old addon used Components to get read/write access to a SQLite dictionary packaged with the addon, but I’m not sure it’s possible with WebExtensions.
  3. Login/Session management? I’m pretty sure it’s possible to get user/password and login to HiNative with XHR and proper addon permissions.

← Older

Newer →

Alex Tsui

Alex Tsui

Computer science grad student at UC Davis, writes C++, enjoys learning languages, and occasionally video games.