Skip to content
This repository has been archived by the owner on May 10, 2024. It is now read-only.

Commit

Permalink
Fix #627 Add brave://search URL scheme (#3582)
Browse files Browse the repository at this point in the history
Co-authored-by: Kacper Wybranski <[email protected]>
  • Loading branch information
KacperWybranski and Kacper Wybranski authored Jun 21, 2021
1 parent ebfac37 commit 37695cd
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 20 deletions.
62 changes: 43 additions & 19 deletions BraveShareTo/ShareToBraveViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,47 @@ import MobileCoreServices
import BraveShared

class ShareToBraveViewController: SLComposeServiceViewController {
private struct Scheme {
private enum SchemeType {
case url, query
}

private let type: SchemeType
private let urlOrQuery: String

init?(item: NSSecureCoding) {
if let text = item as? String {
urlOrQuery = text
type = .query
} else if let url = (item as? URL)?.absoluteString.firstURL?.absoluteString {
urlOrQuery = url
type = .url
} else {
return nil
}
}

var schemeUrl: URL? {
var components = URLComponents()
let queryItem: URLQueryItem

components.scheme = "brave"

switch type {
case .url:
components.host = "open-url"
queryItem = URLQueryItem(name: "url", value: urlOrQuery)
case .query:
components.host = "search"
queryItem = URLQueryItem(name: "q", value: urlOrQuery)
}

components.queryItems = [queryItem]
return components.url
}
}

// TODO: Separate scheme for debug builds, so it can be tested without need to uninstall production app.
private func urlScheme(for url: String) -> URL? {
return URL(string: "brave://open-url?url=\(url)")
}

override func configurationItems() -> [Any]! {
guard let inputItems = extensionContext?.inputItems as? [NSExtensionItem] else {
Expand All @@ -34,24 +70,12 @@ class ShareToBraveViewController: SLComposeServiceViewController {
}

provider.loadItem(of: provider.isUrl ? kUTTypeURL : kUTTypeText) { item, error in
var urlItem: URL?

// We can get urls from other apps as a kUTTypeText type, for example from Apple's mail.app.
if let text = item as? String {
urlItem = text.firstURL
} else if let url = item as? URL {
urlItem = url.absoluteString.firstURL
} else {
guard let item = item, let schemeUrl = Scheme(item: item)?.schemeUrl else {
self.cancel()
return
}

// Just open the app if we don't find a url. In the future we could
// use this entry point to search instead of open a given URL
let urlString = urlItem?.absoluteString ?? ""
if let braveUrl = urlString.addingPercentEncoding(withAllowedCharacters: .alphanumerics).flatMap(self.urlScheme) {
self.handleUrl(braveUrl)
}
}

self.handleUrl(schemeUrl)
}

return []
Expand Down
3 changes: 3 additions & 0 deletions Client/Application/NavigationRouter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ enum NavigationPath: Equatable {
} else if urlString.starts(with: "\(scheme)://open-text") {
let text = components.valueForQuery("text")
self = .text(text ?? "")
} else if urlString.starts(with: "\(scheme)://search") {
let text = components.valueForQuery("q")
self = .text(text ?? "")
} else {
return nil
}
Expand Down
2 changes: 1 addition & 1 deletion Client/Frontend/Browser/BrowserViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1560,7 +1560,7 @@ class BrowserViewController: UIViewController {
// This let's the user spam the Cmd+T button without lots of responder changes.
guard freshTab == self.tabManager.selectedTab else { return }
if let text = searchText {
self.topToolbar.setLocation(text, search: true)
self.topToolbar.submitLocation(text)
}
}
}
Expand Down
9 changes: 9 additions & 0 deletions Client/Frontend/Browser/Toolbars/UrlBar/TopToolbarView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,15 @@ class TopToolbarView: UIView, ToolbarProtocol {
}
}

func submitLocation(_ location: String?) {
locationTextField?.text = location
guard let text = location, !text.isEmpty else {
return
}
// Not notifying when empty agrees with AutocompleteTextField.textDidChange.
delegate?.topToolbar(self, didSubmitText: text)
}

func enterOverlayMode(_ locationText: String?, pasted: Bool, search: Bool) {
createLocationTextField()

Expand Down
8 changes: 8 additions & 0 deletions ClientTests/NavigationRouterTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,14 @@ class NavigationRouterTests: XCTestCase {
XCTAssertEqual(badNav, NavigationPath.url(webURL: URL(string: "blah"), isPrivate: false))
}

func testSearchScheme() {
let query = "Foo Bar".addingPercentEncoding(withAllowedCharacters: .alphanumerics)!
let appURL = "\(appScheme)://search?q="+query
let navItem = NavigationPath(url: URL(string: appURL)!)!

XCTAssertEqual(navItem, NavigationPath.text("Foo Bar"))
}

func testDefaultNavigationPath() {
let url = URL(string: "https://duckduckgo.com")!
let appURL = URL(string: "\(self.appScheme)://open-url?url=\(url.absoluteString.escape()!)")!
Expand Down

0 comments on commit 37695cd

Please sign in to comment.