├── .gitignore
├── Package
├── Safari Omnibar.pmdoc
│ ├── 01simbl-contents.xml
│ ├── 01simbl.xml
│ ├── 02safariomnibar-contents.xml
│ ├── 02safariomnibar.xml
│ └── index.xml
└── postflight
├── README.md
├── SafariOmnibar.xcodeproj
└── project.pbxproj
└── SafariOmnibar
├── JRSwizzle.h
├── JRSwizzle.m
├── SafariOmnibar-Info.plist
├── SafariOmnibar-Prefix.pch
├── SafariOmnibar.h
├── SafariOmnibar.m
├── SearchProviders.plist
├── SearchProvidersEditor.xib
├── SearchProvidersEditorWindowController.h
├── SearchProvidersEditorWindowController.m
├── SparkleHelper.h
├── SparkleHelper.m
└── en.lproj
└── InfoPlist.strings
/.gitignore:
--------------------------------------------------------------------------------
1 | *.xcworkspace
2 | xcuserdata/
3 | .DS_Store
4 | Sparkle.framework/
5 |
--------------------------------------------------------------------------------
/Package/Safari Omnibar.pmdoc/01simbl-contents.xml:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Package/Safari Omnibar.pmdoc/01simbl.xml:
--------------------------------------------------------------------------------
1 | net.culater.SIMBL.pkg14/Library/ScriptingAdditions/SIMBL.osax/Library/ScriptingAdditionsallowRevertlocationTypeinstallToscripts.postinstall.pathscripts.postinstall.isRelativeTypeinstallFrom.isRelativeTypeversionparentidentifierrequireAuthorizationinstallFrom.pathextraFilespostInstallpostflight/CVS$/\.svn$/\.cvsignore$/\.cvspass$/\.DS_Store$
--------------------------------------------------------------------------------
/Package/Safari Omnibar.pmdoc/02safariomnibar-contents.xml:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Package/Safari Omnibar.pmdoc/02safariomnibar.xml:
--------------------------------------------------------------------------------
1 | net.rhapsodyk.SafariOmnibar.pkg1.6/Users/rs/Library/Application Support/SIMBL/Plugins/SafariOmnibar.bundle/Library/Application Support/SIMBL/Plugins/SafariOmnibar.bundleinstallTo.pathinstallTopostInstallinstallFrom.pathidentifierparentrequireAuthorizationversionincludeRootextraFiles02safariomnibar-contents.xml/CVS$/\.svn$/\.cvsignore$/\.cvspass$/\.DS_Store$
--------------------------------------------------------------------------------
/Package/Safari Omnibar.pmdoc/index.xml:
--------------------------------------------------------------------------------
1 | Safari Omnibar/Users/rs/Desktop/Safari Omnibar-1.5.pkgnet.rhapsodykFailureThis version of SIMBL only works with Mac OS X 10.5.x and newer.- 01simbl.xml
- 02safariomnibar.xml
descriptionproperties.titleproperties.anywhereDomainpostinstallActions.actionsproperties.customizeOptionproperties.systemDomainextraFiles
--------------------------------------------------------------------------------
/Package/postflight:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # Copyright 2003-2009, Mike Solomon
3 | # SIMBL is released under the GNU General Public License v2.
4 | # http://www.opensource.org/licenses/gpl-2.0.php
5 |
6 | PACKAGE_PATH="$1"
7 | INSTALL_PATH="$2"
8 | INSTALL_VOLUME="$3"
9 | SYSTEM_ROOT="$4"
10 |
11 | RESOURCES="${PACKAGE_PATH}/Contents/Resources"
12 |
13 | # FIXME(mike) maybe we should copy this out of the install package instead?
14 | LAUNCHD_PLIST="/Library/ScriptingAdditions/SIMBL.osax/Contents/Resources/SIMBL Agent.app/Contents/Resources/net.culater.SIMBL.Agent.plist"
15 | OSAX_PLIST="/Library/ScriptingAdditions/SIMBL.osax/Contents/Info.plist"
16 |
17 | # remove old InputManager if it exists, otherwise these
18 | # two will contend when applications run under 32-bit mode
19 | SIMBL_INPUTMANAGER="/Library/InputManagers/SIMBL"
20 | if [ -d "$SIMBL_INPUTMANAGER" ]; then
21 | rm -rf "$SIMBL_INPUTMANAGER"
22 | fi
23 |
24 | LAUNCH_AGENTS_DIR="/Library/LaunchAgents"
25 | if [ ! -d "$LAUNCH_AGENTS_DIR" ]; then
26 | mkdir -p "$LAUNCH_AGENTS_DIR"
27 | chown root:wheel "$LAUNCH_AGENTS_DIR"
28 | fi
29 | # ensure agents are world-readable, but must be no more permissive
30 | # than 755, otherwise they are just skipped.
31 | chmod 755 "$LAUNCH_AGENTS_DIR"
32 |
33 | # ensure that this loads on restart
34 | cp "$LAUNCHD_PLIST" "$LAUNCH_AGENTS_DIR"
35 | if [ $? != 0 ]; then
36 | exit 1
37 | fi
38 |
39 | # create a system-wide location for plugins
40 | SIMBL_PLUGINS_DIR="/Library/Application Support/SIMBL/Plugins"
41 | if [ ! -d "$SIMBL_PLUGINS_DIR" ]; then
42 | mkdir -p "$SIMBL_PLUGINS_DIR"
43 | chown root:admin "$SIMBL_PLUGINS_DIR"
44 | fi
45 | # ensure plugins are world-readable
46 | chmod 775 "$SIMBL_PLUGINS_DIR"
47 |
48 | # ensure that ScriptingAdditions is world-readable
49 | SCRIPTING_ADDITIONS_DIR="/Library/ScriptingAdditions"
50 | chown root:admin "$SCRIPTING_ADDITIONS_DIR"
51 | chmod 775 "$SCRIPTING_ADDITIONS_DIR"
52 | if [ $? != 0 ]; then
53 | exit 1
54 | fi
55 |
56 | # stop any running agent by unloading it, in case we have made changes
57 | # to the agent that won't take effect until the application is restarted
58 | # NOTE: this runs *as* root, but $USER is the user that launched Installer.app
59 | # we don't want the agent running as root, nor do we want to force the user to
60 | # logout, so we try to kill any agents and then start the new version just for
61 | # this user.
62 | echo "Stop SIMBL Agent"
63 | echo su -l "$USER" /bin/bash -c "/bin/launchctl unload -F -S Aqua \"${LAUNCHD_PLIST}\""
64 | sudo -u "$USER" -- /bin/launchctl unload -F -S Aqua "${LAUNCHD_PLIST}"
65 |
66 |
67 | # This clears out any buggy instance we may have started with previous versions
68 | # of the package.
69 | echo "Stop root SIMBL Agent"
70 | /bin/launchctl unload -F -S Aqua "${LAUNCHD_PLIST}"
71 |
72 | # If there are other users, kill the current agents - launchd will restart
73 | # them with the newly installed code
74 | /usr/bin/killall "SIMBL Agent"
75 |
76 | echo "Start SIMBL Agent"
77 | echo su -l "$USER" /bin/bash -c "/bin/launchctl load -F -S Aqua \"${LAUNCHD_PLIST}\""
78 | sudo -u "$USER" -- /bin/launchctl load -F -S Aqua "${LAUNCHD_PLIST}"
79 | if [ $? != 0 ]; then
80 | exit 1
81 | fi
82 |
83 | # Under 10.6, the Leopard-compatible OSAX event causes a spurious entry in the
84 | # console. This is harmless and the warning is completely pointless, the event
85 | # won't ever be triggered on Snow Leopard. Equally pointless are the complaints
86 | # about this. If one reads the output of the Console, the least one can do is
87 | # be prepared to understand the statements made there.
88 | sw_vers | grep "ProductVersion:.*10\.6"
89 | if [ $? == 0 ]; then
90 | echo "pruning Leopard event handler"
91 | /usr/libexec/PlistBuddy -c "Delete :OSAXHandlers:Events:SIMeleop" "$OSAX_PLIST"
92 | fi
93 |
94 | exit 0
95 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | What is this?
2 | =============
3 |
4 | Safari Omnibar is a Safari SIMBL plugin aiming at mimicing the Chrome's smart location bar which combines location and search.
5 |
6 | [Changelog](http://rsparkle.herokuapp.com/SafariOmnibar/changes.html)
7 |
8 | Requirement
9 | ===========
10 |
11 | - Intel Mac ([PPC port](https://github.com/stefanschmidt/SafariOmnibar))
12 | - Safari 5.0 (Snow Leopard) or 5.1 (Lion)
13 | - [SIMBL](http://www.culater.net/software/SIMBL/SIMBL.php) 0.9.9 (packaged with the installer)
14 |
15 | Installation
16 | ============
17 |
18 | Download our [installer](http://rsparkle.herokuapp.com/SafariOmnibar/last) and run it then restart Safari.
19 |
20 | Uninstallation
21 | ==============
22 |
23 | Remove the file `/Library/Application\ Support/SIMBL/Plugins/SafariOmnibar.bundle`
24 |
25 | Usage
26 | =====
27 |
28 | Just type a search query in the location bar and it will perform a Google search.
29 |
30 | TODO
31 | ====
32 |
33 | - Preference Panel
34 | - Let the user choose not to hide the Safari's search field
35 | - Search engine editor with keyword support just like Chrome's
36 | - Google auto-suggests injection in the completion menu
37 |
--------------------------------------------------------------------------------
/SafariOmnibar.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 1C8F02A713DB765600A3632D /* SearchProvidersEditorWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = 1C8F02A613DB765600A3632D /* SearchProvidersEditorWindowController.m */; };
11 | 1C8F02AA13DB7B2C00A3632D /* SearchProvidersEditor.xib in Resources */ = {isa = PBXBuildFile; fileRef = 1C8F02A913DB7B2C00A3632D /* SearchProvidersEditor.xib */; };
12 | 53B2999813CA4BD800CDB6FF /* JRSwizzle.m in Sources */ = {isa = PBXBuildFile; fileRef = 53B2999713CA4BD800CDB6FF /* JRSwizzle.m */; };
13 | 53B299A913CB306800CDB6FF /* SearchProviders.plist in Resources */ = {isa = PBXBuildFile; fileRef = 53B299A813CB306800CDB6FF /* SearchProviders.plist */; };
14 | 53DDD7FB13E810C000039E90 /* SparkleHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 53DDD7FA13E810C000039E90 /* SparkleHelper.m */; };
15 | 53DDD80513E8157300039E90 /* Sparkle.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 53DDD80313E8155400039E90 /* Sparkle.framework */; };
16 | 53F7E26C13CA2680007FFA53 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 53F7E26B13CA2680007FFA53 /* Cocoa.framework */; };
17 | 53F7E27613CA2680007FFA53 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 53F7E27413CA2680007FFA53 /* InfoPlist.strings */; };
18 | 53F7E27F13CA26BC007FFA53 /* SafariOmnibar.m in Sources */ = {isa = PBXBuildFile; fileRef = 53F7E27E13CA26BC007FFA53 /* SafariOmnibar.m */; };
19 | /* End PBXBuildFile section */
20 |
21 | /* Begin PBXCopyFilesBuildPhase section */
22 | 53DDD80013E814E300039E90 /* CopyFiles */ = {
23 | isa = PBXCopyFilesBuildPhase;
24 | buildActionMask = 2147483647;
25 | dstPath = "";
26 | dstSubfolderSpec = 10;
27 | files = (
28 | 53DDD80513E8157300039E90 /* Sparkle.framework in CopyFiles */,
29 | );
30 | runOnlyForDeploymentPostprocessing = 0;
31 | };
32 | /* End PBXCopyFilesBuildPhase section */
33 |
34 | /* Begin PBXFileReference section */
35 | 1C8F02A513DB765600A3632D /* SearchProvidersEditorWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SearchProvidersEditorWindowController.h; sourceTree = ""; };
36 | 1C8F02A613DB765600A3632D /* SearchProvidersEditorWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SearchProvidersEditorWindowController.m; sourceTree = ""; };
37 | 1C8F02A913DB7B2C00A3632D /* SearchProvidersEditor.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = SearchProvidersEditor.xib; sourceTree = ""; };
38 | 53B2999613CA4BD800CDB6FF /* JRSwizzle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JRSwizzle.h; sourceTree = ""; };
39 | 53B2999713CA4BD800CDB6FF /* JRSwizzle.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JRSwizzle.m; sourceTree = ""; };
40 | 53B299A813CB306800CDB6FF /* SearchProviders.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = SearchProviders.plist; sourceTree = ""; };
41 | 53DDD7F913E810C000039E90 /* SparkleHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SparkleHelper.h; sourceTree = ""; };
42 | 53DDD7FA13E810C000039E90 /* SparkleHelper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SparkleHelper.m; sourceTree = ""; };
43 | 53DDD80313E8155400039E90 /* Sparkle.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Sparkle.framework; sourceTree = ""; };
44 | 53F7E26813CA2680007FFA53 /* SafariOmnibar.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SafariOmnibar.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
45 | 53F7E26B13CA2680007FFA53 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
46 | 53F7E27313CA2680007FFA53 /* SafariOmnibar-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "SafariOmnibar-Info.plist"; sourceTree = ""; };
47 | 53F7E27513CA2680007FFA53 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; };
48 | 53F7E27713CA2680007FFA53 /* SafariOmnibar-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SafariOmnibar-Prefix.pch"; sourceTree = ""; };
49 | 53F7E27D13CA26BC007FFA53 /* SafariOmnibar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SafariOmnibar.h; sourceTree = ""; };
50 | 53F7E27E13CA26BC007FFA53 /* SafariOmnibar.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SafariOmnibar.m; sourceTree = ""; };
51 | /* End PBXFileReference section */
52 |
53 | /* Begin PBXFrameworksBuildPhase section */
54 | 53F7E26513CA2680007FFA53 /* Frameworks */ = {
55 | isa = PBXFrameworksBuildPhase;
56 | buildActionMask = 2147483647;
57 | files = (
58 | 53F7E26C13CA2680007FFA53 /* Cocoa.framework in Frameworks */,
59 | );
60 | runOnlyForDeploymentPostprocessing = 0;
61 | };
62 | /* End PBXFrameworksBuildPhase section */
63 |
64 | /* Begin PBXGroup section */
65 | 53F7E25D13CA2680007FFA53 = {
66 | isa = PBXGroup;
67 | children = (
68 | 53F7E27113CA2680007FFA53 /* SafariOmnibar */,
69 | 53F7E26A13CA2680007FFA53 /* Frameworks */,
70 | 53F7E26913CA2680007FFA53 /* Products */,
71 | );
72 | sourceTree = "";
73 | };
74 | 53F7E26913CA2680007FFA53 /* Products */ = {
75 | isa = PBXGroup;
76 | children = (
77 | 53F7E26813CA2680007FFA53 /* SafariOmnibar.bundle */,
78 | );
79 | name = Products;
80 | sourceTree = "";
81 | };
82 | 53F7E26A13CA2680007FFA53 /* Frameworks */ = {
83 | isa = PBXGroup;
84 | children = (
85 | 53DDD80313E8155400039E90 /* Sparkle.framework */,
86 | 53F7E26B13CA2680007FFA53 /* Cocoa.framework */,
87 | );
88 | name = Frameworks;
89 | sourceTree = "";
90 | };
91 | 53F7E27113CA2680007FFA53 /* SafariOmnibar */ = {
92 | isa = PBXGroup;
93 | children = (
94 | 53F7E27213CA2680007FFA53 /* Supporting Files */,
95 | 53F7E27D13CA26BC007FFA53 /* SafariOmnibar.h */,
96 | 53F7E27E13CA26BC007FFA53 /* SafariOmnibar.m */,
97 | 53DDD7F913E810C000039E90 /* SparkleHelper.h */,
98 | 53DDD7FA13E810C000039E90 /* SparkleHelper.m */,
99 | 1C8F02A513DB765600A3632D /* SearchProvidersEditorWindowController.h */,
100 | 1C8F02A613DB765600A3632D /* SearchProvidersEditorWindowController.m */,
101 | 1C8F02A913DB7B2C00A3632D /* SearchProvidersEditor.xib */,
102 | 53B2999613CA4BD800CDB6FF /* JRSwizzle.h */,
103 | 53B2999713CA4BD800CDB6FF /* JRSwizzle.m */,
104 | );
105 | path = SafariOmnibar;
106 | sourceTree = "";
107 | };
108 | 53F7E27213CA2680007FFA53 /* Supporting Files */ = {
109 | isa = PBXGroup;
110 | children = (
111 | 53F7E27313CA2680007FFA53 /* SafariOmnibar-Info.plist */,
112 | 53F7E27413CA2680007FFA53 /* InfoPlist.strings */,
113 | 53F7E27713CA2680007FFA53 /* SafariOmnibar-Prefix.pch */,
114 | 53B299A813CB306800CDB6FF /* SearchProviders.plist */,
115 | );
116 | name = "Supporting Files";
117 | sourceTree = "";
118 | };
119 | /* End PBXGroup section */
120 |
121 | /* Begin PBXNativeTarget section */
122 | 53F7E26713CA2680007FFA53 /* SafariOmnibar */ = {
123 | isa = PBXNativeTarget;
124 | buildConfigurationList = 53F7E27A13CA2680007FFA53 /* Build configuration list for PBXNativeTarget "SafariOmnibar" */;
125 | buildPhases = (
126 | 53DDD7FD13E8112B00039E90 /* ShellScript */,
127 | 53F7E26413CA2680007FFA53 /* Sources */,
128 | 53F7E26513CA2680007FFA53 /* Frameworks */,
129 | 53F7E26613CA2680007FFA53 /* Resources */,
130 | 53DDD80013E814E300039E90 /* CopyFiles */,
131 | 53F7E28313CA2F46007FFA53 /* Run Script */,
132 | );
133 | buildRules = (
134 | );
135 | dependencies = (
136 | );
137 | name = SafariOmnibar;
138 | productName = SafariOmnibar;
139 | productReference = 53F7E26813CA2680007FFA53 /* SafariOmnibar.bundle */;
140 | productType = "com.apple.product-type.bundle";
141 | };
142 | /* End PBXNativeTarget section */
143 |
144 | /* Begin PBXProject section */
145 | 53F7E25F13CA2680007FFA53 /* Project object */ = {
146 | isa = PBXProject;
147 | attributes = {
148 | LastUpgradeCheck = 0420;
149 | };
150 | buildConfigurationList = 53F7E26213CA2680007FFA53 /* Build configuration list for PBXProject "SafariOmnibar" */;
151 | compatibilityVersion = "Xcode 3.2";
152 | developmentRegion = English;
153 | hasScannedForEncodings = 0;
154 | knownRegions = (
155 | en,
156 | );
157 | mainGroup = 53F7E25D13CA2680007FFA53;
158 | productRefGroup = 53F7E26913CA2680007FFA53 /* Products */;
159 | projectDirPath = "";
160 | projectRoot = "";
161 | targets = (
162 | 53F7E26713CA2680007FFA53 /* SafariOmnibar */,
163 | );
164 | };
165 | /* End PBXProject section */
166 |
167 | /* Begin PBXResourcesBuildPhase section */
168 | 53F7E26613CA2680007FFA53 /* Resources */ = {
169 | isa = PBXResourcesBuildPhase;
170 | buildActionMask = 2147483647;
171 | files = (
172 | 53F7E27613CA2680007FFA53 /* InfoPlist.strings in Resources */,
173 | 53B299A913CB306800CDB6FF /* SearchProviders.plist in Resources */,
174 | 1C8F02AA13DB7B2C00A3632D /* SearchProvidersEditor.xib in Resources */,
175 | );
176 | runOnlyForDeploymentPostprocessing = 0;
177 | };
178 | /* End PBXResourcesBuildPhase section */
179 |
180 | /* Begin PBXShellScriptBuildPhase section */
181 | 53DDD7FD13E8112B00039E90 /* ShellScript */ = {
182 | isa = PBXShellScriptBuildPhase;
183 | buildActionMask = 2147483647;
184 | files = (
185 | );
186 | inputPaths = (
187 | );
188 | outputPaths = (
189 | );
190 | runOnlyForDeploymentPostprocessing = 0;
191 | shellPath = /bin/sh;
192 | shellScript = "if [ ! -d Sparkle.framework ]\nthen\n echo \"Downloading Sparkle Framework\"\n curl -s -o /tmp/$$.zip http://sparkle.andymatuschak.org/files/Sparkle%201.5b6.zip\n unzip -q /tmp/$$.zip Sparkle.framework/*\n rm -f /tmp/$$.zip\nfi";
193 | };
194 | 53F7E28313CA2F46007FFA53 /* Run Script */ = {
195 | isa = PBXShellScriptBuildPhase;
196 | buildActionMask = 2147483647;
197 | files = (
198 | );
199 | inputPaths = (
200 | );
201 | name = "Run Script";
202 | outputPaths = (
203 | );
204 | runOnlyForDeploymentPostprocessing = 0;
205 | shellPath = /bin/sh;
206 | shellScript = "# ensure user-local SIMBL plugins folder exists\nmkdir -p \"${USER_LIBRARY_DIR}/Application Support/SIMBL/Plugins\"\n\n# clean up any previous products/symbolic links in the SIMBL Plugins folder\nif [ -a \"${USER_LIBRARY_DIR}/Application Support/SIMBL/Plugins/${FULL_PRODUCT_NAME}\" ]; then\nrm -Rf \"${USER_LIBRARY_DIR}/Application Support/SIMBL/Plugins/${FULL_PRODUCT_NAME}\"\nfi\n\n# Depending on the build configuration, either copy or link to the most recent product\nif [ \"${CONFIGURATION}\" == \"Debug\" ]; then\n# if we're debugging, add a symbolic link to the plug-in\nln -sf \"${TARGET_BUILD_DIR}/${FULL_PRODUCT_NAME}\" \"${USER_LIBRARY_DIR}/Application Support/SIMBL/Plugins/${FULL_PRODUCT_NAME}\"\nelif [ \"${CONFIGURATION}\" == \"Release\" ]; then\n# if we're compiling for release, just copy the plugin to the SIMBL Plugins folder\ncp -Rfv \"${TARGET_BUILD_DIR}/${FULL_PRODUCT_NAME}\" \"${USER_LIBRARY_DIR}/Application Support/SIMBL/Plugins/${FULL_PRODUCT_NAME}\"\nfi";
207 | };
208 | /* End PBXShellScriptBuildPhase section */
209 |
210 | /* Begin PBXSourcesBuildPhase section */
211 | 53F7E26413CA2680007FFA53 /* Sources */ = {
212 | isa = PBXSourcesBuildPhase;
213 | buildActionMask = 2147483647;
214 | files = (
215 | 53F7E27F13CA26BC007FFA53 /* SafariOmnibar.m in Sources */,
216 | 53B2999813CA4BD800CDB6FF /* JRSwizzle.m in Sources */,
217 | 1C8F02A713DB765600A3632D /* SearchProvidersEditorWindowController.m in Sources */,
218 | 53DDD7FB13E810C000039E90 /* SparkleHelper.m in Sources */,
219 | );
220 | runOnlyForDeploymentPostprocessing = 0;
221 | };
222 | /* End PBXSourcesBuildPhase section */
223 |
224 | /* Begin PBXVariantGroup section */
225 | 53F7E27413CA2680007FFA53 /* InfoPlist.strings */ = {
226 | isa = PBXVariantGroup;
227 | children = (
228 | 53F7E27513CA2680007FFA53 /* en */,
229 | );
230 | name = InfoPlist.strings;
231 | sourceTree = "";
232 | };
233 | /* End PBXVariantGroup section */
234 |
235 | /* Begin XCBuildConfiguration section */
236 | 53F7E27813CA2680007FFA53 /* Debug */ = {
237 | isa = XCBuildConfiguration;
238 | buildSettings = {
239 | ALWAYS_SEARCH_USER_PATHS = NO;
240 | ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
241 | CLANG_ENABLE_OBJC_ARC = NO;
242 | COPY_PHASE_STRIP = NO;
243 | GCC_C_LANGUAGE_STANDARD = gnu99;
244 | GCC_DYNAMIC_NO_PIC = NO;
245 | GCC_ENABLE_OBJC_EXCEPTIONS = YES;
246 | GCC_OPTIMIZATION_LEVEL = 0;
247 | GCC_PREPROCESSOR_DEFINITIONS = (
248 | "DEBUG=1",
249 | "$(inherited)",
250 | );
251 | GCC_SYMBOLS_PRIVATE_EXTERN = NO;
252 | GCC_VERSION = "";
253 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
254 | GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
255 | GCC_WARN_ABOUT_RETURN_TYPE = YES;
256 | GCC_WARN_UNUSED_VARIABLE = YES;
257 | MACOSX_DEPLOYMENT_TARGET = 10.7;
258 | ONLY_ACTIVE_ARCH = YES;
259 | RUN_CLANG_STATIC_ANALYZER = YES;
260 | SDKROOT = macosx;
261 | };
262 | name = Debug;
263 | };
264 | 53F7E27913CA2680007FFA53 /* Release */ = {
265 | isa = XCBuildConfiguration;
266 | buildSettings = {
267 | ALWAYS_SEARCH_USER_PATHS = NO;
268 | ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
269 | CLANG_ENABLE_OBJC_ARC = NO;
270 | COPY_PHASE_STRIP = YES;
271 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
272 | GCC_C_LANGUAGE_STANDARD = gnu99;
273 | GCC_ENABLE_OBJC_EXCEPTIONS = YES;
274 | GCC_VERSION = "";
275 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
276 | GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
277 | GCC_WARN_ABOUT_RETURN_TYPE = YES;
278 | GCC_WARN_UNUSED_VARIABLE = YES;
279 | MACOSX_DEPLOYMENT_TARGET = 10.7;
280 | RUN_CLANG_STATIC_ANALYZER = YES;
281 | SDKROOT = macosx;
282 | };
283 | name = Release;
284 | };
285 | 53F7E27B13CA2680007FFA53 /* Debug */ = {
286 | isa = XCBuildConfiguration;
287 | buildSettings = {
288 | FRAMEWORK_SEARCH_PATHS = (
289 | "$(inherited)",
290 | "\"$(SRCROOT)\"",
291 | );
292 | GCC_PRECOMPILE_PREFIX_HEADER = YES;
293 | GCC_PREFIX_HEADER = "SafariOmnibar/SafariOmnibar-Prefix.pch";
294 | INFOPLIST_FILE = "SafariOmnibar/SafariOmnibar-Info.plist";
295 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Bundles";
296 | PRODUCT_NAME = "$(TARGET_NAME)";
297 | WRAPPER_EXTENSION = bundle;
298 | };
299 | name = Debug;
300 | };
301 | 53F7E27C13CA2680007FFA53 /* Release */ = {
302 | isa = XCBuildConfiguration;
303 | buildSettings = {
304 | FRAMEWORK_SEARCH_PATHS = (
305 | "$(inherited)",
306 | "\"$(SRCROOT)\"",
307 | );
308 | GCC_PRECOMPILE_PREFIX_HEADER = YES;
309 | GCC_PREFIX_HEADER = "SafariOmnibar/SafariOmnibar-Prefix.pch";
310 | INFOPLIST_FILE = "SafariOmnibar/SafariOmnibar-Info.plist";
311 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Bundles";
312 | PRODUCT_NAME = "$(TARGET_NAME)";
313 | WRAPPER_EXTENSION = bundle;
314 | };
315 | name = Release;
316 | };
317 | /* End XCBuildConfiguration section */
318 |
319 | /* Begin XCConfigurationList section */
320 | 53F7E26213CA2680007FFA53 /* Build configuration list for PBXProject "SafariOmnibar" */ = {
321 | isa = XCConfigurationList;
322 | buildConfigurations = (
323 | 53F7E27813CA2680007FFA53 /* Debug */,
324 | 53F7E27913CA2680007FFA53 /* Release */,
325 | );
326 | defaultConfigurationIsVisible = 0;
327 | defaultConfigurationName = Release;
328 | };
329 | 53F7E27A13CA2680007FFA53 /* Build configuration list for PBXNativeTarget "SafariOmnibar" */ = {
330 | isa = XCConfigurationList;
331 | buildConfigurations = (
332 | 53F7E27B13CA2680007FFA53 /* Debug */,
333 | 53F7E27C13CA2680007FFA53 /* Release */,
334 | );
335 | defaultConfigurationIsVisible = 0;
336 | defaultConfigurationName = Release;
337 | };
338 | /* End XCConfigurationList section */
339 | };
340 | rootObject = 53F7E25F13CA2680007FFA53 /* Project object */;
341 | }
342 |
--------------------------------------------------------------------------------
/SafariOmnibar/JRSwizzle.h:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | JRSwizzle.h
3 | Copyright (c) 2007 Jonathan 'Wolf' Rentzsch:
4 | Some rights reserved:
5 |
6 | ***************************************************************************/
7 |
8 | #import
9 |
10 | @interface NSObject (JRSwizzle)
11 | + (BOOL)jr_swizzleMethod:(SEL)origSel_ withMethod:(SEL)altSel_ error:(NSError**)error_;
12 | + (BOOL)jr_swizzleClassMethod:(SEL)origSel_ withClassMethod:(SEL)altSel_ error:(NSError**)error_;
13 | @end
14 |
--------------------------------------------------------------------------------
/SafariOmnibar/JRSwizzle.m:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | JRSwizzle.m
3 | Copyright (c) 2007 Jonathan 'Wolf' Rentzsch:
4 | Some rights reserved:
5 |
6 | ***************************************************************************/
7 |
8 | #import "JRSwizzle.h"
9 | #import
10 |
11 | #define SetNSError(ERROR_VAR, FORMAT,...) \
12 | if (ERROR_VAR) { \
13 | NSString *errStr = [@"+[NSObject(JRSwizzle) jr_swizzleMethod:withMethod:error:]: " stringByAppendingFormat:FORMAT,##__VA_ARGS__]; \
14 | *ERROR_VAR = [NSError errorWithDomain:@"NSCocoaErrorDomain" \
15 | code:-1 \
16 | userInfo:[NSDictionary dictionaryWithObject:errStr forKey:NSLocalizedDescriptionKey]]; \
17 | }
18 |
19 | @implementation NSObject (JRSwizzle)
20 |
21 | + (BOOL)jr_swizzleMethod:(SEL)origSel_ withMethod:(SEL)altSel_ error:(NSError**)error_ {
22 | #if OBJC_API_VERSION >= 2
23 | Method origMethod = class_getInstanceMethod(self, origSel_);
24 | if (!origMethod) {
25 | SetNSError(error_, @"original method %@ not found for class %@", NSStringFromSelector(origSel_), [self className]);
26 | return NO;
27 | }
28 |
29 | Method altMethod = class_getInstanceMethod(self, altSel_);
30 | if (!altMethod) {
31 | SetNSError(error_, @"alternate method %@ not found for class %@", NSStringFromSelector(altSel_), [self className]);
32 | return NO;
33 | }
34 |
35 | class_addMethod(self,
36 | origSel_,
37 | class_getMethodImplementation(self, origSel_),
38 | method_getTypeEncoding(origMethod));
39 | class_addMethod(self,
40 | altSel_,
41 | class_getMethodImplementation(self, altSel_),
42 | method_getTypeEncoding(altMethod));
43 |
44 | method_exchangeImplementations(class_getInstanceMethod(self, origSel_), class_getInstanceMethod(self, altSel_));
45 | return YES;
46 | #else
47 | // Scan for non-inherited methods.
48 | Method directOriginalMethod = NULL, directAlternateMethod = NULL;
49 |
50 | void *iterator = NULL;
51 | struct objc_method_list *mlist = class_nextMethodList(self, &iterator);
52 | while (mlist) {
53 | int method_index = 0;
54 | for (; method_index < mlist->method_count; method_index++) {
55 | if (mlist->method_list[method_index].method_name == origSel_) {
56 | assert(!directOriginalMethod);
57 | directOriginalMethod = &mlist->method_list[method_index];
58 | }
59 | if (mlist->method_list[method_index].method_name == altSel_) {
60 | assert(!directAlternateMethod);
61 | directAlternateMethod = &mlist->method_list[method_index];
62 | }
63 | }
64 | mlist = class_nextMethodList(self, &iterator);
65 | }
66 |
67 | // If either method is inherited, copy it up to the target class to make it non-inherited.
68 | if (!directOriginalMethod || !directAlternateMethod) {
69 | Method inheritedOriginalMethod = NULL, inheritedAlternateMethod = NULL;
70 | if (!directOriginalMethod) {
71 | inheritedOriginalMethod = class_getInstanceMethod(self, origSel_);
72 | if (!inheritedOriginalMethod) {
73 | SetNSError(error_, @"original method %@ not found for class %@", NSStringFromSelector(origSel_), [self className]);
74 | return NO;
75 | }
76 | }
77 | if (!directAlternateMethod) {
78 | inheritedAlternateMethod = class_getInstanceMethod(self, altSel_);
79 | if (!inheritedAlternateMethod) {
80 | SetNSError(error_, @"alternate method %@ not found for class %@", NSStringFromSelector(altSel_), [self className]);
81 | return NO;
82 | }
83 | }
84 |
85 | int hoisted_method_count = !directOriginalMethod && !directAlternateMethod ? 2 : 1;
86 | struct objc_method_list *hoisted_method_list = malloc(sizeof(struct objc_method_list) + (sizeof(struct objc_method)*(hoisted_method_count-1)));
87 | hoisted_method_list->method_count = hoisted_method_count;
88 | Method hoisted_method = hoisted_method_list->method_list;
89 |
90 | if (!directOriginalMethod) {
91 | bcopy(inheritedOriginalMethod, hoisted_method, sizeof(struct objc_method));
92 | directOriginalMethod = hoisted_method++;
93 | }
94 | if (!directAlternateMethod) {
95 | bcopy(inheritedAlternateMethod, hoisted_method, sizeof(struct objc_method));
96 | directAlternateMethod = hoisted_method;
97 | }
98 | class_addMethods(self, hoisted_method_list);
99 | }
100 |
101 | // Swizzle.
102 | IMP temp = directOriginalMethod->method_imp;
103 | directOriginalMethod->method_imp = directAlternateMethod->method_imp;
104 | directAlternateMethod->method_imp = temp;
105 |
106 | return YES;
107 | #endif
108 | }
109 |
110 | + (BOOL)jr_swizzleClassMethod:(SEL)origSel_ withClassMethod:(SEL)altSel_ error:(NSError**)error_ {
111 | assert(0);
112 | return NO;
113 | }
114 |
115 | @end
116 |
--------------------------------------------------------------------------------
/SafariOmnibar/SafariOmnibar-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | English
7 | CFBundleExecutable
8 | ${EXECUTABLE_NAME}
9 | CFBundleIconFile
10 |
11 | CFBundleIdentifier
12 | net.rhapsodyk.${PRODUCT_NAME:rfc1034identifier}
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | ${PRODUCT_NAME}
17 | CFBundlePackageType
18 | BNDL
19 | CFBundleShortVersionString
20 | 1.6
21 | CFBundleSignature
22 | ????
23 | CFBundleVersion
24 | 1.6
25 | NSHumanReadableCopyright
26 | Copyright © 2011 Olivier Poitrey. All rights reserved.
27 | NSPrincipalClass
28 | SafariOmnibar
29 | SIMBLTargetApplications
30 |
31 |
32 | BundleIdentifier
33 | com.apple.Safari
34 | MaxBundleVersion
35 | 7534
36 | MinBundleVersion
37 | 6533
38 |
39 |
40 | BundleIdentifier
41 | org.webkit.nightly.WebKit
42 |
43 |
44 | SUFeedURL
45 | https://rsparkle.herokuapp.com/SafariOmnibar/updates.xml
46 | SUEnableAutomaticChecks
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/SafariOmnibar/SafariOmnibar-Prefix.pch:
--------------------------------------------------------------------------------
1 | //
2 | // Prefix header for all source files of the 'SafariOmnibar' target in the 'SafariOmnibar' project
3 | //
4 |
5 | #ifdef __OBJC__
6 | #import
7 | #endif
8 |
--------------------------------------------------------------------------------
/SafariOmnibar/SafariOmnibar.h:
--------------------------------------------------------------------------------
1 | //
2 | // SafariOmnibar.h
3 | // SafariOmnibar
4 | //
5 | // Created by Olivier Poitrey on 10/07/11.
6 | // Copyright 2011 Olivier Poitrey. All rights reserved.
7 | //
8 |
9 | @interface SafariOmnibar : NSObject
10 | {
11 | @private
12 | NSArray *searchProviders;
13 | NSDictionary *defaultSearchProvider;
14 | NSMenuItem *editSearchProvidersItem;
15 | NSMutableDictionary *locationFieldContext;
16 | }
17 |
18 | @property (nonatomic, readonly) NSArray *searchProviders;
19 | @property (nonatomic, readonly) NSDictionary *defaultSearchProvider;
20 | @property (nonatomic, readonly) NSString *pluginVersion;
21 |
22 | + (SafariOmnibar *)sharedInstance;
23 | - (NSDictionary *)searchProviderForKeyword:(NSString *)keyword;
24 | - (NSDictionary *)searchProviderForLocationField:(NSTextField *)locationField;
25 | - (void)resetSearchProviderForLocationField:(NSTextField *)locationField;
26 | - (void)updateSearchProviderForLocationField:(NSTextField *)locationField;
27 | - (NSDictionary *)previousSearchProviderForLocationField:(NSTextField *)locationField;
28 | - (void)saveSearchQuery:(NSString *)searchQuery forLocationField:(NSTextField *)locationField;
29 | - (NSString *)previousSearchQueryForLocationField:(NSTextField *)locationField;
30 |
31 | @end
32 |
--------------------------------------------------------------------------------
/SafariOmnibar/SafariOmnibar.m:
--------------------------------------------------------------------------------
1 | //
2 | // SafariOmnibar.m
3 | // SafariOmnibar
4 | //
5 | // Created by Olivier Poitrey on 10/07/11.
6 | // Copyright 2011 Olivier Poitrey. All rights reserved.
7 | //
8 |
9 | #import "SafariOmnibar.h"
10 | #import "SparkleHelper.h"
11 | #import "SearchProvidersEditorWindowController.h"
12 | #import "JRSwizzle.h"
13 |
14 | NSString * const kOmnibarSearchProviders = @"SafariOmnibar_SearchProviders";
15 |
16 | static BOOL is_search_query(NSString *string)
17 | {
18 | // Clean the input
19 | string = [string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
20 |
21 | // If it starts by a known scheme, don't try to validate the URL format, user certainly want to enter a URL.
22 | // Even a bad one should shouldn't be treated as a search
23 | if ([string hasPrefix:@"http://"] || [string hasPrefix:@"https://"] || [string hasPrefix:@"file://"]
24 | || [string hasPrefix:@"javascript:"] || [string hasPrefix:@"feed:"] || [string hasPrefix:@"about:"])
25 | return NO;
26 |
27 | // If it starts by a scheme handled by another app, let the target app validate the URL and do not catch it as a search
28 | if (LSGetApplicationForURL((CFURLRef)[NSURL URLWithString:string], kLSRolesAll, NULL, NULL) == 0)
29 | return NO;
30 |
31 | // If more than one word, it's certainly a search query
32 | if ([string rangeOfString:@" "].location != NSNotFound)
33 | return YES;
34 |
35 | NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"http://%@", string]];
36 |
37 | // A single word that can't be parsed as an URL is certainly a search query
38 | if (!url)
39 | return YES;
40 |
41 | // Treat localhost specifically
42 | if ([url.host isEqualToString:@"localhost"])
43 | return NO;
44 |
45 | // If the host part contains dot(s), treat the string as URL, the user certainly entered a URL manually with no scheme
46 | if ([url.host rangeOfString:@"."].location != NSNotFound)
47 | return NO;
48 |
49 | return YES;
50 | }
51 |
52 | @implementation NSWindowController(SO)
53 |
54 | - (void)SafariOmnibar_goToToolbarLocation:(NSTextField *)locationField
55 | {
56 | SafariOmnibar *plugin = [SafariOmnibar sharedInstance];
57 | NSDictionary *provider = [plugin searchProviderForLocationField:locationField];
58 | NSString *location = [locationField.stringValue stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
59 | NSString *searchTerms = location;
60 | NSString *searchURLTemplate = nil;
61 |
62 | if (provider)
63 | {
64 | // Custom search provider
65 | searchURLTemplate = [provider objectForKey:@"SearchURLTemplate"];
66 | NSUInteger colonLoc = [location rangeOfString:@":"].location;
67 | if (colonLoc + 2 < location.length)
68 | {
69 | searchTerms = [location substringWithRange:NSMakeRange(colonLoc + 2, location.length - (colonLoc + 2))];
70 | }
71 | else
72 | {
73 | searchTerms = @"";
74 | }
75 | [plugin resetSearchProviderForLocationField:locationField];
76 | }
77 | else if (is_search_query(location))
78 | {
79 | // If we detect a search query with not search provider keyword, use the default search provider
80 | searchURLTemplate = [[plugin defaultSearchProvider] objectForKey:@"SearchURLTemplate"];
81 | }
82 |
83 | if (searchURLTemplate)
84 | {
85 | // Save untouched search terms in this fields' context
86 | [plugin saveSearchQuery:searchTerms forLocationField:locationField];
87 |
88 | searchTerms = [searchTerms stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
89 | // escape more
90 | searchTerms = [searchTerms stringByReplacingOccurrencesOfString:@"&" withString:@"%26"];
91 | searchTerms = [searchTerms stringByReplacingOccurrencesOfString:@"+" withString:@"%2B"];
92 | [locationField setStringValue:[searchURLTemplate stringByReplacingOccurrencesOfString:@"{searchTerms}" withString:searchTerms]];
93 | }
94 |
95 | [self SafariOmnibar_goToToolbarLocation:locationField];
96 | }
97 |
98 | @end
99 |
100 | @implementation NSDocument(SO)
101 |
102 | - (NSTextField *)SafariOmnibar_locationField
103 | {
104 | id windowController = nil;
105 | if ([self respondsToSelector:@selector(browserWindowControllerMac)]) // Safari 5.1
106 | {
107 | windowController = [self performSelector:@selector(browserWindowControllerMac)];
108 | }
109 | else if ([self respondsToSelector:@selector(browserWindowController)]) // Safari 5.0
110 | {
111 | windowController = [self performSelector:@selector(browserWindowController)];
112 | }
113 | if (windowController)
114 | {
115 | if ([windowController respondsToSelector:@selector(locationField)])
116 | {
117 | return [windowController performSelector:@selector(locationField)];
118 | }
119 | }
120 | return nil;
121 | }
122 |
123 | - (BOOL)SafariOmnibar_restoreLastSearch:(NSTextField *)locationField forced:(BOOL)forced
124 | {
125 | SafariOmnibar *plugin = [SafariOmnibar sharedInstance];
126 |
127 | // If current location URL contains the last search (or forced is YES), replace the URL by the search so user can easily edit it
128 | NSString *lastSearch = [plugin previousSearchQueryForLocationField:locationField];
129 | if (lastSearch
130 | && (forced || [[locationField.stringValue stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding] rangeOfString:lastSearch].location != NSNotFound))
131 | {
132 | NSDictionary *provider = [plugin previousSearchProviderForLocationField:locationField];
133 | if (provider)
134 | {
135 | // Add back the former search provider keyword
136 | lastSearch = [NSString stringWithFormat:@"%@ %@", [provider objectForKey:@"Keyword"], lastSearch];
137 | }
138 | if (lastSearch)
139 | {
140 | [locationField setStringValue:lastSearch];
141 | if (provider) [plugin updateSearchProviderForLocationField:locationField];
142 | return YES;
143 | }
144 | }
145 |
146 | return NO;
147 | }
148 |
149 | - (void)SafariOmnibar_searchWeb:(id)sender
150 | {
151 | // This is the action behind Edit > Find > Find Google...
152 | NSTextField *locationField = [self SafariOmnibar_locationField];
153 | if (locationField)
154 | {
155 | if (![self SafariOmnibar_restoreLastSearch:locationField forced:YES])
156 | {
157 | // Force default search provider
158 | [locationField setStringValue:@"?"];
159 | [[SafariOmnibar sharedInstance] updateSearchProviderForLocationField:locationField];
160 | }
161 | // Focus location field
162 | [locationField becomeFirstResponder];
163 | // Move the caret at the end of the text's field
164 | [(NSText *)[[locationField window] firstResponder] setSelectedRange:NSMakeRange(locationField.stringValue.length, 0)];
165 | }
166 | }
167 |
168 | - (void)SafariOmnibar_openLocation:(id)sender
169 | {
170 | // This is the action behind File > Open Location...
171 | NSTextField *locationField = [self SafariOmnibar_locationField];
172 | if (locationField)
173 | {
174 | // Mimic Chrome behavior by selecting the content of the location text field, ready to be replaced
175 | [locationField selectText:nil];
176 | }
177 | [self SafariOmnibar_openLocation:sender];
178 | }
179 |
180 | @end
181 |
182 | @interface SafariOmnibar ()
183 |
184 | @property (nonatomic, retain) NSMenuItem *editSearchProvidersItem;
185 |
186 | @end
187 |
188 | @implementation SafariOmnibar
189 | @synthesize searchProviders;
190 | @synthesize defaultSearchProvider;
191 | @synthesize editSearchProvidersItem;
192 | @dynamic pluginVersion;
193 |
194 | - (NSMutableDictionary *)contextForLocationField:(NSTextField *)locationField
195 | {
196 | return [locationFieldContext objectForKey:[NSNumber numberWithInteger:locationField.hash]];
197 | }
198 |
199 | - (void)onLocationFieldChange:(NSNotification *)notification
200 | {
201 | [self updateSearchProviderForLocationField:notification.object];
202 | }
203 |
204 | - (void)addContextMenuItemsToLocationField:(id)locationField
205 | {
206 | // To add an item to the location field's context menu, we need to add one
207 | // to its field editor. In Safari, this field editor appears to be unique
208 | // to the location field, and the same instance is shared throughout the
209 | // application. This lets us simply keep a reference to the menu item we
210 | // add and check its presence to stop from adding the menu item multiple
211 | // times.
212 | if (self.editSearchProvidersItem) return;
213 | self.editSearchProvidersItem = [[[NSMenuItem alloc] initWithTitle:NSLocalizedString(@"Edit Omnibar Search Providers…", @"location field context menu item")
214 | action:@selector(editSearchProviders:)
215 | keyEquivalent:@""] autorelease];
216 | self.editSearchProvidersItem.target = self;
217 | NSWindow *window = [locationField performSelector:@selector(window)];
218 | NSResponder *locationFieldEditor = [window fieldEditor:YES forObject:locationField];
219 | [locationFieldEditor.menu addItem:[NSMenuItem separatorItem]];
220 | [locationFieldEditor.menu addItem:self.editSearchProvidersItem];
221 | }
222 |
223 | - (void)initBrowserWindow:(NSWindow *)window
224 | {
225 | NSWindowController *windowController = [window windowController];
226 | if ([windowController respondsToSelector:@selector(searchField)]
227 | && [windowController respondsToSelector:@selector(locationField)])
228 | {
229 | [[windowController performSelector:@selector(searchField)] removeFromSuperview];
230 |
231 | NSTextField *locationField = [windowController performSelector:@selector(locationField)];
232 | // Init Omnibar context for this field
233 | [locationFieldContext setObject:[NSMutableDictionary dictionary] forKey:[NSNumber numberWithInteger:locationField.hash]];
234 |
235 | [[NSNotificationCenter defaultCenter] addObserver:self
236 | selector:@selector(onLocationFieldChange:)
237 | name:@"NSControlTextDidChangeNotification"
238 | object:locationField];
239 | [self addContextMenuItemsToLocationField:locationField];
240 | }
241 | }
242 |
243 | - (void)onNewWindow:(NSNotification *)notification
244 | {
245 | NSWindow *window = notification.object;
246 | [self initBrowserWindow:window];
247 | }
248 |
249 | - (void)loadApplicationDefaults
250 | {
251 | NSString *path = [[NSBundle bundleForClass:self.class] pathForResource:@"SearchProviders" ofType:@"plist"];
252 | NSDictionary *searchProvidersConf = [NSDictionary dictionaryWithContentsOfFile:path];
253 | NSArray *defaultSearchProviders = [searchProvidersConf objectForKey:@"SearchProvidersList"];
254 | NSDictionary *appDefaults = [NSDictionary dictionaryWithObject:defaultSearchProviders
255 | forKey:kOmnibarSearchProviders];
256 | [[NSUserDefaults standardUserDefaults] registerDefaults:appDefaults];
257 | }
258 |
259 | - (void)loadSearchProviders
260 | {
261 | [searchProviders release]; searchProviders = nil;
262 | [defaultSearchProvider release]; defaultSearchProvider = nil;
263 |
264 | searchProviders = [[[NSUserDefaults standardUserDefaults] arrayForKey:kOmnibarSearchProviders] retain];
265 |
266 | for (NSDictionary *searchProvider in searchProviders)
267 | {
268 | if ([[searchProvider objectForKey:@"Default"] boolValue])
269 | {
270 | defaultSearchProvider = [searchProvider retain];
271 | break;
272 | }
273 | }
274 | }
275 |
276 | - (void)saveSearchProviders:(NSArray *)someSearchProviders
277 | {
278 | [[NSUserDefaults standardUserDefaults] setObject:someSearchProviders
279 | forKey:kOmnibarSearchProviders];
280 | }
281 |
282 | - (NSDictionary *)searchProviderForKeyword:(NSString *)keyword
283 | {
284 | NSString *lcKeyword = [keyword lowercaseString];
285 | for (NSDictionary *provider in searchProviders)
286 | {
287 | if ([lcKeyword isEqualToString:[[provider objectForKey:@"Keyword"] lowercaseString]])
288 | {
289 | return provider;
290 | }
291 | }
292 |
293 | return nil;
294 | }
295 |
296 | - (void)updateSearchProviderForLocationField:(NSTextField *)locationField
297 | {
298 | NSString *location = locationField.stringValue;
299 | NSDictionary *provider = [self searchProviderForLocationField:locationField];
300 |
301 | if (provider)
302 | {
303 | NSString *providerName = [provider objectForKey:@"Name"];
304 | if (![location hasPrefix:[NSString stringWithFormat:@"%@: ", providerName]])
305 | {
306 | [self resetSearchProviderForLocationField:locationField];
307 | NSUInteger colonLoc = [location rangeOfString:@":"].location;
308 | if (colonLoc != NSNotFound)
309 | {
310 | location = [NSString stringWithFormat:@"%@%@",
311 | [provider objectForKey:@"Keyword"],
312 | [location substringWithRange:NSMakeRange(colonLoc + 1, location.length - (colonLoc + 1))]];
313 | [locationField setStringValue:location];
314 | }
315 | }
316 | }
317 | else
318 | {
319 | NSDictionary *provider = nil;
320 | NSString *terms = nil;
321 |
322 | if ([location hasPrefix:@"?"])
323 | {
324 | // Force default search provider if location starts with "?"
325 | terms = [location substringFromIndex:1];
326 | provider = [[SafariOmnibar sharedInstance] defaultSearchProvider];
327 | }
328 | else
329 | {
330 | // Keyword custom search provider
331 | NSUInteger firstSpaceLoc = [location rangeOfString:@" "].location;
332 |
333 | if (firstSpaceLoc != NSNotFound && firstSpaceLoc > 0)
334 | {
335 | // Lookup for search provider keyword
336 | NSString *firstWord = [[location substringWithRange:NSMakeRange(0, firstSpaceLoc)] lowercaseString];
337 | provider = [[SafariOmnibar sharedInstance] searchProviderForKeyword:firstWord];
338 | if (provider)
339 | {
340 | // Remove the keyword from terms
341 | terms = [location substringFromIndex:firstSpaceLoc + 1];
342 | }
343 | }
344 | }
345 |
346 | if (provider)
347 | {
348 | // Add the provider name
349 | locationField.stringValue = [NSString stringWithFormat:@"%@: %@", [provider objectForKey:@"Name"], terms];
350 | // Save current provider for this field
351 | [[self contextForLocationField:locationField] setObject:provider forKey:@"provider"];
352 | }
353 | }
354 | }
355 |
356 | - (NSDictionary *)searchProviderForLocationField:(NSTextField *)locationField
357 | {
358 | return [[self contextForLocationField:locationField] objectForKey:@"provider"];
359 | }
360 |
361 | - (void)resetSearchProviderForLocationField:(NSTextField *)locationField
362 | {
363 | NSDictionary *lastProvider = [self searchProviderForLocationField:locationField];
364 | if (lastProvider)
365 | {
366 | [[self contextForLocationField:locationField] removeObjectForKey:@"provider"];
367 | [[self contextForLocationField:locationField] setObject:lastProvider forKey:@"last_provider"];
368 | }
369 | }
370 |
371 | - (NSDictionary *)previousSearchProviderForLocationField:(NSTextField *)locationField
372 | {
373 | return [[self contextForLocationField:locationField] objectForKey:@"last_provider"];
374 | }
375 |
376 | - (void)saveSearchQuery:(NSString *)searchQuery forLocationField:(NSTextField *)locationField
377 | {
378 | [[self contextForLocationField:locationField] setObject:searchQuery forKey:@"last_search"];
379 | }
380 |
381 | - (NSString *)previousSearchQueryForLocationField:(NSTextField *)locationField
382 | {
383 | return [[self contextForLocationField:locationField] objectForKey:@"last_search"];
384 | }
385 |
386 |
387 | - (void)editSearchProviders:(id)sender
388 | {
389 | NSMutableArray *mutableSearchProviders = [NSMutableArray array];
390 | for (NSDictionary *provider in [SafariOmnibar sharedInstance].searchProviders)
391 | {
392 | [mutableSearchProviders addObject:[[provider mutableCopy] autorelease]];
393 | }
394 | SearchProvidersEditorWindowController *editor = [[SearchProvidersEditorWindowController alloc] initWithSearchProviders:mutableSearchProviders];
395 | [[NSApplication sharedApplication] beginSheet:editor.window
396 | modalForWindow:[[NSApplication sharedApplication] keyWindow]
397 | modalDelegate:self
398 | didEndSelector:@selector(didEndSheet:returnCode:contextInfo:)
399 | contextInfo:editor];
400 | }
401 |
402 | - (void)didEndSheet:(NSWindow *)sheet returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo
403 | {
404 | SearchProvidersEditorWindowController *editor = contextInfo;
405 | [self saveSearchProviders:editor.searchProviders];
406 | [self loadSearchProviders];
407 | [sheet orderOut:self];
408 | [editor autorelease];
409 | }
410 |
411 | - (id)init
412 | {
413 | if ((self = [super init]))
414 | {
415 | locationFieldContext = [[NSMutableDictionary alloc] init];
416 | [self loadApplicationDefaults];
417 | [self loadSearchProviders];
418 |
419 | for (NSWindow *window in [[NSApplication sharedApplication] windows])
420 | {
421 | [self initBrowserWindow:window];
422 | }
423 |
424 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onNewWindow:) name:@"NSWindowDidBecomeMainNotification" object:nil];
425 |
426 | if (NSClassFromString(@"BrowserWindowControllerMac"))
427 | {
428 | // Safari 5.1
429 | [NSClassFromString(@"BrowserWindowControllerMac") jr_swizzleMethod:@selector(goToToolbarLocation:)
430 | withMethod:@selector(SafariOmnibar_goToToolbarLocation:) error:NULL];
431 | }
432 | else
433 | {
434 | // Safari 5.0
435 | [NSClassFromString(@"BrowserWindowController") jr_swizzleMethod:@selector(goToToolbarLocation:)
436 | withMethod:@selector(SafariOmnibar_goToToolbarLocation:) error:NULL];
437 | }
438 |
439 | [NSClassFromString(@"BrowserDocument") jr_swizzleMethod:@selector(searchWeb:)
440 | withMethod:@selector(SafariOmnibar_searchWeb:) error:NULL];
441 | [NSClassFromString(@"BrowserDocument") jr_swizzleMethod:@selector(openLocation:)
442 | withMethod:@selector(SafariOmnibar_openLocation:) error:NULL];
443 |
444 |
445 | [SparkleHelper initUpdater];
446 | }
447 | return self;
448 | }
449 |
450 | - (void)dealloc
451 | {
452 | [[NSNotificationCenter defaultCenter] removeObserver:self];
453 | [editSearchProvidersItem release], editSearchProvidersItem = nil;
454 | [locationFieldContext release], locationFieldContext = nil;
455 | [defaultSearchProvider release], defaultSearchProvider = nil;
456 | [searchProviders release], searchProviders = nil;
457 | [super dealloc];
458 | }
459 |
460 | + (NSString *)pluginVersion
461 | {
462 | return [[[NSBundle bundleForClass:self] infoDictionary] objectForKey:@"CFBundleVersion"];
463 | }
464 |
465 | + (SafariOmnibar *)sharedInstance
466 | {
467 | static SafariOmnibar *plugin = nil;
468 |
469 | if (plugin == nil)
470 | plugin = [[SafariOmnibar alloc] init];
471 |
472 | return plugin;
473 | }
474 |
475 | + (void)load
476 | {
477 | [self sharedInstance];
478 | NSLog(@"Safari Omnibar %@ Loaded", self.pluginVersion);
479 | }
480 |
481 | @end
482 |
--------------------------------------------------------------------------------
/SafariOmnibar/SearchProviders.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SearchProvidersList
6 |
7 |
8 | Name
9 | Google
10 | Keyword
11 | g
12 | Default
13 |
14 | SearchURLTemplate
15 | http://www.google.com/search?client=safari&rls=en&q={searchTerms}&ie=UTF-8&oe=UTF-8
16 |
17 |
18 | Name
19 | Google Image
20 | Keyword
21 | image
22 | Default
23 |
24 | SearchURLTemplate
25 | http://images.google.com/images?hl=en&source=hp&q={searchTerms}&btnG=Search+Images&gbv=2&aq=f&oq=&aqi=
26 |
27 |
28 | Name
29 | DuckDuckGo
30 | Keyword
31 | ddg
32 | Default
33 |
34 | SearchURLTemplate
35 | https://duckduckgo.com/?q={searchTerms}&t=safariomnibar
36 |
37 |
38 | Name
39 | Wikipedia
40 | Keyword
41 | w
42 | Default
43 |
44 | SearchURLTemplate
45 | http://en.wikipedia.org/w/index.php?title=Special:Search&search={searchTerms}
46 |
47 |
48 | Name
49 | Dailymotion
50 | Keyword
51 | video
52 | Default
53 |
54 | SearchURLTemplate
55 | http://www.dailymotion.com?search={searchTerms}
56 |
57 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/SafariOmnibar/SearchProvidersEditor.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 1070
5 | 11B26
6 | 1617
7 | 1138
8 | 566.00
9 |
13 |
29 |
33 |
40 |
41 | YES
42 |
43 | SearchProvidersEditorWindowController
44 |
45 |
46 | FirstResponder
47 |
48 |
49 | NSApplication
50 |
51 |
52 | YES
53 |
54 | YES
55 | YES
56 | YES
57 | YES
58 | YES
59 |
60 |
61 | 31
62 | 2
63 | {{139, 81}, {480, 259}}
64 | -1535638528
65 | Window
66 | NSPanel
67 |
68 |
69 |
70 |
71 | 256
72 |
73 | YES
74 |
75 |
76 | 266
77 | {{17, 222}, {446, 17}}
78 |
79 |
80 |
81 | _NS:3936
82 | YES
83 |
84 | 68288064
85 | 272630784
86 | Edit Search Providers
87 |
88 | LucidaGrande-Bold
89 | 13
90 | 2072
91 |
92 | _NS:3936
93 |
94 |
95 | 6
96 | System
97 | controlColor
98 |
99 | 3
100 | MC42NjY2NjY2NjY3AA
101 |
102 |
103 |
104 | 6
105 | System
106 | controlTextColor
107 |
108 | 3
109 | MAA
110 |
111 |
112 |
113 |
114 |
115 |
116 | 274
117 |
118 | YES
119 |
120 |
121 | 2304
122 |
123 | YES
124 |
125 |
126 | 256
127 | {438, 147}
128 |
129 |
130 |
131 | _NS:1197
132 | YES
133 |
142 |
143 |
144 | -2147483392
145 | {{224, 0}, {16, 17}}
146 | _NS:1202
147 |
148 |
149 | YES
150 |
151 | 101
152 | 40
153 | 1000
154 |
174 |
175 | 337772096
176 | 2048
177 | Text Cell
178 |
179 | LucidaGrande
180 | 13
181 | 1044
182 |
183 |
184 |
185 | 6
186 | System
187 | controlBackgroundColor
188 |
189 |
190 |
191 |
192 | 3
193 | YES
194 | YES
195 |
196 |
197 |
198 | 66
199 | 40
200 | 1000
201 |
209 |
210 | 337772096
211 | 2048
212 | Text Cell
213 |
214 |
215 |
216 |
217 |
218 | 3
219 | YES
220 | YES
221 |
222 |
223 |
224 | 262
225 | 10
226 | 3.4028234663852886e+38
227 |
243 |
244 | 337772096
245 | 2048
246 | Text Cell
247 |
248 |
249 |
250 |
251 |
252 | 3
253 | YES
254 | YES
255 |
256 |
257 |
258 | 3
259 | 2
260 |
261 |
262 | 6
263 | System
264 | gridColor
265 |
266 | 3
267 | MC41AA
268 |
269 |
270 | 17
271 | 1447034880
272 |
273 |
274 | 4
275 | 15
276 | 0
277 | YES
278 | 1
279 | 1
280 |
281 |
282 | {{1, 17}, {438, 147}}
283 |
284 |
285 |
286 | _NS:1195
287 |
288 |
289 | 4
290 |
291 |
292 |
293 | -2147483392
294 | {{224, 17}, {15, 102}}
295 |
296 |
297 |
298 | _NS:1214
299 |
300 | _doScroller:
301 | 0.9932432432432432
302 |
303 |
304 |
305 | -2147483392
306 | {{1, 189}, {438, 15}}
307 |
308 |
309 |
310 | _NS:1216
311 | 1
312 |
313 | _doScroller:
314 | 0.99772209567198178
315 |
316 |
317 |
318 | 2304
319 |
320 | YES
321 |
322 |
323 | {{1, 0}, {438, 17}}
324 |
325 |
326 |
327 |
328 |
329 | 4
330 |
331 |
332 | {{20, 49}, {440, 165}}
333 |
334 |
335 |
336 | _NS:1193
337 | 133682
338 |
339 |
340 |
341 |
342 | QSAAAEEgAABBmAAAQZgAAA
343 |
344 |
345 |
346 | 289
347 | {{374, 13}, {92, 32}}
348 |
349 |
350 |
351 | _NS:161
352 | YES
353 |
354 | 67239424
355 | 134217728
356 | Done
357 |
358 | _NS:161
359 |
360 | -2038284033
361 | 129
362 |
363 | DQ
364 | 200
365 | 25
366 |
367 |
368 |
369 |
370 | 292
371 | {{77, 13}, {127, 32}}
372 |
373 |
374 |
375 | _NS:161
376 | YES
377 |
378 | 67239424
379 | 134217728
380 | Set as Default
381 |
382 | _NS:161
383 |
384 | -2038284033
385 | 129
386 |
387 |
388 | 200
389 | 25
390 |
391 |
392 |
393 |
394 | 292
395 | {{20, 19}, {28, 23}}
396 |
397 |
398 |
399 | _NS:1566
400 | YES
401 |
402 | -2080244224
403 | 134217728
404 |
405 |
406 | _NS:1566
407 |
408 | -2033434369
409 | 162
410 |
411 | NSImage
412 | NSAddTemplate
413 |
414 |
415 |
416 | 400
417 | 75
418 |
419 |
420 |
421 |
422 | 292
423 | {{47, 19}, {28, 23}}
424 |
425 |
426 |
427 | _NS:1566
428 | YES
429 |
430 | -2080244224
431 | 134217728
432 |
433 |
434 | _NS:1566
435 |
436 | -2033434369
437 | 162
438 |
439 | NSImage
440 | NSRemoveTemplate
441 |
442 |
443 |
444 | 400
445 | 75
446 |
447 |
448 |
449 | {480, 259}
450 |
451 |
452 |
453 | _NS:2837
454 |
455 | {{0, 0}, {1920, 1178}}
456 | {10000000000000, 10000000000000}
457 | OmnibarEditor
458 | YES
459 |
460 |
461 |
462 |
463 | YES
464 |
465 |
466 | contentArray: searchProviders
467 |
468 |
469 |
470 |
471 |
472 | contentArray: searchProviders
473 | contentArray
474 | searchProviders
475 | 2
476 |
477 |
478 | 21
479 |
480 |
481 |
482 | content: arrangedObjects
483 |
484 |
485 |
486 |
487 |
488 | content: arrangedObjects
489 | content
490 | arrangedObjects
491 | 2
492 |
493 |
494 | 61
495 |
496 |
497 |
498 | selectionIndexes: selectionIndexes
499 |
500 |
501 |
502 |
503 |
504 | selectionIndexes: selectionIndexes
505 | selectionIndexes
506 | selectionIndexes
507 |
508 | 2
509 |
510 |
511 | 62
512 |
513 |
514 |
515 | sortDescriptors: sortDescriptors
516 |
517 |
518 |
519 |
520 |
521 | sortDescriptors: sortDescriptors
522 | sortDescriptors
523 | sortDescriptors
524 |
525 | 2
526 |
527 |
528 | 63
529 |
530 |
531 |
532 | value: arrangedObjects.SearchURLTemplate
533 |
534 |
535 |
536 |
537 |
538 | value: arrangedObjects.SearchURLTemplate
539 | value
540 | arrangedObjects.SearchURLTemplate
541 | 2
542 |
543 |
544 | 64
545 |
546 |
547 |
548 | value: arrangedObjects.Name
549 |
550 |
551 |
552 |
553 |
554 | value: arrangedObjects.Name
555 | value
556 | arrangedObjects.Name
557 | 2
558 |
559 |
560 | 65
561 |
562 |
563 |
564 | value: arrangedObjects.Keyword
565 |
566 |
567 |
568 |
569 |
570 | value: arrangedObjects.Keyword
571 | value
572 | arrangedObjects.Keyword
573 | 2
574 |
575 |
576 | 67
577 |
578 |
579 |
580 | dismiss:
581 |
582 |
583 |
584 | 68
585 |
586 |
587 |
588 | window
589 |
590 |
591 |
592 | 69
593 |
594 |
595 |
596 | enabled: selection.Default
597 |
598 |
599 |
600 |
601 |
602 | enabled: selection.Default
603 | enabled
604 | selection.Default
605 |
606 | NSValueTransformerName
607 | NSNegateBoolean
608 |
609 | 2
610 |
611 |
612 | 75
613 |
614 |
615 |
616 | fontBold: arrangedObjects.Default
617 |
618 |
619 |
620 |
621 |
622 | fontBold: arrangedObjects.Default
623 | fontBold
624 | arrangedObjects.Default
625 | 2
626 |
627 |
628 | 77
629 |
630 |
631 |
632 | setSelectedProviderAsDefault:
633 |
634 |
635 |
636 | 78
637 |
638 |
639 |
640 | arrayController
641 |
642 |
643 |
644 | 79
645 |
646 |
647 |
648 | tableView
649 |
650 |
651 |
652 | 84
653 |
654 |
655 |
656 | addSearchProvider:
657 |
658 |
659 |
660 | 85
661 |
662 |
663 |
664 | removeSearchProvider:
665 |
666 |
667 |
668 | 86
669 |
670 |
671 |
672 |
673 | YES
674 |
675 | 0
676 |
677 |
678 |
679 |
680 |
681 | -2
682 |
683 |
684 | File's Owner
685 |
686 |
687 | -1
688 |
689 |
690 | First Responder
691 |
692 |
693 | -3
694 |
695 |
696 | Application
697 |
698 |
699 | 16
700 |
701 |
702 |
703 |
704 | 42
705 |
706 |
707 | YES
708 |
709 |
710 |
711 |
712 |
713 | 43
714 |
715 |
716 | YES
717 |
718 |
719 |
720 |
721 |
722 |
723 |
724 |
725 |
726 |
727 | 44
728 |
729 |
730 | YES
731 |
732 |
733 |
734 |
735 |
736 | 45
737 |
738 |
739 | YES
740 |
741 |
742 |
743 |
744 |
745 |
746 |
747 |
748 | 46
749 |
750 |
751 | YES
752 |
753 |
754 |
755 |
756 |
757 | 47
758 |
759 |
760 |
761 |
762 | 48
763 |
764 |
765 | YES
766 |
767 |
768 |
769 |
770 |
771 |
772 |
773 | 49
774 |
775 |
776 |
777 |
778 | 51
779 |
780 |
781 |
782 |
783 | 53
784 |
785 |
786 | YES
787 |
788 |
789 |
790 |
791 |
792 | 54
793 |
794 |
795 | YES
796 |
797 |
798 |
799 |
800 |
801 | 55
802 |
803 |
804 | YES
805 |
806 |
807 |
808 |
809 |
810 | 56
811 |
812 |
813 |
814 |
815 | 57
816 |
817 |
818 |
819 |
820 | 58
821 |
822 |
823 |
824 |
825 | 60
826 |
827 |
828 |
829 |
830 | 70
831 |
832 |
833 | YES
834 |
835 |
836 |
837 |
838 |
839 | 71
840 |
841 |
842 |
843 |
844 | 80
845 |
846 |
847 | YES
848 |
849 |
850 |
851 |
852 |
853 | 81
854 |
855 |
856 |
857 |
858 | 82
859 |
860 |
861 | YES
862 |
863 |
864 |
865 |
866 |
867 | 83
868 |
869 |
870 |
871 |
872 | 87
873 |
874 |
875 |
876 |
877 |
878 |
879 | YES
880 |
881 | YES
882 | -1.IBPluginDependency
883 | -2.IBPluginDependency
884 | -3.IBPluginDependency
885 | 16.IBPluginDependency
886 | 42.IBPluginDependency
887 | 42.NSWindowTemplate.visibleAtLaunch
888 | 43.IBPluginDependency
889 | 44.IBPluginDependency
890 | 45.IBPluginDependency
891 | 46.IBPluginDependency
892 | 47.IBPluginDependency
893 | 48.IBPluginDependency
894 | 49.IBPluginDependency
895 | 51.IBPluginDependency
896 | 53.IBPluginDependency
897 | 54.IBPluginDependency
898 | 55.IBPluginDependency
899 | 56.IBPluginDependency
900 | 57.IBPluginDependency
901 | 58.IBPluginDependency
902 | 60.IBPluginDependency
903 | 70.IBPluginDependency
904 | 71.IBPluginDependency
905 | 80.IBPluginDependency
906 | 81.IBPluginDependency
907 | 82.IBPluginDependency
908 | 83.IBPluginDependency
909 | 87.IBPluginDependency
910 |
911 |
912 | YES
913 | com.apple.InterfaceBuilder.CocoaPlugin
914 | com.apple.InterfaceBuilder.CocoaPlugin
915 | com.apple.InterfaceBuilder.CocoaPlugin
916 | com.apple.InterfaceBuilder.CocoaPlugin
917 | com.apple.InterfaceBuilder.CocoaPlugin
918 |
919 | com.apple.InterfaceBuilder.CocoaPlugin
920 | com.apple.InterfaceBuilder.CocoaPlugin
921 | com.apple.InterfaceBuilder.CocoaPlugin
922 | com.apple.InterfaceBuilder.CocoaPlugin
923 | com.apple.InterfaceBuilder.CocoaPlugin
924 | com.apple.InterfaceBuilder.CocoaPlugin
925 | com.apple.InterfaceBuilder.CocoaPlugin
926 | com.apple.InterfaceBuilder.CocoaPlugin
927 | com.apple.InterfaceBuilder.CocoaPlugin
928 | com.apple.InterfaceBuilder.CocoaPlugin
929 | com.apple.InterfaceBuilder.CocoaPlugin
930 | com.apple.InterfaceBuilder.CocoaPlugin
931 | com.apple.InterfaceBuilder.CocoaPlugin
932 | com.apple.InterfaceBuilder.CocoaPlugin
933 | com.apple.InterfaceBuilder.CocoaPlugin
934 | com.apple.InterfaceBuilder.CocoaPlugin
935 | com.apple.InterfaceBuilder.CocoaPlugin
936 | com.apple.InterfaceBuilder.CocoaPlugin
937 | com.apple.InterfaceBuilder.CocoaPlugin
938 | com.apple.InterfaceBuilder.CocoaPlugin
939 | com.apple.InterfaceBuilder.CocoaPlugin
940 | com.apple.InterfaceBuilder.CocoaPlugin
941 |
942 |
943 |
944 | YES
945 |
946 |
947 |
948 |
949 |
950 | YES
951 |
952 |
953 |
954 |
955 | 87
956 |
957 |
958 |
959 | YES
960 |
961 | SearchProvidersEditorWindowController
962 | NSWindowController
963 |
964 | YES
965 |
966 | YES
967 | addSearchProvider:
968 | dismiss:
969 | removeSearchProvider:
970 | setSelectedProviderAsDefault:
971 |
972 |
973 | YES
974 | id
975 | id
976 | id
977 | id
978 |
979 |
980 |
981 | YES
982 |
983 | YES
984 | addSearchProvider:
985 | dismiss:
986 | removeSearchProvider:
987 | setSelectedProviderAsDefault:
988 |
989 |
990 | YES
991 |
992 | addSearchProvider:
993 | id
994 |
995 |
996 | dismiss:
997 | id
998 |
999 |
1000 | removeSearchProvider:
1001 | id
1002 |
1003 |
1004 | setSelectedProviderAsDefault:
1005 | id
1006 |
1007 |
1008 |
1009 |
1010 | YES
1011 |
1012 | YES
1013 | arrayController
1014 | tableView
1015 |
1016 |
1017 | YES
1018 | NSArrayController
1019 | NSTableView
1020 |
1021 |
1022 |
1023 | YES
1024 |
1025 | YES
1026 | arrayController
1027 | tableView
1028 |
1029 |
1030 | YES
1031 |
1032 | arrayController
1033 | NSArrayController
1034 |
1035 |
1036 | tableView
1037 | NSTableView
1038 |
1039 |
1040 |
1041 |
1042 | IBProjectSource
1043 | ./Classes/SearchProvidersEditorWindowController.h
1044 |
1045 |
1046 |
1047 |
1048 | 0
1049 | IBCocoaFramework
1050 |
1051 | com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3
1052 |
1053 |
1054 | YES
1055 | 3
1056 |
1057 | YES
1058 |
1059 | YES
1060 | NSAddTemplate
1061 | NSRemoveTemplate
1062 |
1063 |
1064 | YES
1065 | {8, 8}
1066 | {8, 8}
1067 |
1068 |
1069 |
1070 |
1071 |
--------------------------------------------------------------------------------
/SafariOmnibar/SearchProvidersEditorWindowController.h:
--------------------------------------------------------------------------------
1 | //
2 | // SearchProvidersEditorWindowController.h
3 | // SafariOmnibar
4 | //
5 | // Created by Nolan Waite on 11-07-23.
6 | //
7 |
8 | #import
9 |
10 | @interface SearchProvidersEditorWindowController : NSWindowController
11 | {
12 | NSMutableArray *searchProviders;
13 | NSArrayController *arrayController;
14 | NSTableView *tableView;
15 | }
16 |
17 | @property (nonatomic, readonly, copy) NSMutableArray *searchProviders;
18 | @property (nonatomic, retain) IBOutlet NSArrayController *arrayController;
19 | @property (nonatomic, retain) IBOutlet NSTableView *tableView;
20 |
21 | - (id)initWithSearchProviders:(NSArray *)searchProviders;
22 |
23 | - (IBAction)addSearchProvider:(id)sender;
24 | - (IBAction)removeSearchProvider:(id)sender;
25 | - (IBAction)setSelectedProviderAsDefault:(id)sender;
26 | - (IBAction)dismiss:(id)sender;
27 |
28 | @end
29 |
--------------------------------------------------------------------------------
/SafariOmnibar/SearchProvidersEditorWindowController.m:
--------------------------------------------------------------------------------
1 | //
2 | // SearchProvidersEditorWindowController.m
3 | // SafariOmnibar
4 | //
5 | // Created by Nolan Waite on 11-07-23.
6 | //
7 |
8 | #import "SearchProvidersEditorWindowController.h"
9 |
10 | @implementation SearchProvidersEditorWindowController
11 |
12 | @synthesize searchProviders;
13 | @synthesize arrayController;
14 | @synthesize tableView;
15 |
16 | - (id)initWithSearchProviders:(NSArray *)someSearchProviders
17 | {
18 | if ((self = [super initWithWindowNibName:@"SearchProvidersEditor"]))
19 | {
20 | searchProviders = [someSearchProviders mutableCopy];
21 | }
22 | return self;
23 | }
24 |
25 | static NSString *FirstHTTPURLStringOnGeneralPasteboard()
26 | {
27 | NSPasteboard *generalPasteboard = [NSPasteboard generalPasteboard];
28 | NSArray *copiedStrings = [generalPasteboard readObjectsForClasses:[NSArray arrayWithObject:[NSString class]] options:nil];
29 | for (NSString *maybeURLString in copiedStrings)
30 | {
31 | if ([maybeURLString hasPrefix:@"http"]) return maybeURLString;
32 | }
33 | return nil;
34 | }
35 |
36 | - (IBAction)addSearchProvider:(id)sender
37 | {
38 | NSMutableDictionary *newProvider = [NSMutableDictionary dictionaryWithObjectsAndKeys:@"New Provider", @"Name", @"new", @"Keyword", @"http://example.com/search?q={searchTerms}", @"SearchURLTemplate", nil];
39 | NSString *copiedURLString = FirstHTTPURLStringOnGeneralPasteboard();
40 | if (copiedURLString != nil)
41 | {
42 | [newProvider setObject:copiedURLString forKey:@"SearchURLTemplate"];
43 | }
44 | [self.arrayController addObject:newProvider];
45 | [self.tableView editColumn:0 row:([self.searchProviders count] - 1) withEvent:nil select:YES];
46 | }
47 |
48 | - (IBAction)removeSearchProvider:(id)sender
49 | {
50 | if ([self.searchProviders count] < 2) return;
51 | BOOL wasDefault = [[self.arrayController.selection valueForKey:@"Default"] boolValue];
52 | [self.arrayController removeObjects:self.arrayController.selectedObjects];
53 | if (wasDefault)
54 | {
55 | [self setSelectedProviderAsDefault:nil];
56 | }
57 | }
58 |
59 | - (IBAction)setSelectedProviderAsDefault:(id)sender
60 | {
61 | [self.arrayController.arrangedObjects setValue:[NSNumber numberWithBool:NO] forKey:@"Default"];
62 | [self.arrayController.selectedObjects setValue:[NSNumber numberWithBool:YES] forKey:@"Default"];
63 | }
64 |
65 | - (IBAction)dismiss:(id)sender
66 | {
67 | [[NSApplication sharedApplication] endSheet:self.window];
68 | }
69 |
70 | - (void)dealloc
71 | {
72 | [tableView release], tableView = nil;
73 | [arrayController release], arrayController = nil;
74 | [searchProviders release], searchProviders = nil;
75 | [super dealloc];
76 | }
77 |
78 | @end
79 |
--------------------------------------------------------------------------------
/SafariOmnibar/SparkleHelper.h:
--------------------------------------------------------------------------------
1 | //
2 | // SparkleHelper.h
3 | // SafariOmnibar
4 | //
5 | // Created by Olivier Poitrey on 02/08/11.
6 | // Copyright 2011 Olivier Poitrey. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface SparkleHelper : NSObject
12 |
13 | + (void)initUpdater;
14 |
15 | @end
16 |
--------------------------------------------------------------------------------
/SafariOmnibar/SparkleHelper.m:
--------------------------------------------------------------------------------
1 | //
2 | // SparkleHelper.m
3 | // SafariOmnibar
4 | //
5 | // Created by Olivier Poitrey on 02/08/11.
6 | // Copyright 2011 Olivier Poitrey. All rights reserved.
7 | //
8 |
9 | #import "SparkleHelper.h"
10 |
11 | @implementation SparkleHelper
12 |
13 | + (void)initUpdater
14 | {
15 | if (self != SparkleHelper.class) return;
16 |
17 | Class SUUpdater_class = NSClassFromString(@"SUUpdater");
18 | if (SUUpdater_class == Nil)
19 | {
20 | // Only load Sparkle if another bundle hasn't yet (i.e. WebKit or other SIMBL plugins)
21 | // Loading different versions of a framework is a Bad Idea
22 | NSString *sparklePath = [[[NSBundle bundleForClass:self] bundlePath] stringByAppendingString:@"/Contents/Frameworks/Sparkle.framework"];
23 | [[NSBundle bundleWithPath:sparklePath] load];
24 | SUUpdater_class = NSClassFromString(@"SUUpdater");
25 | }
26 |
27 | id updater = nil;
28 | if ([SUUpdater_class respondsToSelector:@selector(updaterForBundle:)])
29 | {
30 | updater = [SUUpdater_class performSelector:@selector(updaterForBundle:) withObject:[NSBundle bundleForClass:self]];
31 | }
32 |
33 | if (updater)
34 | {
35 | [updater setDelegate:self];
36 | if ([updater respondsToSelector:@selector(applicationDidFinishLaunching:)])
37 | {
38 | [updater performSelector:@selector(applicationDidFinishLaunching:) withObject:nil];
39 | }
40 | if ([updater respondsToSelector:@selector(resetUpdateCycle)])
41 | {
42 | [updater performSelector:@selector(resetUpdateCycle) withObject:nil];
43 | }
44 | }
45 | }
46 |
47 | + (NSString *)pathToRelaunchForUpdater:(id)updater
48 | {
49 | return [[NSBundle mainBundle] bundlePath];
50 | }
51 |
52 | @end
53 |
--------------------------------------------------------------------------------
/SafariOmnibar/en.lproj/InfoPlist.strings:
--------------------------------------------------------------------------------
1 | /* Localized versions of Info.plist keys */
2 |
3 |
--------------------------------------------------------------------------------