Porting Firefox extensions to Internet Explorer – Part 4

Tractor
In my previous articles, I described how to set up the compiler, build a basic BHO, work with regular expressions and fetch pages using XMLHttpRequest’s. I’ve now combined those components into the first working version of PeteSearch in IE. The source code is available through Sourceforge, or you can download it as a zip archive.

This version detects search pages from Google, Live, Ask, Technorati and Exalead, pulls out the search result links, fetches the contents of those pages to ensure they’re still active and relevant, and updates the search page to show each link’s status. I’ll be covering the remaining tasks in later articles, which include implementing hot-keys, adding a split-screen view to IE and writing an installer.

More posts on porting Firefox add-ons to IE

Multi-threaded DOM access in a BHO causing crashes

Threads
PeteSearch relies on Document Object Model (DOM) access to analyze and update HTML pages. This is built-in to Firefox’s Javascript, but in IE you have to use the IHTMLDocument(2/3) COM object. I’ll give some code examples in a later article, but first I want to cover a serious problem I ran into, and the solution I found.   

I was seeing a lot of crashes once I started analyzing search results, and fetching pages. I discovered that the crashes all seemed to happen when multiple threads were all accessing the same document. I was passing a pointer to the IHTMLDocument3 object to the XMLHttpRequest worker threads, and after a little thought, it made sense that this object wasn’t thread-safe, and so I’d need to synchronize my access to it somehow.

This part really puzzled me. I couldn’t figure out a good way to call back my BHO on the main thread, because the BHO doesn’t control the message loop for the main thread, that’s all in IE. And since IE could be using the same object, and I don’t control that code, I couldn’t implement my own manual locking.

Luckily, I came across a life-saving post from Tony Schreiner. He explains that COM objects in IE are not thread-safe by default, but that you can get a wrapped version that adds thread-safe locking by calling CoMarshalInterface(). This gives you a version of the object that you can use on a different thread, without worrying about crashes caused by other threads accessing it at the same time.

It was only a few lines of code, and implementing it removed all the bugs I was hitting. Thanks Tony!

More posts on porting Firefox add-ons to IE

XMLHttpRequest in C++ using WinHttp

Glowflow

My decision to use WinInet to implement my XMLHttpRequest class turned out to be a mistake! I went back to the drawing-board, and reimplemented the class using WinHttp, the more modern alternative from Microsoft. Here’s the code, the CPeteHttpRequest class that implements the classic XMLHttpRequest interface together with an app to test its use. It’s available for reuse with no restrictions.

Here’s the differences between this new version and the old WinInet-based one:

  • It no longer crashes when under heavy multi-thread use
  • The interface is now entirely in wide character strings
  • WinHttp is only available on Windows 2000, XP and Vista, so use the WinInet code for legacy support

More posts on porting Firefox add-ons to IE

WinInet Thread Crashes

Crash
In my previous post on XMLHttpRequest, I explained why I chose to implement my http request class using the legacy WinInet library, rather than one of the more modern alternatives. Last week, I was able to get the DOM parsing part of PeteSearch running, and so I was able to start stress-testing my class.

I was getting a lot of crashes, and after finding and eliminating a couple of my own bugs, and paring down the code as much as I could I was left with some minimal code that still crashed, often in the wininet dll!

After digging around some more on the MSDN site, and reading between the lines, I realized this seemed to be a known problem, and there probably wasn’t much I could do about it. They recommend using WinHttp for "server applications", and there seem to be a lot of hard-coded limits in WinInet, such as how many concurrent accesses to the same server you can have.

As far as I could tell, the crashes all occurred when I had a lot of requests being processed on different threads at the same time.

I replaced WinInet in my XMLHttpRequest implementation with WinHttp, and the crashes went away, which is strong evidence that it wasn’t my code doing something whacky. I’ll be posting the updated code in my next article.

More posts on porting Firefox add-ons to IE

Firefox Shortcuts

Fire

More Search Tips…

Here’s some ways to speed up searching and browsing by using shortcuts for common tasks.

  • Press F7 to turn on Caret Browsing. You’ll now see a blinking cursor
    when you click on a page, which you can move around with the arrow
    keys. What’s really handy is that when you move the cursor to a link,
    you can open it by pressing Return, which allows you to move rapidly
    through web pages using only the keyboard. Control+Left/Right in Caret Browsing mode will move by whole words. It doesn’t always work well on pages with complex layouts.
  • Hold Command/Control when pressing Return after typing a word in the location bar and it will add www and .com to the start and end. For example, typing ibm and Command/Control+Return will take you to http://www.ibm.com. Shift+Return does the same, but adds .net, and Command/Control+Shift+Return adds .org.
  • If you select some text, you can instantly search for it on Google using the right-click menu.
  • Control/Command+L will let you type a URL into the location bar, without having to move the mouse and click on it.
  • Control/Command+K lets you type into the search box without mousing over to it.

Firefox Search Keywords

Keys
Firefox has a powerful feature that lets you search specialized sites from the location bar, called Search Keywords. Normally, when you type something in the location bar, and it isn’t recognized as an address, Firefox will open up a Google search page for the string you typed. The idea is you can type wiki optical flow and you’ll be directed to wikipedia’s internal search results for optical flow.

In theory, all you need to do to set up custom keywords for the sites you visit most often is navigate to the main page, right-click on the search box and choose Add a Keyword for this Search from the menu.

In practice, this GUI method doesn’t work on a lot of sites, since Firefox seems to have trouble with relative URLs in search forms. So doing this on wikipedia will send you to  http://wiki/Special:Search?search=optical+flow rather than the full address!

There’s some handy pre-packaged collections you can download, such as this one from Lifehacker, or this massive compendium, but if you’re comfortable building up URLs, I’ll show how you can create your own.

We start by doing a search on the site we want to add, and creating a bookmark of that page. In this case, we go to http://en.wikipedia.org and enter optical flow in the search box on the left, and press the Search button (not Go, since that’s the equrivalent of I Feel Lucky on Google). That takes us to this page:

http://en.wikipedia.org/wiki/Special:Search?search=optical+flow&fulltext=Search

Pressing Control+D, or choosing Bookmarks->Bookmark This Page from the main menu adds this to our bookmarks.

Now, bring up the Bookmark Organizer by picking Bookmarks->Organize Bookmarks... from the menu. Find the bookmark you just created in the list, select it, and press Control+I or click the Properties icon in the top bar.

We should now see a dialog box like this:
Bookmarkbox1

In the location text box, scroll until you see the words you entered as a search, separated by a plus sign:
Bookmarkbox2

This is the part we’ll want to replace with the terms after the keyword in the location bar, so delete just those words and any plus’s separating them, making sure not to delete past the words. We’ll delete up to the end of the URL, or to the next & sign, whichever comes first.

Once the specific terms have been removed, we can put in the placeholder for the terms we type after the keyword, %s
Bookmarkbox3

Finally, we chose a keyword to type for this search, in our case wiki, and click OK.
Bookmarkbox4

Now, we can test out the keyword by typing wiki gaussian blur in the location bar, and we should see a new page of search results.

This is a real time-saver if you set it up for reference sites you commonly search on, sometimes you can’t beat the command-line style for speed of access!

More Search Tips…