Skip to content

Commit

Permalink
Merge pull request mozilla-mobile#86 from thebnich/search-default-fal…
Browse files Browse the repository at this point in the history
…lback

Bug 1120776 - Implement URIFixup with search fallback
  • Loading branch information
thebnich committed Jan 16, 2015
2 parents cb57217 + abdece5 commit fd2a9ae
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 13 deletions.
12 changes: 11 additions & 1 deletion Client.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,10 @@
D3968F251A38FE8500CEFD3B /* TabManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = D3968F241A38FE8500CEFD3B /* TabManager.swift */; };
D3A9949C1A3686BD008AD1AC /* BrowserViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D3A994951A3686BD008AD1AC /* BrowserViewController.swift */; };
D3A9949D1A3686BD008AD1AC /* Browser.swift in Sources */ = {isa = PBXBuildFile; fileRef = D3A994961A3686BD008AD1AC /* Browser.swift */; };
D3C744CD1A687D6C004CE85D /* URIFixup.swift in Sources */ = {isa = PBXBuildFile; fileRef = D3C744CC1A687D6C004CE85D /* URIFixup.swift */; };
D3C744CE1A687D6C004CE85D /* URIFixup.swift in Sources */ = {isa = PBXBuildFile; fileRef = D3C744CC1A687D6C004CE85D /* URIFixup.swift */; };
D3C744CF1A687D6C004CE85D /* URIFixup.swift in Sources */ = {isa = PBXBuildFile; fileRef = D3C744CC1A687D6C004CE85D /* URIFixup.swift */; };
D3C744D01A687D6C004CE85D /* URIFixup.swift in Sources */ = {isa = PBXBuildFile; fileRef = D3C744CC1A687D6C004CE85D /* URIFixup.swift */; };
D3FA777B1A43B2990010CD32 /* SearchTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D3FA777A1A43B2990010CD32 /* SearchTests.swift */; };
D3FA77971A43B5390010CD32 /* OpenSearch.swift in Sources */ = {isa = PBXBuildFile; fileRef = D3FA77831A43B2CE0010CD32 /* OpenSearch.swift */; };
D3FA77C41A44F9A80010CD32 /* Locales in Resources */ = {isa = PBXBuildFile; fileRef = D3FA77C31A44F9A80010CD32 /* Locales */; };
Expand Down Expand Up @@ -349,6 +353,7 @@
D3968F241A38FE8500CEFD3B /* TabManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TabManager.swift; sourceTree = "<group>"; };
D3A994951A3686BD008AD1AC /* BrowserViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BrowserViewController.swift; sourceTree = "<group>"; };
D3A994961A3686BD008AD1AC /* Browser.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Browser.swift; sourceTree = "<group>"; };
D3C744CC1A687D6C004CE85D /* URIFixup.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = URIFixup.swift; sourceTree = "<group>"; };
D3FA777A1A43B2990010CD32 /* SearchTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SearchTests.swift; sourceTree = "<group>"; };
D3FA77831A43B2CE0010CD32 /* OpenSearch.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OpenSearch.swift; sourceTree = "<group>"; };
D3FA77C31A44F9A80010CD32 /* Locales */ = {isa = PBXFileReference; lastKnownFileType = folder; path = Locales; sourceTree = "<group>"; };
Expand Down Expand Up @@ -566,9 +571,10 @@
D314E7F51A37B98700426A76 /* BrowserToolbar.swift */,
D3A994951A3686BD008AD1AC /* BrowserViewController.swift */,
D3FA77831A43B2CE0010CD32 /* OpenSearch.swift */,
D308E4E31A5306F500842685 /* SearchEngines.swift */,
D3968F241A38FE8500CEFD3B /* TabManager.swift */,
D301AAED1A3A55B70078DD1D /* TabTrayController.swift */,
D308E4E31A5306F500842685 /* SearchEngines.swift */,
D3C744CC1A687D6C004CE85D /* URIFixup.swift */,
);
path = Browser;
sourceTree = "<group>";
Expand Down Expand Up @@ -1146,6 +1152,7 @@
D34C5AF21A5E0C9800E0DF7B /* SWXMLHash.swift in Sources */,
D3968F251A38FE8500CEFD3B /* TabManager.swift in Sources */,
D3A9949D1A3686BD008AD1AC /* Browser.swift in Sources */,
D3C744CD1A687D6C004CE85D /* URIFixup.swift in Sources */,
F84B220D1A0910F600AAB793 /* ReaderViewController.swift in Sources */,
D3A9949C1A3686BD008AD1AC /* BrowserViewController.swift in Sources */,
E42CCE011A24C4E300B794D3 /* ExtensionUtils.swift in Sources */,
Expand Down Expand Up @@ -1177,6 +1184,7 @@
D3FA77971A43B5390010CD32 /* OpenSearch.swift in Sources */,
D3FA777B1A43B2990010CD32 /* SearchTests.swift in Sources */,
0B657B461A3B9CAB005A9E43 /* Favicon.swift in Sources */,
D3C744CE1A687D6C004CE85D /* URIFixup.swift in Sources */,
0BD19A6D1A2530C80084FBA7 /* ReaderViewController.swift in Sources */,
0BD19A641A2530750084FBA7 /* Panels.swift in Sources */,
0BD19A6E1A2530CE0084FBA7 /* SettingsViewController.swift in Sources */,
Expand All @@ -1203,6 +1211,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
D3C744CF1A687D6C004CE85D /* URIFixup.swift in Sources */,
0B79B18A1A3F6DE900DBECB3 /* Site.swift in Sources */,
E418D0DA1A251B3200CAE47A /* AccountManager.swift in Sources */,
0BD2C61D1A643B6000BB4BB9 /* Locking.swift in Sources */,
Expand Down Expand Up @@ -1232,6 +1241,7 @@
files = (
0B79B1891A3F6DE000DBECB3 /* Favicon.swift in Sources */,
282DA4691A68C13400A406E2 /* Clients.swift in Sources */,
D3C744D01A687D6C004CE85D /* URIFixup.swift in Sources */,
0B79B18B1A3F6DE900DBECB3 /* Site.swift in Sources */,
E42CCDEA1A23A74400B794D3 /* RestAPI.swift in Sources */,
D35179C11A5C8D6800E7622E /* OpenSearch.swift in Sources */,
Expand Down
35 changes: 35 additions & 0 deletions Client/Frontend/Browser/URIFixup.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

import Foundation

class URIFixup {
func getURL(entry: String) -> NSURL? {
let trimmed = entry.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet())
var url = NSURL(string: trimmed)

// First check if the URL includes a scheme. This will handle
// all valid requests starting with "http://", "about:", etc.
if url?.scheme != nil {
return url
}

// If there's no scheme, we're going to prepend "http://". First,
// make sure there's at least one "." in the host. This means
// we'll allow single-word searches (e.g., "foo") at the expense
// of breaking single-word hosts without a scheme (e.g., "localhost").
if trimmed.rangeOfString(".") == nil {
return nil
}

// If there is a ".", prepend "http://" and try again. Since this
// is strictly an "http://" URL, we also require a host.
url = NSURL(string: "http://\(trimmed)")
if url?.host != nil {
return url
}

return nil
}
}
25 changes: 13 additions & 12 deletions Client/Frontend/TabBar/TabBarViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ class TabBarViewController: UIViewController, UITextFieldDelegate, SearchViewCon
private var cancelButton: UIButton!
private var buttons: [ToolbarButton] = []
private var searchController: SearchViewController?
private let uriFixup = URIFixup()

override func viewWillDisappear(animated: Bool) {
NSNotificationCenter.defaultCenter().removeObserver(notificationToken)
Expand Down Expand Up @@ -241,18 +242,18 @@ class TabBarViewController: UIViewController, UITextFieldDelegate, SearchViewCon
}

func textFieldShouldReturn(textField: UITextField) -> Bool {
let urlString = toolbarTextField.text

// If the URL is missing a scheme then parse then we manually prefix it with http:// and try
// again. We can probably do some smarter things here but I think this is a
// decent start that at least lets people skip typing the protocol.
var url = NSURL(string: urlString)
if url == nil || url?.scheme == nil {
url = NSURL(string: "http://" + urlString)
if url == nil {
println("Error parsing URL: " + urlString)
return false
}
let text = toolbarTextField.text
var url = uriFixup.getURL(text)

// If we can't make a valid URL, do a search query.
if url == nil {
url = profile.searchEngines.defaultEngine.urlForQuery(text)
}

// If we still don't have a valid URL, something is broken. Give up.
if url == nil {
println("Error handling URL entry: " + text)
return false
}

delegate?.didEnterURL(url!)
Expand Down
30 changes: 30 additions & 0 deletions ClientTests/SearchTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import XCTest
let ExpectedEngines = ["Amazon.com", "Bing", "DuckDuckGo", "Google", "Twitter", "Wikipedia", "Yahoo"]

class SearchTests: XCTestCase {
private let uriFixup = URIFixup()

func testParsing() {
let parser = OpenSearchParser(pluginMode: true)
let file = NSBundle.mainBundle().pathForResource("google", ofType: "xml", inDirectory: "Locales/en-US/searchplugins")
Expand All @@ -30,4 +32,32 @@ class SearchTests: XCTestCase {
XCTAssertEqual(engine.shortName, ExpectedEngines[i])
}
}

func testURIFixup() {
// Check valid URLs. We can load these after some fixup.
checkValidURL("http://www.mozilla.org", afterFixup: "http://www.mozilla.org")
checkValidURL("about:", afterFixup: "about:")
checkValidURL("about:config", afterFixup: "about:config")
checkValidURL("file:///f/o/o", afterFixup: "file:///f/o/o")
checkValidURL("ftp://ftp.mozilla.org", afterFixup: "ftp://ftp.mozilla.org")
checkValidURL("foo.bar", afterFixup: "http://foo.bar")
checkValidURL(" foo.bar ", afterFixup: "http://foo.bar")
checkValidURL("1.2.3", afterFixup: "http://1.2.3")

// Check invalid URLs. These are passed along to the default search engine.
checkInvalidURL("foobar")
checkInvalidURL("foo bar")
checkInvalidURL("mozilla. org")
checkInvalidURL("about: config")
checkInvalidURL("123")
checkInvalidURL("a/b")
}

private func checkValidURL(beforeFixup: String, afterFixup: String) {
XCTAssertEqual(uriFixup.getURL(beforeFixup)!.absoluteString!, afterFixup)
}

private func checkInvalidURL(beforeFixup: String) {
XCTAssertNil(uriFixup.getURL(beforeFixup))
}
}

0 comments on commit fd2a9ae

Please sign in to comment.