diff --git a/src/modules/launcher/Plugins/Microsoft.Plugin.Program/Languages/de.xaml b/src/modules/launcher/Plugins/Microsoft.Plugin.Program/Languages/de.xaml
index cfcb43089d..58bcf7beaf 100644
--- a/src/modules/launcher/Plugins/Microsoft.Plugin.Program/Languages/de.xaml
+++ b/src/modules/launcher/Plugins/Microsoft.Plugin.Program/Languages/de.xaml
@@ -34,4 +34,9 @@
Programm
Suche Programme mit Wox
-
\ No newline at end of file
+
+ Win32-Anwendung
+ Weblink-Anwendung
+ Web-Anwendung
+
+
diff --git a/src/modules/launcher/Plugins/Microsoft.Plugin.Program/Languages/en.xaml b/src/modules/launcher/Plugins/Microsoft.Plugin.Program/Languages/en.xaml
index b7202d590f..2caa14067c 100644
--- a/src/modules/launcher/Plugins/Microsoft.Plugin.Program/Languages/en.xaml
+++ b/src/modules/launcher/Plugins/Microsoft.Plugin.Program/Languages/en.xaml
@@ -45,4 +45,8 @@
Success
Successfully disabled this program from displaying in your query
+
+ Win32 application
+ Internet shortcut application
+ Web application
\ No newline at end of file
diff --git a/src/modules/launcher/Plugins/Microsoft.Plugin.Program/Languages/ja.xaml b/src/modules/launcher/Plugins/Microsoft.Plugin.Program/Languages/ja.xaml
index 07630a1cda..364dc4e9b2 100644
--- a/src/modules/launcher/Plugins/Microsoft.Plugin.Program/Languages/ja.xaml
+++ b/src/modules/launcher/Plugins/Microsoft.Plugin.Program/Languages/ja.xaml
@@ -35,4 +35,9 @@
Program
Search programs in Wox
+
+ Win32 application
+ Internet shortcut application
+ Web application
+
\ No newline at end of file
diff --git a/src/modules/launcher/Plugins/Microsoft.Plugin.Program/Languages/pl.xaml b/src/modules/launcher/Plugins/Microsoft.Plugin.Program/Languages/pl.xaml
index bb82ee8d2e..b739a1d551 100644
--- a/src/modules/launcher/Plugins/Microsoft.Plugin.Program/Languages/pl.xaml
+++ b/src/modules/launcher/Plugins/Microsoft.Plugin.Program/Languages/pl.xaml
@@ -34,4 +34,9 @@
Programy
Szukaj i uruchamiaj programy z poziomu Woxa
+
+ Win32 application
+ Internet shortcut application
+ Web application
+
\ No newline at end of file
diff --git a/src/modules/launcher/Plugins/Microsoft.Plugin.Program/Languages/tr.xaml b/src/modules/launcher/Plugins/Microsoft.Plugin.Program/Languages/tr.xaml
index ef01e29fd1..e659da4876 100644
--- a/src/modules/launcher/Plugins/Microsoft.Plugin.Program/Languages/tr.xaml
+++ b/src/modules/launcher/Plugins/Microsoft.Plugin.Program/Languages/tr.xaml
@@ -36,4 +36,9 @@
Geçersiz Konum
+
+ Win32 application
+ Internet shortcut application
+ Web application
+
\ No newline at end of file
diff --git a/src/modules/launcher/Plugins/Microsoft.Plugin.Program/Languages/zh-cn.xaml b/src/modules/launcher/Plugins/Microsoft.Plugin.Program/Languages/zh-cn.xaml
index f41193095b..83acbe6148 100644
--- a/src/modules/launcher/Plugins/Microsoft.Plugin.Program/Languages/zh-cn.xaml
+++ b/src/modules/launcher/Plugins/Microsoft.Plugin.Program/Languages/zh-cn.xaml
@@ -36,4 +36,9 @@
无效路径
+
+ Win32 application
+ Internet shortcut application
+ Web application
+
\ No newline at end of file
diff --git a/src/modules/launcher/Plugins/Microsoft.Plugin.Program/Languages/zh-tw.xaml b/src/modules/launcher/Plugins/Microsoft.Plugin.Program/Languages/zh-tw.xaml
index d3c0f18cca..c424b7347a 100644
--- a/src/modules/launcher/Plugins/Microsoft.Plugin.Program/Languages/zh-tw.xaml
+++ b/src/modules/launcher/Plugins/Microsoft.Plugin.Program/Languages/zh-tw.xaml
@@ -33,4 +33,9 @@
程式
在 Wox 中搜尋程式
+
+
+ Win32 application
+ Internet shortcut application
+ Web application
diff --git a/src/modules/launcher/Plugins/Microsoft.Plugin.Program/Programs/ShellLinkHelper.cs b/src/modules/launcher/Plugins/Microsoft.Plugin.Program/Programs/ShellLinkHelper.cs
index 6d829d741c..5842a386de 100644
--- a/src/modules/launcher/Plugins/Microsoft.Plugin.Program/Programs/ShellLinkHelper.cs
+++ b/src/modules/launcher/Plugins/Microsoft.Plugin.Program/Programs/ShellLinkHelper.cs
@@ -103,6 +103,7 @@ namespace Microsoft.Plugin.Program.Programs
public String description = String.Empty;
// Sets to true if the program takes in arguments
+ public String Arguments = String.Empty;
public bool hasArguments = false;
// Retrieve the target path using Shell Link
@@ -130,6 +131,7 @@ namespace Microsoft.Plugin.Program.Programs
StringBuilder argumentBuffer = new StringBuilder(MAX_PATH);
((IShellLinkW)link).GetArguments(argumentBuffer, argumentBuffer.Capacity);
+ Arguments = argumentBuffer.ToString();
// Set variable to true if the program takes in any arguments
if (argumentBuffer.Length != 0)
diff --git a/src/modules/launcher/Plugins/Microsoft.Plugin.Program/Programs/Win32.cs b/src/modules/launcher/Plugins/Microsoft.Plugin.Program/Programs/Win32.cs
index a2875eb8a9..75f6ee46c4 100644
--- a/src/modules/launcher/Plugins/Microsoft.Plugin.Program/Programs/Win32.cs
+++ b/src/modules/launcher/Plugins/Microsoft.Plugin.Program/Programs/Win32.cs
@@ -31,16 +31,24 @@ namespace Microsoft.Plugin.Program.Programs
public bool Valid { get; set; }
public bool Enabled { get; set; }
public bool hasArguments { get; set; } = false;
+ public string Arguments { get; set; } = String.Empty;
public string Location => ParentDirectory;
- public string AppType { get; set; }
+ public uint AppType { get; set; }
private const string ShortcutExtension = "lnk";
private const string ApplicationReferenceExtension = "appref-ms";
private const string ExeExtension = "exe";
private const string InternetShortcutExtension = "url";
-
- private const string InternetShortcutApplication = "Internet shortcut application";
- private const string Win32Application = "Win32 application";
+
+ private const string proxyWebApp = "_proxy.exe";
+ private const string appIdArgument = "--app-id";
+
+ private enum ApplicationTypes
+ {
+ WEB_APPLICATION = 0,
+ INTERNET_SHORTCUT_APPLICATION = 1,
+ WIN32_APPLICATION = 2
+ }
private int Score(string query)
{
@@ -51,6 +59,68 @@ namespace Microsoft.Plugin.Program.Programs
return score;
}
+ public bool IsWebApplication()
+ {
+ // To Filter PWAs when the user searches for the main application
+ // All Chromium based applications contain the --app-id argument
+ // Reference : https://codereview.chromium.org/399045/show
+ bool isWebApplication = FullPath.Contains(proxyWebApp) && Arguments.Contains(appIdArgument);
+ return isWebApplication;
+ }
+
+ // Condition to Filter pinned Web Applications or PWAs when searching for the main application
+ public bool FilterWebApplication(string query)
+ {
+ // If the app is not a web application, then do not filter it
+ if(!IsWebApplication())
+ {
+ return false;
+ }
+
+ // Set the subtitle to 'Web Application'
+ AppType = (uint)ApplicationTypes.WEB_APPLICATION;
+
+ string[] subqueries = query.Split();
+ bool nameContainsQuery = false;
+ bool pathContainsQuery = false;
+
+ // check if any space separated query is a part of the app name or path name
+ foreach (var subquery in subqueries)
+ {
+ if (FullPath.Contains(subquery, StringComparison.OrdinalIgnoreCase))
+ {
+ pathContainsQuery = true;
+ }
+
+ if(Name.Contains(subquery, StringComparison.OrdinalIgnoreCase))
+ {
+ nameContainsQuery = true;
+ }
+ }
+ return pathContainsQuery && !nameContainsQuery;
+ }
+
+ // Function to set the subtitle based on the Type of application
+ public string SetSubtitle(uint AppType, IPublicAPI api)
+ {
+ if(AppType == (uint)ApplicationTypes.WIN32_APPLICATION)
+ {
+ return api.GetTranslation("powertoys_run_plugin_program_win32_application");
+ }
+ else if(AppType == (uint)ApplicationTypes.INTERNET_SHORTCUT_APPLICATION)
+ {
+ return api.GetTranslation("powertoys_run_plugin_program_internet_shortcut_application");
+ }
+ else if(AppType == (uint)ApplicationTypes.WEB_APPLICATION)
+ {
+ return api.GetTranslation("powertoys_run_plugin_program_web_application");
+ }
+ else
+ {
+ return String.Empty;
+ }
+ }
+
public Result Result(string query, IPublicAPI api)
{
var score = Score(query);
@@ -64,10 +134,18 @@ namespace Microsoft.Plugin.Program.Programs
var noArgumentScoreModifier = 5;
score += noArgumentScoreModifier;
}
+ else
+ {
+ // Filter Web Applications when searching for the main application
+ if (FilterWebApplication(query))
+ {
+ return null;
+ }
+ }
var result = new Result
{
- SubTitle = AppType,
+ SubTitle = SetSubtitle(AppType, api),
IcoPath = IcoPath,
Score = score,
ContextData = this,
@@ -105,7 +183,7 @@ namespace Microsoft.Plugin.Program.Programs
public List ContextMenus(IPublicAPI api)
{
// To add a context menu only to open file location as Internet shortcut applications do not have the functionality to run as admin
- if(AppType.Equals(InternetShortcutApplication))
+ if(AppType == (uint)ApplicationTypes.INTERNET_SHORTCUT_APPLICATION)
{
var contextMenuItems = new List
{
@@ -195,7 +273,7 @@ namespace Microsoft.Plugin.Program.Programs
Description = string.Empty,
Valid = true,
Enabled = true,
- AppType = Win32Application
+ AppType = (uint)ApplicationTypes.WIN32_APPLICATION
};
return p;
}
@@ -260,10 +338,9 @@ namespace Microsoft.Plugin.Program.Programs
FullPath = path.ToLower(),
UniqueIdentifier = path,
ParentDirectory = Directory.GetParent(path).FullName,
- Description = InternetShortcutApplication,
Valid = true,
Enabled = true,
- AppType = InternetShortcutApplication
+ AppType = (uint)ApplicationTypes.INTERNET_SHORTCUT_APPLICATION
};
return p;
}
@@ -295,6 +372,7 @@ namespace Microsoft.Plugin.Program.Programs
program.FullPath = Path.GetFullPath(target).ToLower();
program.ExecutableName = Path.GetFileName(target);
program.hasArguments = _helper.hasArguments;
+ program.Arguments = _helper.Arguments;
var description = _helper.description;
if (!string.IsNullOrEmpty(description))
diff --git a/src/modules/launcher/Wox.Test/Plugins/ProgramPluginTest.cs b/src/modules/launcher/Wox.Test/Plugins/ProgramPluginTest.cs
index 54b8b95fc0..abf45b7888 100644
--- a/src/modules/launcher/Wox.Test/Plugins/ProgramPluginTest.cs
+++ b/src/modules/launcher/Wox.Test/Plugins/ProgramPluginTest.cs
@@ -78,6 +78,53 @@ namespace Wox.Test.Plugins
LnkResolvedPath = null
};
+ Win32 twitter_pwa = new Win32
+ {
+ Name = "Twitter",
+ FullPath = "c:\\program files (x86)\\google\\chrome\\application\\chrome_proxy.exe",
+ LnkResolvedPath = "c:\\users\\powertoys\\appdata\\roaming\\microsoft\\windows\\start menu\\programs\\chrome apps\\twitter.lnk",
+ Arguments = " --profile-directory=Default --app-id=jgeosdfsdsgmkedfgdfgdfgbkmhcgcflmi"
+ };
+
+ Win32 pinned_webpage = new Win32
+ {
+ Name = "Web page",
+ FullPath = "c:\\program files (x86)\\microsoft\\edge\\application\\msedge_proxy.exe",
+ LnkResolvedPath = "c:\\users\\powertoys\\appdata\\roaming\\microsoft\\windows\\start menu\\programs\\web page.lnk",
+ Arguments = "--profile-directory=Default --app-id=homljgmgpmcbpjbnjpfijnhipfkiclkd"
+ };
+
+ Win32 edge_named_pinned_webpage = new Win32
+ {
+ Name = "edge - Bing",
+ FullPath = "c:\\program files (x86)\\microsoft\\edge\\application\\msedge_proxy.exe",
+ LnkResolvedPath = "c:\\users\\powertoys\\appdata\\roaming\\microsoft\\windows\\start menu\\programs\\edge - bing.lnk",
+ Arguments = " --profile-directory=Default --app-id=aocfnapldcnfbofgmbbllojgocaelgdd"
+ };
+
+ Win32 msedge = new Win32
+ {
+ Name = "Microsoft Edge",
+ ExecutableName = "msedge.exe",
+ FullPath = "c:\\program files (x86)\\microsoft\\edge\\application\\msedge.exe",
+ LnkResolvedPath = "c:\\programdata\\microsoft\\windows\\start menu\\programs\\microsoft edge.lnk"
+ };
+
+ Win32 chrome = new Win32
+ {
+ Name = "Google Chrome",
+ ExecutableName = "chrome.exe",
+ FullPath = "c:\\program files (x86)\\google\\chrome\\application\\chrome.exe",
+ LnkResolvedPath = "c:\\programdata\\microsoft\\windows\\start menu\\programs\\google chrome.lnk"
+ };
+
+ Win32 dummy_proxy_app = new Win32
+ {
+ Name = "Proxy App",
+ ExecutableName = "test_proxy.exe",
+ FullPath = "c:\\program files (x86)\\microsoft\\edge\\application\\test_proxy.exe",
+ LnkResolvedPath = "c:\\programdata\\microsoft\\windows\\start menu\\programs\\test proxy.lnk"
+ };
[Test]
public void DedupFunction_whenCalled_mustRemoveDuplicateNotepads()
@@ -139,5 +186,79 @@ namespace Wox.Test.Plugins
// Assert
Assert.AreEqual(apps.Length, 3);
}
+
+ [Test]
+ public void FunctionIsWebApplication_ShouldReturnTrue_ForWebApplications()
+ {
+ // The IsWebApplication(() function must return true for all PWAs and pinned web pages
+ Assert.IsTrue(twitter_pwa.IsWebApplication());
+ Assert.IsTrue(pinned_webpage.IsWebApplication());
+ Assert.IsTrue(edge_named_pinned_webpage.IsWebApplication());
+
+ // Should not filter apps whose executable name ends with proxy.exe
+ Assert.IsFalse(dummy_proxy_app.IsWebApplication());
+ }
+
+ [TestCase("ignore")]
+ public void FunctionFilterWebApplication_ShouldReturnFalse_WhenSearchingForTheMainApp(string query)
+ {
+ // Irrespective of the query, the FilterWebApplication() Function must not filter main apps such as edge and chrome
+ Assert.IsFalse(msedge.FilterWebApplication(query));
+ Assert.IsFalse(chrome.FilterWebApplication(query));
+ }
+
+ [TestCase("edge", ExpectedResult = true)]
+ [TestCase("EDGE", ExpectedResult = true)]
+ [TestCase("msedge", ExpectedResult = true)]
+ [TestCase("Microsoft", ExpectedResult = true)]
+ [TestCase("edg", ExpectedResult = true)]
+ [TestCase("Edge page", ExpectedResult = false)]
+ [TestCase("Edge Web page", ExpectedResult = false)]
+ public bool EdgeWebSites_ShouldBeFiltered_WhenSearchingForEdge(string query)
+ {
+ return pinned_webpage.FilterWebApplication(query);
+ }
+
+ [TestCase("chrome", ExpectedResult = true)]
+ [TestCase("CHROME", ExpectedResult = true)]
+ [TestCase("Google", ExpectedResult = true)]
+ [TestCase("Google Chrome", ExpectedResult = true)]
+ [TestCase("Google Chrome twitter", ExpectedResult = false)]
+ public bool ChromeWebSites_ShouldBeFiltered_WhenSearchingForChrome(string query)
+ {
+ return twitter_pwa.FilterWebApplication(query);
+ }
+
+ [TestCase("twitter", 0, ExpectedResult = false)]
+ [TestCase("Twit", 0, ExpectedResult = false)]
+ [TestCase("TWITTER", 0, ExpectedResult = false)]
+ [TestCase("web", 1, ExpectedResult = false)]
+ [TestCase("Page", 1, ExpectedResult = false)]
+ [TestCase("WEB PAGE", 1, ExpectedResult = false)]
+ [TestCase("edge", 2, ExpectedResult = false)]
+ [TestCase("EDGE", 2, ExpectedResult = false)]
+ public bool PinnedWebPages_ShouldNotBeFiltered_WhenSearchingForThem(string query, int Case)
+ {
+ const uint CASE_TWITTER = 0;
+ const uint CASE_WEB_PAGE = 1;
+ const uint CASE_EDGE_NAMED_WEBPAGE = 2;
+
+ // If the query is a part of the name of the web application, it should not be filtered,
+ // even if the name is the same as that of the main application, eg: case 2 - edge
+ if (Case == CASE_TWITTER)
+ {
+ return twitter_pwa.FilterWebApplication(query);
+ }
+ else if(Case == CASE_WEB_PAGE)
+ {
+ return pinned_webpage.FilterWebApplication(query);
+ }
+ else if(Case == CASE_EDGE_NAMED_WEBPAGE)
+ {
+ return edge_named_pinned_webpage.FilterWebApplication(query);
+ }
+ // unreachable code
+ return true;
+ }
}
}