From df2141d9e69da138b491122839780260e8548a80 Mon Sep 17 00:00:00 2001 From: Rita Zhang Date: Sun, 24 Apr 2016 22:17:01 -0700 Subject: [PATCH] :zap: Add API: IsDefaultProtocolClient --- atom/browser/api/atom_api_app.cc | 2 ++ atom/browser/browser.h | 3 +++ atom/browser/browser_linux.cc | 4 ++++ atom/browser/browser_mac.mm | 24 ++++++++++++++++++++++ atom/browser/browser_win.cc | 44 ++++++++++++++++++++++++++++++++++++++++ docs/api/app.md | 14 +++++++++++++ 6 files changed, 91 insertions(+) diff --git a/atom/browser/api/atom_api_app.cc b/atom/browser/api/atom_api_app.cc index ce20ce9..304e53a 100644 --- a/atom/browser/api/atom_api_app.cc +++ b/atom/browser/api/atom_api_app.cc @@ -451,6 +451,8 @@ void App::BuildPrototype( base::Bind(&Browser::ClearRecentDocuments, browser)) .SetMethod("setAppUserModelId", base::Bind(&Browser::SetAppUserModelID, browser)) + .SetMethod("isDefaultProtocolClient", + base::Bind(&Browser::IsDefaultProtocolClient, browser)) .SetMethod("setAsDefaultProtocolClient", base::Bind(&Browser::SetAsDefaultProtocolClient, browser)) .SetMethod("removeAsDefaultProtocolClient", diff --git a/atom/browser/browser.h b/atom/browser/browser.h index 0f1dbe9..8329b14 100644 --- a/atom/browser/browser.h +++ b/atom/browser/browser.h @@ -82,6 +82,9 @@ class Browser : public WindowListObserver { // Set as default handler for a protocol. bool SetAsDefaultProtocolClient(const std::string& protocol); + // Query the current state of default handler for a protocol. + bool IsDefaultProtocolClient(const std::string& protocol); + #if defined(OS_MACOSX) // Hide the application. void Hide(); diff --git a/atom/browser/browser_linux.cc b/atom/browser/browser_linux.cc index 6c7d4ab..d994bb4 100644 --- a/atom/browser/browser_linux.cc +++ b/atom/browser/browser_linux.cc @@ -42,6 +42,10 @@ bool Browser::SetAsDefaultProtocolClient(const std::string& protocol) { return false; } +bool Browser::IsDefaultProtocolClient(const std::string& protocol) { + return false; +} + std::string Browser::GetExecutableFileVersion() const { return brightray::GetApplicationVersion(); } diff --git a/atom/browser/browser_mac.mm b/atom/browser/browser_mac.mm index 11fd3aa..c10369a 100644 --- a/atom/browser/browser_mac.mm +++ b/atom/browser/browser_mac.mm @@ -60,6 +60,30 @@ bool Browser::SetAsDefaultProtocolClient(const std::string& protocol) { return return_code == noErr; } +bool Browser::IsDefaultProtocolClient(const std::string& protocol) { + if (protocol.empty()) + return false; + + NSString* identifier = [base::mac::MainBundle() bundleIdentifier]; + if (!identifier) + return false; + + NSString* protocol_ns = [NSString stringWithUTF8String:protocol.c_str()]; + + CFStringRef bundle = + LSCopyDefaultHandlerForURLScheme(base::mac::NSToCFCast(protocol_ns)); + NSString* bundleId = static_cast( + base::mac::CFTypeRefToNSObjectAutorelease(bundle)); + if (!bundleId) + return false; + + // Ensure the comparison is case-insensitive + // as LS does not persist the case of the bundle id. + NSComparisonResult result = + [bundleId caseInsensitiveCompare:identifier]; + return result == NSOrderedSame; +} + void Browser::SetAppUserModelID(const base::string16& name) { } diff --git a/atom/browser/browser_win.cc b/atom/browser/browser_win.cc index 9531406..7b1402b 100644 --- a/atom/browser/browser_win.cc +++ b/atom/browser/browser_win.cc @@ -225,6 +225,50 @@ bool Browser::SetAsDefaultProtocolClient(const std::string& protocol) { return true; } +bool Browser::IsDefaultProtocolClient(const std::string& protocol) { + if (protocol.empty()) + return false; + + base::FilePath path; + if (!PathService::Get(base::FILE_EXE, &path)) { + LOG(ERROR) << "Error getting app exe path"; + return false; + } + + // Main Registry Key + HKEY root = HKEY_CURRENT_USER; + std::string keyPathStr = "Software\\Classes\\" + protocol; + std::wstring keyPath = std::wstring(keyPathStr.begin(), keyPathStr.end()); + + // Command Key + std::string cmdPathStr = keyPathStr + "\\shell\\open\\command"; + std::wstring cmdPath = std::wstring(cmdPathStr.begin(), cmdPathStr.end()); + + base::win::RegKey key; + base::win::RegKey commandKey; + if (FAILED(key.Open(root, keyPath.c_str(), KEY_ALL_ACCESS))) + // Key doesn't exist, we can confirm that it is not set + return false; + + if (FAILED(commandKey.Open(root, cmdPath.c_str(), KEY_ALL_ACCESS))) + // Key doesn't exist, we can confirm that it is not set + return false; + + std::wstring keyVal; + if (FAILED(commandKey.ReadValue(L"", &keyVal))) + // Default value not set, we can confirm that it is not set + return false; + + std::wstring exePath(path.value()); + std::wstring exe = L"\"" + exePath + L"\" \"%1\""; + if (keyVal == exe) { + // Default value is the same as current file path + return true; + } else { + return false; + } +} + PCWSTR Browser::GetAppUserModelID() { if (app_user_model_id_.empty()) { SetAppUserModelID(base::ReplaceStringPlaceholders( diff --git a/docs/api/app.md b/docs/api/app.md index 0aca703..1f68293 100644 --- a/docs/api/app.md +++ b/docs/api/app.md @@ -384,6 +384,18 @@ This method checks if the current executable as the default handler for a protoc **Note:** On OS X, removing the app will automatically remove the app as the default protocol handler. +### `app.isDefaultProtocolClient(protocol)` _OS X_ _Windows_ + +* `protocol` String - The name of your protocol, without `://`. + +This method checks if the current executable is the default handler for a protocol +(aka URI scheme). If so, it will return true. Otherwise, it will return false. + +**Note:** On OS X, you can use this method to check if the app has been registered as the default protocol handler for a protocol. You can also verify this by checking `~/Library/Preferences/com.apple.LaunchServices.plist` on the OS X machine. +Please refer to [Apple's documentation][LSCopyDefaultHandlerForURLScheme] for details. + +The API uses the Windows Registry and LSCopyDefaultHandlerForURLScheme internally. + ### `app.setUserTasks(tasks)` _Windows_ * `tasks` Array - Array of `Task` objects @@ -556,3 +568,5 @@ Sets the `image` associated with this dock icon. [tasks]:http://msdn.microsoft.com/en-us/library/windows/desktop/dd378460(v=vs.85).aspx#tasks [app-user-model-id]: https://msdn.microsoft.com/en-us/library/windows/desktop/dd378459(v=vs.85).aspx [CFBundleURLTypes]: https://developer.apple.com/library/ios/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html#//apple_ref/doc/uid/TP40009249-102207-TPXREF115 +[LSCopyDefaultHandlerForURLScheme]: +https://developer.apple.com/library/mac/documentation/Carbon/Reference/LaunchServicesReference/#//apple_ref/c/func/LSCopyDefaultHandlerForURLScheme -- 2.7.4