Yahoo! Search for Safari plugin
Category: Blog

Today I went in search of a basic plugin which switched the search provider for Safari 3 to use Yahoo! Search. I found a number of different SIMBL plugins, but all of them did a lot more than I wanted and/or were unstable. AcidSearch is unstable currently and also adds two menu items into the right click menu. This is annoying as I routinely right click on links to “open in new tab” and with it adding two options at the top it would always cause me to click on it instinctively instead of the option I really wanted. I also tried out Inquisitor 3 and while it was stable, it had a boatload more functionality than I needed or wanted (why go to Niagra falls when all you need is a single drop of water?). Not finding anything really to serve my rather specific desires, I decided to set out and learn SIMBL myself and write a plugin.

Being a newb so to speak in Objective-C it wasn’t an easy path to go down. Unfortunately Apple’s documentation leaves a lot to be desired, especially in regards to documenting what methods are inherited from parent classes. Thankfully I have a few OSX developer buddies who were able to come to my rescue a couple times. One really kewl tool I learned about in the process is called F-Script. It allows you to introspect applications as they are running and run scripts poking and prodding deep inside an application. This combined with class-dump provided me with the information I needed to be able to make my modifications.

Thankfully I knew a bit about method swizzling and how that works from a couple other previous pet projects I worked on. It’s still something I consider a black magic hack, but at least I was comfortable enough with the concept to know what to do. I’ve seen several ways of implementing method swizzling before, but I found the one inside ForgetMeNot and SIMBL’s documentation to be the simplest, so I used it instead of what I used previously.

The first thing I needed to do was figure out what created the URL that Safari used to load up the search results for a specific query. Digging around for a while using F-Script Anywhere, I found that was done by the URLWithSearchCriteria method of the GoogleSearchChannel class. I started off by writing a simple wrapper method which NSLog’d the input of the function as well as the output. After I learned what it did fully, I then wrote the following replacement method:

- (NSURL *)_jj_URLWithSearchCriteria: (NSString *)searchCriteria
{
NSURL *yurl = [NSURL URLWithString: [[NSString stringWithFormat:@"http://search.yahoo.com/search?p=%@", searchCriteria] stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding]];
NSURL *url = [self _safari_URLWithSearchCriteria: searchCriteria];

NSLog(@"Search Criteria: %@", searchCriteria);
NSLog(@"Google URL: %@", url);
NSLog(@"Yahoo URL: %@", yurl);

return yurl;
}

I then needed to find a way to replace the placeholder text inside the SearchField with “Yahoo!” instead of “Google“. This unfortunately took a lot longer than I had hoped as I had trouble finding how to get access to the SearchField since it’s obviously not an easily accessible global variable or anything like that. Thankfully I finally was able to trace the stack and find it was defined inside _toolbarController in the BrowserWindowController class. I had already figured out how to set the text using F-Script, so it was a simple matter of finding a method to swizzle inside BrowserWindowController which would allow me to latch in. Viewing the class dump for Safari, I found my target pretty quickly, _setUpSearchField looked like a perfect candidate. Unfortunately I had trouble grabbing ahold of the private instance variable, but this was one of the spots where a buddy of mine was able to provide a solution. By using object_getInstanceVariable I was able to access it and thus could go on with my changes. Here’s the final replacement method which changes the “Google” placeholder text to “Yahoo!”:

- (void)_jj_setUpSearchField
{
// Call the "parent" first so it does it's business
[self _safari_setUpSearchField];

id _toolbarControllerObj;
object_getInstanceVariable(self, [@"_toolbarController" UTF8String], &_toolbarControllerObj);

// Now change the placeholder string from "Google" to "Yahoo!"
[[[_toolbarControllerObj searchField] cell] setPlaceholderString:@"Yahoo!"];

NSLog(@"Search placeholder string changed to Yahoo! from Google");
}

There are a few other spots which I could replace “Google” with “Yahoo!” (like the error dialog which happens when you press enter without typing anything or the toolbar editor), but I decided those weren’t important right now. If you would like to see the source code to this plugin, please go here:

http://safari-yahoo-search.googlecode.com/svn//trunk/YahooSearchPlugin/

You can also download the installer here (which also includes the source code inside the disk image):

http://safari-yahoo-search.googlecode.com/files/YahooSearchPlugin.dmg

Please note that while I work for Yahoo!, this plugin is not endorsed or supported in any way by my employer. Use is at your own risk and I make no guarantees it won’t blow up your computer, “eat babies” (stealing a term a coworker uses when an app does something bad), or generally cause you any multitude of different problems. You have been warned!

I’ll try and write up a good tutorial based on what I learned today in the near future. Please feel free to leave a comment with any comments, feedback, or questions and I will do my best to respond.

Update: This has only been tested on Safari 3.0.4 using SIMBL 0.82 on OSX 10.4.11 (aka Tiger). I will do my best to test this on Leopard as soon as possible.

Update: Since DreamHost is having serious performance issues today (first time it has been really bad for me, despite what others have experienced with them), I decided to copy the source code and download location over to Google Code. The URLs above have been updated above accordingly, please use them going forward.

Tags: , , , ,

10 Responses to “Yahoo! Search for Safari plugin”

  1. Anime Girl says:

    This is fantastic. I was wondering how I could get Yahoo search in Safari and now I can.

    Cheers!

  2. Alex says:

    Tried to install on 10.4.11 under (using 3.0.4) and the installer had a red band on all disks. I ran the install both as
    a regular user and under sudo. Safari was closed during install attempts.

  3. Jeremy says:

    @Alex:

    This is caused by not having the latest version of SIMBL installed. I apologize for the lack of appropriate error message, but if you install it then you should be good to go.

  4. seven77 says:

    hi, just to add a question: am a complete newbie to this, but would love to see if you can actually integrate some specific search
    engines – not looking for yahoo, myself. The tow websites are World of Warcraft related and while firefox used to offer to option,
    looks like Safari doesn’t…

    Do not want to spam, but pls tell me if you could help me out. Email is gave is valid.

    thanks a lot!
    ale

  5. Jeremy says:

    Assuming you only wanted to replace Yahoo! with (pick a search engine), it would be very easy to do (like <5mins work most likely). If instead you wanted the ability to switch between engines, it would take a fair bit more work. I’ll look into it and then email you with info once I have time to figure it out.

  6. seven77 says:

    thanks a lot. This is just great! Would love to be able to do the multi search engine thingy that Firefox has…
    Anyaway would love to hear your views.

  7. jermal says:

    great plug-in,

    how can i easily change the search engine in the code? Which files do i need to change and with what program?

    Also a ‘ restore to google’ package would be very good.
    Thanks,
    Jeroen

  8. Jeremy says:

    @Jeroen

    It’s pretty obvious if you look in the code (less than a hundred lines of code in the whole plugin), but here’s a couple helpful pointers:

    1.) To change the search provider, you would change this line in “GoogleSearchChannel.m”:

    NSURL *yurl = [NSURL URLWithString: [[NSString stringWithFormat:@"http://search.yahoo.com/search?p=%@", searchCriteria] stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding]];

    There you can see the URL being used is:

    http://search.yahoo.com/search?p=%@

    %@ is being replaced with the search term used, so edit this URL as needed for whatever engine you are using.

    2.) To change the label inside the search box, you would edit this line in “BrowserWindowController.m”:

    [[[_toolbarControllerObj searchField] cell] setPlaceholderString:@”Yahoo!”];

    In that line you will see:

    “Yahoo!”

    You would change that string with whatever you wanted to show up in the search box when a user hasn’t typed anything.

    Hope this helps!

    -Jeremy

  9. Renu says:

    Hello,
    I am very new to the safari environment. I have a firefox extension. I want to build a similar one for safari. I need to know what development tools would i need. Also how to i go about installing this dmg. I have safari on my machine. Any kind of online material would also be a gr8 help.

    Thanks
    Renu

  10. lmn says:

    Hi there,
    Is it working with Safari 4 and Snow Leopard?
    Did you dig out the multi search engine, or a drop down context menu?

    Thanks for your work :)

Leave a Comment

Spam Protection by WP-SpamFree