<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Ramblings of a Geek - Jeremy Johnstone &#187; Safari Plugins</title>
	<atom:link href="http://www.jeremyjohnstone.com/tag/safari-plugins/feed" rel="self" type="application/rss+xml" />
	<link>http://www.jeremyjohnstone.com</link>
	<description>Ramblings of a Geek</description>
	<lastBuildDate>Sat, 04 Feb 2012 18:33:00 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Yahoo! Search for Safari plugin</title>
		<link>http://www.jeremyjohnstone.com/blog/2007-12-26-yahoo-search-for-safari-plugin.html</link>
		<comments>http://www.jeremyjohnstone.com/blog/2007-12-26-yahoo-search-for-safari-plugin.html#comments</comments>
		<pubDate>Thu, 27 Dec 2007 05:42:59 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Objective-C]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Safari]]></category>
		<category><![CDATA[Safari Plugins]]></category>
		<category><![CDATA[SIMBL]]></category>

		<guid isPermaLink="false">http://www.jeremyjohnstone.com/blog/?p=257</guid>
		<description><![CDATA[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 [...]]]></description>
			<content:encoded><![CDATA[<p>Today I went in search of a basic plugin which switched the search provider for Safari 3 to use <span id="lw_1198734657_0" class="yshortcuts">Yahoo! Search</span>. I found a number of different SIMBL plugins, but all of them did a lot more than I wanted and/or were unstable. <a href="http://www.pozytron.com/">AcidSearch</a> 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 &#8220;open in new tab&#8221; 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 <a href="http://www.inquisitorx.com/safari/">Inquisitor 3</a> 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.</p>
<p>Being a newb so to speak in Objective-C it wasn&#8217;t an easy path to go down. Unfortunately Apple&#8217;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 <a href="http://www.fscript.org">F-Script</a>. It allows you to introspect applications as they are running and run scripts poking and prodding deep inside an application. This combined with <a href="http://www.codethecode.com/projects/class-dump/">class-dump</a> provided me with the information I needed to be able to make my modifications.</p>
<p>Thankfully I knew a bit about <a href="http://search.yahoo.com/search?p=method%20swizzling">method swizzling</a> and how that works from a couple other previous pet projects I worked on. It&#8217;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&#8217;ve seen several ways of implementing method swizzling before, but I found the one inside <a href="http://kisonecat.com/software/forget-me-not/">ForgetMeNot</a> and <a href="http://culater.net/wiki/moin.cgi/CocoaReverseEngineering">SIMBL&#8217;s documentation</a> to be the simplest, so I used it instead of what I used previously.</p>
<p>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 <a href="http://www.fscript.org">F-Script Anywhere</a>, I found that was done by the <strong>URLWithSearchCriteria</strong> method of the <strong>GoogleSearchChannel</strong> class. I started off by writing a simple wrapper method which NSLog&#8217;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:</p>
<pre class="brush: c">
- (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;
}
</pre>
<p>I then needed to find a way to replace the placeholder text inside the <strong>SearchField</strong> with &#8220;Yahoo!&#8221; instead of &#8220;<span id="lw_1198734657_1" class="yshortcuts">Google</span>&#8220;. This unfortunately took a lot longer than I had hoped as I had trouble finding how to get access to the SearchField since it&#8217;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 <strong>_toolbarController</strong> in the <strong>BrowserWindowController</strong> 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, <strong>_setUpSearchField</strong> 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 <strong>object_getInstanceVariable</strong> I was able to access it and thus could go on with my changes. Here&#8217;s the final replacement method which changes the &#8220;Google&#8221; placeholder text to &#8220;Yahoo!&#8221;:</p>
<pre class="brush: c">
- (void)_jj_setUpSearchField
{
// Call the "parent" first so it does it's business
[self _safari_setUpSearchField];

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

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

NSLog(@"Search placeholder string changed to Yahoo! from Google");
}
</pre>
<p>There are a few other spots which I could replace &#8220;Google&#8221; with &#8220;Yahoo!&#8221; (like the error dialog which happens when you press enter without typing anything or the toolbar editor), but I decided those weren&#8217;t important right now. If you would like to see the source code to this plugin, please go here:</p>
<p><a href="http://safari-yahoo-search.googlecode.com/svn/trunk/YahooSearchPlugin">http://safari-yahoo-search.googlecode.com/svn//trunk/YahooSearchPlugin/</a></p>
<p>You can also download the installer here (which also includes the source code inside the disk image):</p>
<p><a href="http://safari-yahoo-search.googlecode.com/files/YahooSearchPlugin.dmg">http://safari-yahoo-search.googlecode.com/files/YahooSearchPlugin.dmg</a></p>
<p>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&#8217;t blow up your computer, &#8220;eat babies&#8221; (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!</p>
<p>I&#8217;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.</p>
<p><strong>Update:</strong> 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.</p>
<p><strong>Update:</strong> Since <a href="http://www.dreamhost.com">DreamHost</a> 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 <a href="http://code.google.com/p/safari-yahoo-search/">Google Code</a>. The URLs above have been updated above accordingly, please use them going forward.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jeremyjohnstone.com/blog/2007-12-26-yahoo-search-for-safari-plugin.html/feed</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
	</channel>
</rss>

