diff --git a/Auxiliary/BrowserDiscoveryUtils.cs b/Auxiliary/BrowserDiscoveryUtils.cs new file mode 100644 index 0000000..52c8681 --- /dev/null +++ b/Auxiliary/BrowserDiscoveryUtils.cs @@ -0,0 +1,146 @@ +using AdvancedSharpAdbClient; +using ChromeDroid_TabMan.DTOs; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using static ChromeDroid_TabMan.Auxiliary.ImportUtils; +using AdvancedSharpAdbClient.DeviceCommands; +using ChromeDroid_TabMan.Connection_and_Import; +using System.Net.Http; +using System.Net.Http.Json; +using System.Security.Cryptography.X509Certificates; + +namespace ChromeDroid_TabMan.Auxiliary +{ + public static class BrowserDiscoveryUtils + { + public static List GetDefaultBrowserComboItems() + { + return new List + { + new BrowserComboItem("Chrome",ConfigHelper.ADB.Chrome_PackageName,ConfigHelper.ADB.Chrome_ForwardParameter_Remote,true,DiscoveryStateEnum.NotSearchedFor), + new BrowserComboItem("Opera",ConfigHelper.ADB.Opera_PackageName,ConfigHelper.ADB.Opera_ForwardParameter_Remote,true,DiscoveryStateEnum.NotSearchedFor), + new BrowserComboItem("SamsungInternet",ConfigHelper.ADB.SamsungInternet_PackageName,ConfigHelper.ADB.SamsungInternet_ForwardParameter_Remote,true,DiscoveryStateEnum.NotSearchedFor), + new BrowserComboItem("Edge",ConfigHelper.ADB.Edge_PackageName,ConfigHelper.ADB.EdgeAndBraveAndChrome_Base_ForwardParameterRemote__MissingPidAtEnd,false,DiscoveryStateEnum.NotSearchedFor), + new BrowserComboItem("Brave",ConfigHelper.ADB.Brave_PackageName,ConfigHelper.ADB.EdgeAndBraveAndChrome_Base_ForwardParameterRemote__MissingPidAtEnd,false,DiscoveryStateEnum.NotSearchedFor) + }; + } + + public static List GetDevToolsSockets(string adbPath) + { + ClientAndDevice_Adb clientAndDevice_Adb = ImportUtils.ConnectAndGetAdbClientAndDevice(adbPath); + AdbClient client = clientAndDevice_Adb.client; + DeviceData device = clientAndDevice_Adb.device; + + ConsoleOutputReceiver cOR = new(); + client.ExecuteShellCommand(device, @"ss -a 2>/dev/null| grep devtools| cut -F 5", cOR); + string response = cOR.ToString(); + + return response.Split("\n").ToList(); + } + + public static void VerifyExistingSockets(List browserComboItemsToVerify, List devToolsSocketsFound, string adbPath) //remember that C# passes objects and collections of objects as references. + { + for (int i = 0; i < browserComboItemsToVerify.Count; i++) + { + var browser = browserComboItemsToVerify[i]; + var currBD = browser.BrowserDetails; + + var socketFullName = browser.BrowserDetails.SocketNameFullOrPartial; + if ((!currBD.IsSocketNameFull && currBD.PackageName != null) || currBD.PackageName==ConfigHelper.ADB.Chrome_PackageName)//the || currBD.PackageName==ConfigHelper.ADB.Chrome_PackageName condition fixes the condition where one of the other chromium browsers somehow gets the name default devtools socket before chrome. + { + + try + { + socketFullName = currBD.SocketNameFullOrPartial + "_" + ImportUtils.GetChromiumBrowserPid(adbPath, currBD.PackageName, false); + } + catch (PidNotParsedException pidEx) + { //This mostly means the browser is not running, so we can safely mark the browser's sockets as not found. + browser.BrowserDetails = new BrowserDetailsStruct(currBD.BrowserName, currBD.PackageName, currBD.SocketNameFullOrPartial, currBD.IsSocketNameFull, DiscoveryStateEnum.NotFound); + continue; + } + } + if (devToolsSocketsFound.Any(s => (socketFullName == "localabstract:" + s.Replace("\r", "").Replace("\n", "").Replace("@", "")))) + { + DiscoveryStateEnum discoveryState = DiscoveryStateEnum.Verified; + if (currBD.PackageName == ConfigHelper.ADB.Chrome_PackageName && socketFullName != ConfigHelper.ADB.Chrome_ForwardParameter_Remote) + discoveryState = DiscoveryStateEnum.RediscoveredAndFixed; + else if (!currBD.IsSocketNameFull) + discoveryState = DiscoveryStateEnum.RediscoveredAndFilledRestOfTheSocket; + browser.BrowserDetails = new BrowserDetailsStruct(currBD.BrowserName, currBD.PackageName, socketFullName, true, discoveryState); + devToolsSocketsFound.RemoveAll(s => (socketFullName == "localabstract:" + s.Replace("\r", "").Replace("\n", "").Replace("@", ""))); + } + else if(currBD.PackageName==ConfigHelper.ADB.Chrome_PackageName && devToolsSocketsFound.Any(s=>s==ConfigHelper.ADB.Chrome_ForwardParameter_Remote)) + { + browser.BrowserDetails = new BrowserDetailsStruct(currBD.BrowserName, currBD.PackageName, ConfigHelper.ADB.Chrome_ForwardParameter_Remote, true, DiscoveryStateEnum.Verified); + //not removing this from devTools so that it can be verified later in the next stage. + } + else + { + browser.BrowserDetails = new BrowserDetailsStruct(currBD.BrowserName, currBD.PackageName, currBD.SocketNameFullOrPartial, currBD.IsSocketNameFull, DiscoveryStateEnum.NotFound); + } + } + } + + public static void DiscoverNewSocketsAndOrFixKnownBrowsersWithUnexpectedSocketNames(List existingBrowserComboList, List devToolsSocketsFound, string adbPath_ProvideIfNewBrowserDetailsNeeded=null) //remember that C# passes objects and collections of objects as references. + { + string adbPath = adbPath_ProvideIfNewBrowserDetailsNeeded; + HashSet packageNameOfBrowsersThatCanBeFixed = existingBrowserComboList.Where(b => b.BrowserDetails.PackageName.Contains(ConfigHelper.ADB.EdgeAndBraveAndChrome_Base_ForwardParameterRemote__MissingPidAtEnd)).Select(b=>b.BrowserDetails.PackageName).ToHashSet(); + foreach (string currConnSocket in devToolsSocketsFound) + { + if (currConnSocket == string.Empty) + continue; + string nSocket = currConnSocket.Replace("\r", "").Replace("\n", "").Replace("@", ""); + string currSocketFull = "localabstract:" + nSocket; + string browserName = currSocketFull; + string packageName = null; + if(adbPath!=null) //this means that we are supposed to fill in the details for each newly discovered device. + { + var res = BrowserDiscoveryUtils.GetBrowserDetails(adbPath, currSocketFull); + browserName = res.OnlyNameBrowser; + packageName = res.AndroidPackageName; + int preexistingIndex = existingBrowserComboList.FindIndex(b => (b.BrowserDetails.PackageName == packageName)); + if (-1!=preexistingIndex) //fixing old browsers. + { + var currBD = existingBrowserComboList[preexistingIndex].BrowserDetails; + DiscoveryStateEnum discoveryState = DiscoveryStateEnum.RediscoveredAndFilledRestOfTheSocket; + + //if (packageNameOfBrowsersThatCanBeFixed.Contains(currBD.PackageName)) + //{ + if (currBD.PackageName == ConfigHelper.ADB.Chrome_PackageName) + { + //verifying chrome when it gets a different socket than Chrome default. + if (currSocketFull != ConfigHelper.ADB.Chrome_ForwardParameter_Remote) + discoveryState = DiscoveryStateEnum.RediscoveredAndFixed; + else if(currSocketFull == ConfigHelper.ADB.Chrome_ForwardParameter_Remote) + discoveryState = DiscoveryStateEnum.Verified; + } + else if (currBD.PackageName == ConfigHelper.ADB.Brave_PackageName || currBD.PackageName == ConfigHelper.ADB.Edge_PackageName) //verifying edge or brave when they get the default Chrome socket. + { + if (currSocketFull == ConfigHelper.ADB.Chrome_ForwardParameter_Remote) + discoveryState = DiscoveryStateEnum.RediscoveredAndFixed; + } + //} + + existingBrowserComboList[preexistingIndex] = new BrowserComboItem(currBD.BrowserName, currBD.PackageName, currSocketFull, true, discoveryState); + return; + } + } + BrowserComboItem browser = new BrowserComboItem(browserName, packageName, currSocketFull, true, DiscoveryStateEnum.Discovered); + existingBrowserComboList.Add(browser); + } + } + + + public static BrowserJsonVersionDTO GetBrowserDetails(string adbPath,string forwardParameter_Remote) + { + IAdbConnector adbConnector = new DiscoveredSocketOnlyAdbConnector(adbPath, forwardParameter_Remote); + adbConnector.StartAdbJsonListServer(); + HttpClient httpClient = new(); + BrowserJsonVersionDTO response = httpClient.GetFromJsonAsync(ConfigHelper.ADB.BrowserJsonVersionURL).Result; + return response; + } + } +} diff --git a/Auxiliary/ConfigHelper.cs b/Auxiliary/ConfigHelper.cs new file mode 100644 index 0000000..f710140 --- /dev/null +++ b/Auxiliary/ConfigHelper.cs @@ -0,0 +1,86 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Security.Policy; +using System.Text; +using System.Threading.Tasks; + +namespace ChromeDroid_TabMan.Auxiliary +{ + public static class ConfigHelper + { + public static bool SortGroupsInGroupedHtmlAndNetscapeBookmarksAlphabetically = true; + public static string UnidentifiedBaseUrlString => "**Unidentiffied BaseURLs**"; + public static string ExportFilesPartialDefaultName { get { return "recoveredTabs(" + DateTime.Now.ToString("dd-mm-yy__HH-mm-ss")+")";} } + public static void InitializeConfig() + { + FileNamesAndPaths.InitializeConfig(); + Logging.InitializeConfig(); + Database.InitializeConfig(); + } + public static class FileNamesAndPaths + { + public static string OutputPathDefaultExportDirectory => System.AppContext.BaseDirectory + @"Exports\"; + public static string BookmarksGroupedDefaultFileName => "Bookmarks_Grouped - " + ExportFilesPartialDefaultName + ".html"; + public static string BookmarksDefaultFileName => "Bookmarks - " + ExportFilesPartialDefaultName + ".html"; + public static string ListDefaultFileName => "LIST - " + ExportFilesPartialDefaultName + ".html"; + public static string CSVDefaultFileName => "CSV - " + ExportFilesPartialDefaultName + ".csv"; + public static void InitializeConfig() + { + OutputJsonFileName = "_chromtabJSON.json"; + PrevOutputJsonNewFileName = OutputJsonFileName + ".bak"; + CurrentListOfURLsTxtFileName = "CurrentListOfURLs.txt"; + CurrentListOfTitlesTxtFileName = "CurrentListOfTitles.txt"; + } + public static string OutputJsonFileName { get; private set; } + public static string BackUpExtensionWithDot => ".bak"; + public static string PrevOutputJsonNewFileName { get; private set; } + public static string CurrentListOfURLsTxtFileName { get; private set; } + public static string CurrentListOfTitlesTxtFileName { get; private set; } + } + public static class Logging + { + public static void InitializeConfig() + { + EnablePrintingInTabsListProcessingFromTxts = true; + } + public static bool EnablePrintingInTabsListProcessingFromTxts { get; private set; } //= false; + } + public static class Database + { + public static string DbFileExtensionWithDot => ".sqlite3.db"; + public static string DbFileName => "SQLite DB - " + ExportFilesPartialDefaultName + DbFileExtensionWithDot; + public static void InitializeConfig() + { + //DbPath = "_LastTabs.db"; + } + //public static string DbPath { get; private set; } + } + public static class ADB + { + public static string HostURL => "127.0.0.1:62001"; + public static string Chrome_PackageName => "com.android.chrome"; + public static string SamsungInternet_PackageName => "com.sec.android.app.sbrowser"; + public static string Opera_PackageName => "com.opera.browser"; + public static string Edge_PackageName => "com.microsoft.emmx"; + public static string Brave_PackageName => "com.brave.browser"; + public static string LocalHostString => "localhost"; + public static string ForwardParameter_Local_PortOnly => "9223"; + public static string ForwardParameter_Local => "tcp:"+ForwardParameter_Local_PortOnly; + + public static string BaseLocalForwardedURL => "http://" + LocalHostString + ":" + ForwardParameter_Local_PortOnly; + public static string TabListEndpoint => "/json/list"; + public static string TabsJsonListURL => BaseLocalForwardedURL + TabListEndpoint; + public static string BrowserVersionEndpoint => "/json/version"; + public static string BrowserJsonVersionURL => BaseLocalForwardedURL + BrowserVersionEndpoint; + public static string Chrome_ForwardParameter_Remote => "localabstract:chrome_devtools_remote"; + public static string SamsungInternet_ForwardParameter_Remote => "localabstract:Terrace_devtools_remote"; + public static string Opera_ForwardParameter_Remote => "localabstract:com.opera.browser.devtools"; + private static string EdgeAndBrave_ExceptionMessage_For_ForwardParameter_Remote => "For Edge and Brave, the ForwardParameter_Remote is the concatenation of \"localabstract:chrome_devtools_remote_\" with the process ID of the process of the browser instance at that time (can be found using pidof command)."; + //public static string Edge_ForwardParameter_Remote => throw new Exception(EdgeAndBrave_ExceptionMessage_For_ForwardParameter_Remote); + //public static string Brave_ForwardParameter_Remote => throw new Exception(EdgeAndBrave_ExceptionMessage_For_ForwardParameter_Remote); + public static string EdgeAndBraveAndChrome_Base_ForwardParameterRemote__MissingPidAtEnd => Chrome_ForwardParameter_Remote; + } + } +} diff --git a/Auxiliary/ImportUtils.cs b/Auxiliary/ImportUtils.cs new file mode 100644 index 0000000..ed80dff --- /dev/null +++ b/Auxiliary/ImportUtils.cs @@ -0,0 +1,152 @@ +using System; +using System.IO; +using System.Diagnostics; +using System.Net; +using System.Windows.Forms; +//using JQ.Net.JQ; +using System.Collections.Generic; +using System.Text.Json; +using Newtonsoft.Json; +using System.Linq; +using ChromeDroid_TabMan.Data; +using AdvancedSharpAdbClient; +using ChromeDroid_TabMan.Connection_and_Import; +using ChromeDroid_TabMan.DTOs; +using System.Net.Http; +using AdvancedSharpAdbClient.DeviceCommands; + + +//#define _USE_JQ + + +namespace ChromeDroid_TabMan.Auxiliary +{ + public struct ClientAndDevice_Adb + { + public AdbClient client; + public DeviceData device; + } + public static class ImportUtils + { + public static ClientAndDevice_Adb ConnectAndGetAdbClientAndDevice(string adbPath) + { + if (!AdbServer.Instance.GetStatus().IsRunning) + { + AdbServer server = new AdbServer(); + StartServerResult result = server.StartServer(adbPath, false); //(@"C:\adb\adb.exe", false); + if (result != StartServerResult.Started) + { + Console.WriteLine("Can't start adb server"); + } + } + + AdbClient client; + DeviceData device; + + client = new AdbClient(); + client.Connect(ConfigHelper.ADB.HostURL); + device = client.GetDevices().FirstOrDefault(); // Get first connected device + + ClientAndDevice_Adb clientAndDevice_Adb = new ClientAndDevice_Adb(); + clientAndDevice_Adb.client = client; + clientAndDevice_Adb.device = device; + return clientAndDevice_Adb; + } + public static string GetChromiumBrowserPid(string adbPath, string browserPackageName, bool startBrowserAutomatically = true) + { + ClientAndDevice_Adb clientAndDevice_Adb = ImportUtils.ConnectAndGetAdbClientAndDevice(adbPath); + AdbClient client = clientAndDevice_Adb.client; + DeviceData device = clientAndDevice_Adb.device; + + if(startBrowserAutomatically) + client.StartApp(device, browserPackageName); + + ConsoleOutputReceiver cOR = new ConsoleOutputReceiver(); + client.ExecuteShellCommand(device, "pidof " + browserPackageName, cOR); + + cOR.Flush(); + + int pid; + try + { + pid = int.Parse(cOR.ToString()); //could possibly have used TryParse in a better setup/context. + } + catch(System.FormatException e) + { + throw new PidNotParsedException(); + } + + return pid.ToString(); + } + public static string StartChromeAndroidJsonListServer(string adbPath, string browserPackageName, string browserRemoteForwardParameter, bool startBrowserAutomatically = true) + { + ClientAndDevice_Adb clientAndDevice_Adb = ConnectAndGetAdbClientAndDevice(adbPath); + AdbClient client = clientAndDevice_Adb.client; + DeviceData device = clientAndDevice_Adb.device; + + if(startBrowserAutomatically) + client.StartApp(device, browserPackageName); + + string forwardParamLocal = ConfigHelper.ADB.ForwardParameter_Local; + client.CreateForward(device, forwardParamLocal, browserRemoteForwardParameter, true);//procStartInfo.Arguments = " - d forward tcp:9222 localabstract:chrome_devtools_remote"; + return ConfigHelper.ADB.TabsJsonListURL; + } + + public static string DownloadTabListJSON(string tabsJsonUrl = "", string outputJsonFileName = "") + { + if (tabsJsonUrl == "") + tabsJsonUrl = ConfigHelper.ADB.TabsJsonListURL; + if (outputJsonFileName == "") + tabsJsonUrl = ConfigHelper.FileNamesAndPaths.OutputJsonFileName; + + HttpClient httpClient = new HttpClient(); + var request = new HttpRequestMessage(HttpMethod.Get, tabsJsonUrl); + string text; + var response = httpClient.SendAsync(request).Result; + + using (var sr = new StreamReader(response.Content.ReadAsStream()))//response.GetResponseStream())) + { + text = sr.ReadToEnd(); + } + + ///The following is to rename old .json to .json.bak: + // Source file to be renamed + //string sourceFile = ConfigHelper.JsonFileName; + string prevOutPutJsonFileName = outputJsonFileName + ConfigHelper.FileNamesAndPaths.BackUpExtensionWithDot; + // Creating FileInfo + FileInfo fileInfo = new FileInfo(outputJsonFileName); + // Checking if file exists. + if (fileInfo.Exists) + { + // Move file with a new name. Hence renamed. + File.Delete(prevOutPutJsonFileName); + fileInfo.MoveTo(prevOutPutJsonFileName); + //Console.WriteLine("File Renamed."); + } + File.WriteAllText(outputJsonFileName, text, System.Text.Encoding.UTF8); + + return outputJsonFileName; + } + + public static List LoadJson(string jsonPath = "") + { + + //bool usingDefaultPath = false; + if (jsonPath == "") + { + // "\"" was needed for passing as argument to JQ, not needed anymore. + jsonPath = AppContext.BaseDirectory + ConfigHelper.FileNamesAndPaths.OutputJsonFileName; //"\"" + System.AppContext.BaseDirectory + +ConfigHelper.FileNamesAndPaths.JsonFileName+ "\""; + //usingDefaultPath = true; + } + + string jsonText = File.ReadAllText(jsonPath); + + return System.Text.Json.JsonSerializer.Deserialize>(jsonText); //JsonConvert.DeserializeObject<>(jsonText); + } + public static void GetURLtxtAndTITLEtxtFromJSON(List basicTabInfs) + { + File.WriteAllLines(ConfigHelper.FileNamesAndPaths.CurrentListOfURLsTxtFileName, basicTabInfs.Select(x => x.url));//select preserves order. + File.WriteAllLines(ConfigHelper.FileNamesAndPaths.CurrentListOfTitlesTxtFileName, basicTabInfs.Select(x => x.lastKnownTitle));//select preserves order. + } + } +} diff --git a/Auxiliary/PidNotParsedException.cs b/Auxiliary/PidNotParsedException.cs new file mode 100644 index 0000000..fa9de93 --- /dev/null +++ b/Auxiliary/PidNotParsedException.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ChromeDroid_TabMan.Auxiliary +{ + public class PidNotParsedException :Exception + { + public PidNotParsedException(string message="PID could not be found or parsed. One possibility is that the process may not be running.") : base(message) + { + + } + } +} diff --git a/Auxiliary/WinFormsUtils.cs b/Auxiliary/WinFormsUtils.cs new file mode 100644 index 0000000..71517b1 --- /dev/null +++ b/Auxiliary/WinFormsUtils.cs @@ -0,0 +1,66 @@ +using ChromeDroid_TabMan.DTOs; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Policy; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace ChromeDroid_TabMan.Auxiliary +{ + internal static class WinFormsUtils + { + public static void InitializeOrResetBrowserListComboBox(ComboBox browserSelect, List itemLists_OptionalParam = null) //note, c# passes objects by reference. + { + browserSelect.DataSource = null; + List comboItemsAlignedList; + if (itemLists_OptionalParam == null) + comboItemsAlignedList = BrowserDiscoveryUtils.GetDefaultBrowserComboItems(); + else + comboItemsAlignedList = itemLists_OptionalParam; + browserSelect.DataSource = comboItemsAlignedList; + + browserSelect.DisplayMember = nameof(BrowserComboItem.Name); + browserSelect.ValueMember = nameof(BrowserComboItem.BrowserDetails); + browserSelect.SelectedItem = browserSelect.Items[0]; + browserSelect.SelectedIndex = 0; + + browserSelect.Refresh(); + } + + public static string GetADBPathDialog(bool resetFilePathToC = false) + { + var filePath = string.Empty; + bool IsCancelled = false; + while (filePath == string.Empty && !IsCancelled) + { + using (OpenFileDialog openFileDialog = new OpenFileDialog()) + { + if(resetFilePathToC) + openFileDialog.InitialDirectory = "c:\\"; + openFileDialog.Filter = "ADB Executable (adb.exe)|adb.exe|All Executables (*.exe)|*.exe"; + openFileDialog.FilterIndex = 1; + openFileDialog.RestoreDirectory = true; + + if (openFileDialog.ShowDialog() != DialogResult.OK || openFileDialog.FileName == string.Empty) + { + if (DialogResult.Cancel == MessageBox.Show("No file selected.", "Notice", MessageBoxButtons.RetryCancel, MessageBoxIcon.Exclamation)) + { + IsCancelled = true; + return "-1"; + } + continue; + } + + //Get the path of specified file + filePath = openFileDialog.FileName; + } + } + + MessageBox.Show("Selected executable: " + filePath, "ADB Executable Selected!" + filePath, MessageBoxButtons.OK); + + return filePath; + } + } +} diff --git a/ChromeDroid TabMan.csproj b/ChromeDroid TabMan.csproj index 5b40be4..a5006e0 100644 --- a/ChromeDroid TabMan.csproj +++ b/ChromeDroid TabMan.csproj @@ -2,9 +2,18 @@ WinExe - net5.0-windows + net7.0-windows ChromeDroid_TabMan true + AnyCPU;x64 + true + + + + + + + \ No newline at end of file diff --git a/ChromeDroid TabMan.sln b/ChromeDroid TabMan.sln index d415f36..8c77880 100644 --- a/ChromeDroid TabMan.sln +++ b/ChromeDroid TabMan.sln @@ -1,20 +1,26 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.32002.261 +# Visual Studio Version 17 +VisualStudioVersion = 17.4.33110.190 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ChromeDroid TabMan", "ChromeDroid TabMan.csproj", "{8CC8085F-D6A5-44AF-81A9-3FE616CE9AE3}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ChromeDroid TabMan", "ChromeDroid TabMan.csproj", "{8CC8085F-D6A5-44AF-81A9-3FE616CE9AE3}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {8CC8085F-D6A5-44AF-81A9-3FE616CE9AE3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {8CC8085F-D6A5-44AF-81A9-3FE616CE9AE3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8CC8085F-D6A5-44AF-81A9-3FE616CE9AE3}.Debug|x64.ActiveCfg = Debug|x64 + {8CC8085F-D6A5-44AF-81A9-3FE616CE9AE3}.Debug|x64.Build.0 = Debug|x64 {8CC8085F-D6A5-44AF-81A9-3FE616CE9AE3}.Release|Any CPU.ActiveCfg = Release|Any CPU {8CC8085F-D6A5-44AF-81A9-3FE616CE9AE3}.Release|Any CPU.Build.0 = Release|Any CPU + {8CC8085F-D6A5-44AF-81A9-3FE616CE9AE3}.Release|x64.ActiveCfg = Release|x64 + {8CC8085F-D6A5-44AF-81A9-3FE616CE9AE3}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Connection and Import/AdbTabsJsonFetcher.cs b/Connection and Import/AdbTabsJsonFetcher.cs new file mode 100644 index 0000000..547aa4c --- /dev/null +++ b/Connection and Import/AdbTabsJsonFetcher.cs @@ -0,0 +1,26 @@ +using ChromeDroid_TabMan.Auxiliary; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net; +using System.Text; +using System.Threading.Tasks; + +namespace ChromeDroid_TabMan.Connection_and_Import +{ + internal class AdbTabsJsonFetcher : ITabsJsonFetcher + { + public IAdbConnector _adbConnector { get; } + public AdbTabsJsonFetcher(IAdbConnector adbConnector) + { + _adbConnector = adbConnector; + } + + public string FetchTabsJson() + { + string jsonListTabsUrl = _adbConnector.StartAdbJsonListServer(); + return ImportUtils.DownloadTabListJSON(tabsJsonUrl: jsonListTabsUrl, outputJsonFileName: ConfigHelper.FileNamesAndPaths.OutputJsonFileName); + } + } +} diff --git a/Connection and Import/DiscoveredSocketOnlyAdbConnector.cs b/Connection and Import/DiscoveredSocketOnlyAdbConnector.cs new file mode 100644 index 0000000..e3599e8 --- /dev/null +++ b/Connection and Import/DiscoveredSocketOnlyAdbConnector.cs @@ -0,0 +1,26 @@ +using ChromeDroid_TabMan.Auxiliary; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ChromeDroid_TabMan.Connection_and_Import +{ + internal class DiscoveredSocketOnlyAdbConnector : IAdbConnector + { + public string AdbPath { get; } + public string BrowserPackageName => "[DISCOVERED BROWSERS HAVE NO PACKAGE NAMES AVAILABLE]";//=> throw new Exception("Discovered browsers don't have a package name."); + public string ForwardParameter_Remote { get; } + public DiscoveredSocketOnlyAdbConnector(string adbPath, string forwardParameter_Remote) + { + AdbPath = adbPath; + ForwardParameter_Remote = forwardParameter_Remote; + } + + public string StartAdbJsonListServer() + { + return ImportUtils.StartChromeAndroidJsonListServer(AdbPath, BrowserPackageName, ForwardParameter_Remote,false); + } + } +} diff --git a/Connection and Import/DynamicSocketNamePidAtEndChromiumAdbConnector.cs b/Connection and Import/DynamicSocketNamePidAtEndChromiumAdbConnector.cs new file mode 100644 index 0000000..526c0a7 --- /dev/null +++ b/Connection and Import/DynamicSocketNamePidAtEndChromiumAdbConnector.cs @@ -0,0 +1,32 @@ +using AdvancedSharpAdbClient; +using AdvancedSharpAdbClient.DeviceCommands; +using ChromeDroid_TabMan.Auxiliary; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using static ChromeDroid_TabMan.Auxiliary.ImportUtils; + +namespace ChromeDroid_TabMan.Connection_and_Import +{ + internal class DynamicSocketNamePidAtEndChromiumAdbConnector : IAdbConnector + { + public string AdbPath { get; } + public string BrowserPackageName { get; } + public string ForwardParameter_Remote { get; } + public DynamicSocketNamePidAtEndChromiumAdbConnector(string adbPath, string browserPackageName, string baseForwardParameterRemote_MissingPidAtEnd) + { + AdbPath = adbPath; + BrowserPackageName = browserPackageName; + string chromiumDevToolsSocketName = baseForwardParameterRemote_MissingPidAtEnd + "_" + ImportUtils.GetChromiumBrowserPid(AdbPath,BrowserPackageName); + ForwardParameter_Remote = chromiumDevToolsSocketName; + } + + public string StartAdbJsonListServer() + { + return ImportUtils.StartChromeAndroidJsonListServer(AdbPath, BrowserPackageName, ForwardParameter_Remote); + } + + } +} diff --git a/Connection and Import/IAdbConnector.cs b/Connection and Import/IAdbConnector.cs new file mode 100644 index 0000000..211224c --- /dev/null +++ b/Connection and Import/IAdbConnector.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ChromeDroid_TabMan.Connection_and_Import +{ + internal interface IAdbConnector + { + string AdbPath { get; } + string BrowserPackageName { get; } + string ForwardParameter_Remote { get; } + public string StartAdbJsonListServer(); + } +} diff --git a/Connection and Import/ITabsImporter.cs b/Connection and Import/ITabsImporter.cs new file mode 100644 index 0000000..8fad875 --- /dev/null +++ b/Connection and Import/ITabsImporter.cs @@ -0,0 +1,15 @@ +using ChromeDroid_TabMan.Data; +using ChromeDroid_TabMan.DTOs; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ChromeDroid_TabMan.Connection_and_Import +{ + internal interface ITabsImporter + { + public ITabsContainer Import(); + } +} diff --git a/Connection and Import/ITabsJsonFetcher.cs b/Connection and Import/ITabsJsonFetcher.cs new file mode 100644 index 0000000..19fd0e8 --- /dev/null +++ b/Connection and Import/ITabsJsonFetcher.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ChromeDroid_TabMan.Connection_and_Import +{ + internal interface ITabsJsonFetcher + { +#nullable enable + IAdbConnector? _adbConnector { get; } +#nullable disable + public string FetchTabsJson(); + } +} diff --git a/Connection and Import/JsonToTabsImporter.cs b/Connection and Import/JsonToTabsImporter.cs new file mode 100644 index 0000000..44087c3 --- /dev/null +++ b/Connection and Import/JsonToTabsImporter.cs @@ -0,0 +1,49 @@ +using ChromeDroid_TabMan.Data; +using ChromeDroid_TabMan.DTOs; +using ChromeDroid_TabMan.Models; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ChromeDroid_TabMan.Connection_and_Import +{ + internal class JsonToTabsImporter : ITabsImporter + { + string JsonPath { get; set; } + public JsonToTabsImporter(string jsonPath) + { + JsonPath = jsonPath; + } + public ITabsContainer Import() + { + var basicTabInfs = GetBasicTabInfsFromJson(); + + List tabInfs = new(); + Dictionary> baseUrlToTabInfListMap = new(); + + int basicTabInfsCount = basicTabInfs.Count; + for(int i=0; i GetBasicTabInfsFromJson() + { + string jsonText = File.ReadAllText(JsonPath); + + return System.Text.Json.JsonSerializer.Deserialize>(jsonText); //JsonConvert.DeserializeObject<>(jsonText); + } + } +} diff --git a/Connection and Import/SelectFileDialogTabsJsonFetcher.cs b/Connection and Import/SelectFileDialogTabsJsonFetcher.cs new file mode 100644 index 0000000..1014c06 --- /dev/null +++ b/Connection and Import/SelectFileDialogTabsJsonFetcher.cs @@ -0,0 +1,40 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace ChromeDroid_TabMan.Connection_and_Import +{ + internal class SelectFileDialogTabsJsonFetcher : ITabsJsonFetcher + { +#nullable enable + public IAdbConnector? _adbConnector { get; } = null; +#nullable disable + public SelectFileDialogTabsJsonFetcher() { } + public string FetchTabsJson() + { + //Since JSON is pre-fetched, we only ever deal with getting its file path. + + string jsonPath = null; + using (OpenFileDialog openFileDialog = new OpenFileDialog()) + { + openFileDialog.InitialDirectory = "c:\\"; + openFileDialog.Filter = "JSON and JSON.BAK files (*.json, *.json.bak)|*.json;*.json.bak|All Files (*.*)|*.*"; + openFileDialog.FilterIndex = 1; + openFileDialog.RestoreDirectory = true; + + if (openFileDialog.ShowDialog() == DialogResult.OK) + { + jsonPath = openFileDialog.FileName; + } + } + + if (jsonPath == null) + throw new Exception("No file selected."); + + return jsonPath; + } + } +} diff --git a/Connection and Import/StaticSocketNameChromiumBrowserAdbConnector.cs b/Connection and Import/StaticSocketNameChromiumBrowserAdbConnector.cs new file mode 100644 index 0000000..88d03ad --- /dev/null +++ b/Connection and Import/StaticSocketNameChromiumBrowserAdbConnector.cs @@ -0,0 +1,28 @@ +using AdvancedSharpAdbClient; +using ChromeDroid_TabMan.Auxiliary; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ChromeDroid_TabMan.Connection_and_Import +{ + internal class StaticSocketNameChromiumAdbConnector : IAdbConnector + { + public string AdbPath { get; } + public string BrowserPackageName { get; } + public string ForwardParameter_Remote { get; } + public StaticSocketNameChromiumAdbConnector(string adbPath, string browserPackageName, string forwardParameter_Remote) + { + AdbPath = adbPath; + BrowserPackageName = browserPackageName; + ForwardParameter_Remote = forwardParameter_Remote; + } + + public string StartAdbJsonListServer() + { + return ImportUtils.StartChromeAndroidJsonListServer(AdbPath, BrowserPackageName, ForwardParameter_Remote); + } + } +} diff --git a/BasicTabInf.cs b/DTOs/BasicTabInf.cs similarity index 56% rename from BasicTabInf.cs rename to DTOs/BasicTabInf.cs index 4457794..d4f0413 100644 --- a/BasicTabInf.cs +++ b/DTOs/BasicTabInf.cs @@ -1,17 +1,19 @@ -using System; +using Newtonsoft.Json; +using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Text.Json.Serialization; using System.Threading.Tasks; -namespace ChromeDroid_TabMan +namespace ChromeDroid_TabMan.DTOs { public class BasicTabInf { [JsonPropertyName("url")] - public string url; + public string url { get; set; } + //[JsonProperty("title")] [JsonPropertyName("title")] - public string lastKnownTitle; + public string lastKnownTitle { get; set; } } } diff --git a/DTOs/BrowserComboItem.cs b/DTOs/BrowserComboItem.cs new file mode 100644 index 0000000..fbf918a --- /dev/null +++ b/DTOs/BrowserComboItem.cs @@ -0,0 +1,80 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ChromeDroid_TabMan.DTOs +{ + public enum DiscoveryStateEnum + { + NotFound=0, + NotSearchedFor, + Verified, + Discovered, + RediscoveredAndFixed, + RediscoveredAndFilledRestOfTheSocket + }; + public struct BrowserDetailsStruct + { + public string BrowserName; + public string PackageName; + public string SocketNameFullOrPartial; + public bool IsSocketNameFull; + public DiscoveryStateEnum DiscoveryState; + public BrowserDetailsStruct(string browserName, string packageName, string socketNameFullOrPartial, bool isSocketNameFull, DiscoveryStateEnum discoveryState) + { + BrowserName = browserName; + PackageName = packageName; + SocketNameFullOrPartial = socketNameFullOrPartial; + IsSocketNameFull = isSocketNameFull; + DiscoveryState = discoveryState; + } + } + public class BrowserComboItem + { + + public BrowserDetailsStruct BrowserDetails { get; set; } + //public string Name => ((BrowserDetails.IsSocketNameFull && BrowserDetails.SocketNameFullOrPartial!=BrowserDetails.BrowserName) ? (BrowserDetails.BrowserName + " (" + BrowserDetails.SocketNameFullOrPartial + ")" ): BrowserDetails.BrowserName); + public string Name + { + get + { + string prefix; + string suffix = string.Empty; //string suffix = (BrowserDetails.PackageName == null || BrowserDetails.DiscoveryState==DiscoveryStateEnum.NotSearchedFor) ? string.Empty : " (" + BrowserDetails.PackageName + ")"; + switch (BrowserDetails.DiscoveryState) + { + case DiscoveryStateEnum.NotSearchedFor: + prefix= string.Empty; + suffix=string.Empty; + break; + case DiscoveryStateEnum.NotFound: + prefix = "[✘] "; + break; + case DiscoveryStateEnum.Verified: + prefix = "[✔] "; + break; + case DiscoveryStateEnum.RediscoveredAndFilledRestOfTheSocket: + prefix = "[✔*] "; + break; + case DiscoveryStateEnum.RediscoveredAndFixed: + prefix = "[ⒻⒾⓍⒺⒹ] "; //"[**✔**] "; + break; + case DiscoveryStateEnum.Discovered: + prefix = "[🔍] "; + suffix = " (" + BrowserDetails.PackageName + ")"; + break; + default: + throw new Exception("Unsupported DiscoveryState."); + } + return prefix + BrowserDetails.BrowserName + suffix; + + } + } + public BrowserComboItem(string name, string packageName, string socketNameFullOrPartial, bool isSocketNameFull, DiscoveryStateEnum discoveryState) + { + BrowserDetails = new BrowserDetailsStruct(name, packageName,socketNameFullOrPartial,isSocketNameFull, discoveryState); + } + + } +} diff --git a/DTOs/BrowserJsonVersionDTO.cs b/DTOs/BrowserJsonVersionDTO.cs new file mode 100644 index 0000000..b88db0d --- /dev/null +++ b/DTOs/BrowserJsonVersionDTO.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.Json.Serialization; +using System.Threading.Tasks; + +namespace ChromeDroid_TabMan.DTOs +{ + public class BrowserJsonVersionDTO + { + [JsonPropertyName("Android-Package")] + public string AndroidPackageName {get;set;} + + [JsonPropertyName("Browser")] + public string BrowserNameSlashVersion { get; set; } + [JsonIgnore] + public string OnlyNameBrowser => BrowserNameSlashVersion.Split('/')[0]; + [JsonIgnore] + public string OnlyVersionBrowser => BrowserNameSlashVersion.Split('/')[2]; + + + /* //Example content of "/json/version" endpoint HTTP Get response: + { + "Android-Package": "com.android.chrome", + "Browser": "Chrome/119.0.6045.194", + "Protocol-Version": "1.3", + "User-Agent": "...", //removed for privacy + "V8-Version": "11.9.169.7", + "WebKit-Version": "537.36 (@...)", //partially removed for privacy + "webSocketDebuggerUrl": "ws://localhost:9222/devtools/browser" + } + */ + } +} diff --git a/DTOs/ITabsContainer.cs b/DTOs/ITabsContainer.cs new file mode 100644 index 0000000..26bac0b --- /dev/null +++ b/DTOs/ITabsContainer.cs @@ -0,0 +1,17 @@ +using ChromeDroid_TabMan.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ChromeDroid_TabMan.DTOs +{ + internal interface ITabsContainer + { + ICollection AllTabInfs { get; } + int CountOfBaseURLs { get; } + int Count { get; } + IDictionary> BaseUrlToTabInfCollectionMap {get;} + } +} diff --git a/DTOs/TabsContainer.cs b/DTOs/TabsContainer.cs new file mode 100644 index 0000000..9d767c7 --- /dev/null +++ b/DTOs/TabsContainer.cs @@ -0,0 +1,25 @@ +using ChromeDroid_TabMan.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ChromeDroid_TabMan.DTOs +{ + internal class TabsContainer : ITabsContainer + { + public ICollection AllTabInfs { get; } + public IDictionary> BaseUrlToTabInfCollectionMap { get; } + + public int CountOfBaseURLs => BaseUrlToTabInfCollectionMap.Keys.Count; + + public int Count => AllTabInfs.Count; + + public TabsContainer(ICollection tabInfs, IDictionary> baseUrlToTabInfCollectionMap) + { + AllTabInfs = tabInfs; + BaseUrlToTabInfCollectionMap= baseUrlToTabInfCollectionMap; + } + } +} diff --git a/Data/CSVTextFilePairTabsExporter.cs b/Data/CSVTextFilePairTabsExporter.cs new file mode 100644 index 0000000..d97040a --- /dev/null +++ b/Data/CSVTextFilePairTabsExporter.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.IO; +using ChromeDroid_TabMan.DTOs; +using ChromeDroid_TabMan.Models; +using ChromeDroid_TabMan.Auxiliary; + +namespace ChromeDroid_TabMan.Data +{ + internal class CSVTextFilePairTabsExporter : ITabsExporter + { + public string OutputFile { get; } + + public CSVTextFilePairTabsExporter(string outputFile = "") + { + if (outputFile.Length == 0 || !outputFile.Trim('"').ToLower().EndsWith(".csv")) + outputFile = ConfigHelper.FileNamesAndPaths.OutputPathDefaultExportDirectory + ConfigHelper.FileNamesAndPaths.CSVDefaultFileName; + OutputFile = outputFile; + } + + public string Export(ITabsContainer tabsContainer) + { + using (StreamWriter outfile = new StreamWriter(OutputFile,false)) + { + outfile.Write("tab_num,title,url,base_url"); + foreach(TabInf tab in tabsContainer.AllTabInfs) + { + outfile.Write("\n"); + outfile.Write($"\"{tab.TabNum}\",\"{tab.LastKnownTitle}\",\"{tab.URL}\",\"{tab.BaseWebsite}\""); + } + outfile.Flush(); + } + return OutputFile; + } + } +} diff --git a/TabsList.cs b/Data/DEPRECATED_TabsList.cs similarity index 65% rename from TabsList.cs rename to Data/DEPRECATED_TabsList.cs index d89f3d9..4d114ff 100644 --- a/TabsList.cs +++ b/Data/DEPRECATED_TabsList.cs @@ -1,86 +1,132 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Diagnostics; using System.IO; using System.Linq; using System.Text; using System.Text.Json; using System.Threading.Tasks; +using System.Xml; +using ChromeDroid_TabMan.Auxiliary; +using ChromeDroid_TabMan.DTOs; +using ChromeDroid_TabMan.Models; +using static System.Windows.Forms.VisualStyles.VisualStyleElement; +//using JQ.Net; +//using JQ.Net.JQ; -namespace ChromeDroid_TabMan +namespace ChromeDroid_TabMan.Data { - public enum PathType + //Singleton: + public class DEPRECATED_TabsList { - URL_txt=1, - Title_txt=2 - } - class TabsList - { - public int TabCount { get; private set; } - private bool tabsProcessed = false; - private string urlSrcPath = "CurrentListOfURLs.txt"; - private string titleSrcPath = "CurrentListOfTitles.txt"; - //public readonly ArrayList tabs = new ArrayList(); //Contains TabInf for each Tab. - public readonly List tabs = new List(); //Contains TabInf for each Tab. - //public readonly ArrayList baseURLs = new ArrayList(); - public readonly List baseURLs = new List(); - public TabsList(bool PrintEnabled) + private static DEPRECATED_TabsList instance = null; + public enum PathType { - //PathType type = PathType.URL_txt; - //this.urlSrcPath = ReadPath(type); - //type = PathType.Title_txt; - //this.titleSrcPath = ReadPath(type); - //this.titleSrcPath = "C:\\Users\\Noman\\Desktop\\ChromeAndroidTabs-TITLES.txt"; - //this.urlSrcPath = "C:\\Users\\Noman\\Desktop\\ChromeAndroidTabs-URL.txt"; - this.TabCount = 0; - ProcessTabs(PrintEnabled); + URL_txt = 1, + Title_txt = 2 } + public bool TabsProcessed { get; private set; } + public int TabCount { get { return Tabs.Count; } } + public List Tabs { get; private set; } //Contains TabInf for each Tab. + + List DEPRECATED_baseUrls; + + + private readonly string urlSrcPath = ConfigHelper.FileNamesAndPaths.CurrentListOfURLsTxtFileName; + private readonly string titleSrcPath = ConfigHelper.FileNamesAndPaths.CurrentListOfTitlesTxtFileName; - //public TabsList() - //{ - // string fileName = "_chromtabJSON.json"; - // string jsonString = File.ReadAllText("lol.json");//fileName); - // BasicTabInf t1 = JsonSerializer.Deserialize(jsonString, basic)) - // string wow = t1.lastKnownTitle; - - //} - public string ExportToHTML(string outputfile="") + + + //public readonly ArrayList baseURLs = new ArrayList(); + public List BaseURLs { get; private set; } + private DEPRECATED_TabsList() { - string title = "recoveredTabs (" + DateTime.Now.ToString() + ")"; - string outputBaseDIR = string.Empty; - if (outputfile.Length == 0 || !outputfile.Trim('"').EndsWith(".html")) + ResetTabList(); + } + public static DEPRECATED_TabsList GetInstance() + { + if(instance == null) + instance = new DEPRECATED_TabsList(); + return instance; + } + public void ResetTabList() + { + TabsProcessed = false; + BaseURLs = new(); + Tabs = new(); + } + internal void SetFromTabsContainer(ITabsContainer tabsContainer) + { + TabsProcessed = true; + BaseURLs = tabsContainer.BaseUrlToTabInfCollectionMap.Keys.ToList(); + Tabs = tabsContainer.AllTabInfs.ToList(); + } + + public void Process(List basicTabInfs = null) + { + if(basicTabInfs==null) { - outputfile = "LIST - " + title + ".html"; - outputfile = outputfile.Replace("/", "-"); - outputfile = outputfile.Replace(":", "-"); - outputBaseDIR = System.AppContext.BaseDirectory + @"Exports\"; - //if(!Directory.Exists(outputBaseDIR)) //turns out, don't need this for Directory.CreateDirectory. - //{ - // Directory.CreateDirectory(outputBaseDIR); - //} - Directory.CreateDirectory(outputBaseDIR); - outputfile = outputBaseDIR + outputfile; + ProcessTabsFromTxts(); + return; } - using (FileStream fs = new FileStream(outputfile, FileMode.Create)) + + Tabs = new(); + BaseURLs = new(); + HashSet baseUrlsEncountered = new(); + for(int i=0;i----------------- TOTAL TABS RECOVERED= {0} -----------------", TabCount); //NEED TO MAKE MORE EFFICIENT!! (Not need, but should!) - foreach (var baseurl in baseURLs) + foreach (var baseurl in BaseURLs) { w.Write("

", (baseurl as string)); w.Write(baseurl as string); w.WriteLine("

"); var sw = new StringWriter(); int count = 0; - foreach (var tab in tabs)//NOTE TO SELF: TO DO : INEFFECCIENT AF, FIND DIFF METHOD + foreach (var tab in Tabs)//NOTE TO SELF: TO DO : INEFFECCIENT AF, FIND DIFF METHOD { - if ((tab as TabInf).baseWebsite == (baseurl as string)) + if ((tab as TabInf).BaseWebsite == (baseurl as string)) { count++; - sw.WriteLine("
  • {1}
  • ", (tab as TabInf).url, (tab as TabInf).lastKnownTitle); + sw.WriteLine("
  • {1}
  • ", (tab as TabInf).URL, (tab as TabInf).LastKnownTitle); //w.WriteLine("
  • {1}
  • ",(tab as TabInf).url, (tab as TabInf).lastKnownTitle); } } @@ -94,9 +140,9 @@ public string ExportToHTML(string outputfile="") } } Console.ForegroundColor = ConsoleColor.Cyan; - Console.WriteLine("Written to file: " + outputfile + " ."); + Console.WriteLine("Written to file: " + outputFile + " ."); Console.ForegroundColor = ConsoleColor.White; - return outputfile; + return outputFile; } public string ExportToNetscapeBookmarksHTML(string outputfile = "", bool sort_baseURLs=false) @@ -105,7 +151,7 @@ public string ExportToNetscapeBookmarksHTML(string outputfile = "", bool sort_ba string outputBaseDIR = string.Empty; if (outputfile.Length == 0 || !outputfile.Trim('"').EndsWith(".html")) { - outputfile = "Bookmarks - " + title+ ".html"; + outputfile = "Bookmarks - " + title + ".html"; outputfile = outputfile.Replace("/", "-"); outputfile = outputfile.Replace(":", "-"); outputBaseDIR = System.AppContext.BaseDirectory + @"Exports\"; @@ -114,7 +160,7 @@ public string ExportToNetscapeBookmarksHTML(string outputfile = "", bool sort_ba // Directory.CreateDirectory(outputBaseDIR); //} Directory.CreateDirectory(outputBaseDIR); - outputfile = outputBaseDIR+ outputfile; + outputfile = outputBaseDIR + outputfile; } using (FileStream fs = new FileStream(outputfile, FileMode.Create)) { @@ -133,23 +179,23 @@ public string ExportToNetscapeBookmarksHTML(string outputfile = "", bool sort_ba w.WriteLine(title + ""); w.WriteLine("

    "); //NEED TO MAKE MORE EFFICIENT!! (Technically, not needed but should do so!) - if(sort_baseURLs) + if (sort_baseURLs) { - baseURLs.Sort(); + BaseURLs.Sort(); } - foreach (var baseurl in baseURLs) + foreach (var baseurl in BaseURLs) { w.Write("

    "); - w.WriteLine((baseurl as string).Replace(".","_") + "

    "); + w.WriteLine((baseurl as string).Replace(".", "_") + ""); var sw = new StringWriter(); int count = 0; - foreach (var tab in tabs)//NOTE TO SELF: TO DO : INEFFECCIENT AF, FIND DIFF METHOD + foreach (var tab in Tabs)//NOTE TO SELF: TO DO : INEFFECCIENT AF, FIND DIFF METHOD { - if ((tab as TabInf).baseWebsite == (baseurl as string)) + if ((tab as TabInf).BaseWebsite == (baseurl as string)) { count++; - sw.WriteLine("
    {1}", (tab as TabInf).url, (tab as TabInf).lastKnownTitle, DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString()); + sw.WriteLine("
    {1}", (tab as TabInf).URL, (tab as TabInf).LastKnownTitle, DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString()); //w.WriteLine("
  • {1}
  • ",(tab as TabInf).url, (tab as TabInf).lastKnownTitle); } } @@ -168,8 +214,11 @@ public string ExportToNetscapeBookmarksHTML(string outputfile = "", bool sort_ba return outputfile; } - private void ProcessTabs(bool PrintEnabled) + + + private void ProcessTabsFromTxts()//uses .txt files containing URL and titles respectively for constructing the list. This has basically been deprecated. { + bool printEnabled = ConfigHelper.Logging.EnablePrintingInTabsListProcessingFromTxts; Console.BackgroundColor = ConsoleColor.Black; Console.ForegroundColor = ConsoleColor.White; int urlsRead = 0, baseURLsRead = 0, titlesRead = 0, unprocessedLines = 0; @@ -182,32 +231,32 @@ private void ProcessTabs(bool PrintEnabled) { string lastKnownTitle = titleReader.ReadLine(); titlesRead++; - TabInf tab = new TabInf(line, "title-to-be-implemented",++TabCount); //ADD TITLE HERE SOMEHOW!! - tab.lastKnownTitle = lastKnownTitle; - tabs.Add(tab); + TabInf tab = new TabInf(line, "title-to-be-implemented", 1+TabCount);//++TabCount); //ADD TITLE HERE SOMEHOW!! + tab.LastKnownTitle = lastKnownTitle; + Tabs.Add(tab); //Might be able to get rid of the following if condition if I make a viable comparison operator,etc for sorting/grouping if (line.Contains("://")) //Note to self: TO DO? : replace with try catch then inform user some entries were not normal URLs? { urlsRead++; - if (!this.baseURLs.Contains(tab.baseWebsite)) + if (!this.BaseURLs.Contains(tab.BaseWebsite)) { baseURLsRead++; - this.baseURLs.Add(tab.baseWebsite); - if(PrintEnabled) + this.BaseURLs.Add(tab.BaseWebsite); + if(printEnabled) { Console.ForegroundColor = ConsoleColor.Magenta; Console.WriteLine("--new BaseURL found!--"); Console.ForegroundColor = ConsoleColor.White; } } - if(PrintEnabled) + if(printEnabled) { Console.ForegroundColor = ConsoleColor.DarkGray; - Console.Write("[BaseURL: "+tab.baseWebsite+"]"); + Console.Write("[BaseURL: "+tab.BaseWebsite+"]"); Console.ForegroundColor = ConsoleColor.White; Console.Write(line); Console.ForegroundColor = ConsoleColor.DarkGray; - Console.WriteLine("[Last Known Title: {0}]", tab.lastKnownTitle); + Console.WriteLine("[Last Known Title: {0}]", tab.LastKnownTitle); Console.ForegroundColor = ConsoleColor.White; } } @@ -218,7 +267,7 @@ private void ProcessTabs(bool PrintEnabled) //{ // this.baseURLs.Add(tab.baseWebsite); //} - if (PrintEnabled) + if (printEnabled) { Console.ForegroundColor = ConsoleColor.DarkYellow; Console.WriteLine("|--UNPROCESSED LINE:--| {0} [Last Known Title: {1}]", line,lastKnownTitle); @@ -226,7 +275,7 @@ private void ProcessTabs(bool PrintEnabled) } } } - if(PrintEnabled) + if(printEnabled) { Console.ForegroundColor = ConsoleColor.Magenta; Console.WriteLine("Total Lines Read: {0} |||| Lines read successfully: {1} |||| Total unique BaseURLs: {2}", urlsRead + unprocessedLines, urlsRead, baseURLsRead); @@ -235,7 +284,7 @@ private void ProcessTabs(bool PrintEnabled) //tabsProcessed = true; } } - tabsProcessed = true; + TabsProcessed = true; } private static string ReadPath(PathType type) { diff --git a/Data/GroupedBasicHtmlListTabsExporter.cs b/Data/GroupedBasicHtmlListTabsExporter.cs new file mode 100644 index 0000000..8b91ff6 --- /dev/null +++ b/Data/GroupedBasicHtmlListTabsExporter.cs @@ -0,0 +1,73 @@ +using ChromeDroid_TabMan.DTOs; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.IO; +using ChromeDroid_TabMan.Auxiliary; +using ChromeDroid_TabMan.Models; +using static System.Windows.Forms.VisualStyles.VisualStyleElement; +using System.Security.Principal; + +namespace ChromeDroid_TabMan.Data +{ + internal class GroupedBasicHtmlListTabsExporter : ITabsExporter + { + public string OutputFile { get; } + + public GroupedBasicHtmlListTabsExporter(string outputFile = "") + { + if (outputFile.Length == 0 || !outputFile.Trim('"').ToLower().EndsWith(".html")) + outputFile = ConfigHelper.FileNamesAndPaths.OutputPathDefaultExportDirectory + ConfigHelper.FileNamesAndPaths.ListDefaultFileName; + OutputFile = outputFile; + } + + public string Export(ITabsContainer tabsContainer) + { + string title = "Recovered tabs exported on " + DateTime.Now.ToString() + "."; + + using (FileStream fs = new FileStream(OutputFile, FileMode.Create)) + { + using (StreamWriter w = new StreamWriter(fs, Encoding.UTF8)) + { + w.WriteLine(""); + w.WriteLine(""+title+""); + w.WriteLine(""); + w.WriteLine("

    ----------------- TOTAL TABS RECOVERED= {0} -----------------

    ", tabsContainer.Count); + + List baseUrls = tabsContainer.BaseUrlToTabInfCollectionMap.Keys.ToList(); + if (ConfigHelper.SortGroupsInGroupedHtmlAndNetscapeBookmarksAlphabetically) + { + baseUrls.Sort(); + } + foreach (var baseurl in baseUrls) + { + w.Write("

    ", (baseurl as string)); + w.Write(baseurl as string); + w.WriteLine("

    "); + var sw = new StringWriter(); + int count = 0; + foreach (var tab in tabsContainer.BaseUrlToTabInfCollectionMap[baseurl]) + { + if ((tab as TabInf).BaseWebsite == (baseurl as string)) + { + count++; + sw.WriteLine("
  • {1}
  • ", (tab as TabInf).URL, (tab as TabInf).LastKnownTitle); + } + } + w.WriteLine("Count: {0}.", count); + w.WriteLine("
      "); + w.Write(sw.ToString()); + w.WriteLine("
    "); + } + w.WriteLine(""); + w.WriteLine(""); + w.Flush(); + } + } + + return OutputFile; + } + } +} diff --git a/Data/GroupedNetscapeHtmlBookmarksExporter.cs b/Data/GroupedNetscapeHtmlBookmarksExporter.cs new file mode 100644 index 0000000..4d82c38 --- /dev/null +++ b/Data/GroupedNetscapeHtmlBookmarksExporter.cs @@ -0,0 +1,174 @@ +using ChromeDroid_TabMan.Auxiliary; +using ChromeDroid_TabMan.DTOs; +using ChromeDroid_TabMan.Models; +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using static System.Windows.Forms.VisualStyles.VisualStyleElement; + +namespace ChromeDroid_TabMan.Data +{ + internal class GroupedNetscapeHtmlBookmarksExporter : ITabsExporter + { + public string OutputFile { get; } + + public GroupedNetscapeHtmlBookmarksExporter(string outputFile="") + { + if (outputFile.Length == 0 || !outputFile.Trim('"').ToLower().EndsWith(".html")) + outputFile = ConfigHelper.FileNamesAndPaths.OutputPathDefaultExportDirectory + ConfigHelper.FileNamesAndPaths.BookmarksGroupedDefaultFileName; + OutputFile= outputFile; + } + public string Export(ITabsContainer tabsContainer) + { + string title = "Recovered tabs exported on " + DateTime.Now.ToString() + "."; + + return ExportUsingCustomSolution_WithoutDates(tabsContainer, title); + } + + private string ExportUsingCustomSolution_WithoutDates(ITabsContainer tabsContainer, string title) //Supports nested folders. + { + using (FileStream fs = new FileStream(OutputFile, FileMode.Create)) + { + using (StreamWriter w = new StreamWriter(fs, Encoding.UTF8)) + { + w.WriteLine(""); + w.WriteLine(""); + w.WriteLine("\n" + + " Bookmarks \n" + + "

    Bookmarks

    "); + + w.WriteLine("

    "); + w.Write("

    "); + w.WriteLine(title + "

    "); + w.WriteLine("

    "); + + List baseUrls = tabsContainer.BaseUrlToTabInfCollectionMap.Keys.ToList(); + if (ConfigHelper.SortGroupsInGroupedHtmlAndNetscapeBookmarksAlphabetically) + { + baseUrls.Sort(); + } + foreach (var baseurl in baseUrls) + { + string dateTimeUnixTime = DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString(); + w.Write("

    "); + w.WriteLine((baseurl as string).Replace(".", "_") + "

    "); + + var sw = new StringWriter(); + int count = 0; + foreach (var tab in tabsContainer.BaseUrlToTabInfCollectionMap[baseurl]) + { + if ((tab as TabInf).BaseWebsite == (baseurl as string)) + { + count++; + sw.WriteLine("
    {1}", (tab as TabInf).URL, (tab as TabInf).LastKnownTitle); + } + } + w.WriteLine("

    "); + w.Write(sw.ToString()); + w.WriteLine("

    "); + } + w.WriteLine("

    "); + w.WriteLine("

    "); + w.Flush(); + } + } + + return OutputFile; + } + + private string ExportUsingCustomSolution(ITabsContainer tabsContainer, string title) //Supports nested folders. //Probably could get rid of the dates part. + { + using (FileStream fs = new FileStream(OutputFile, FileMode.Create)) + { + using (StreamWriter w = new StreamWriter(fs, Encoding.UTF8)) + { + w.WriteLine(""); + w.WriteLine(""); + w.WriteLine("\n" + + " Bookmarks \n" + + "

    Bookmarks

    "); + + w.WriteLine("

    "); + w.Write("

    "); + w.WriteLine(title + "

    "); + w.WriteLine("

    "); + + List baseUrls = tabsContainer.BaseUrlToTabInfCollectionMap.Keys.ToList(); + if (ConfigHelper.SortGroupsInGroupedHtmlAndNetscapeBookmarksAlphabetically) + { + baseUrls.Sort(); + } + foreach (var baseurl in baseUrls) + { + string dateTimeUnixTime = DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString(); + w.Write("

    "); + w.WriteLine((baseurl as string).Replace(".", "_") + "

    "); + + var sw = new StringWriter(); + int count = 0; + foreach (var tab in tabsContainer.BaseUrlToTabInfCollectionMap[baseurl]) + { + if ((tab as TabInf).BaseWebsite == (baseurl as string)) + { + count++; + sw.WriteLine("
    {1}", (tab as TabInf).URL, (tab as TabInf).LastKnownTitle, dateTimeUnixTime); + } + } + w.WriteLine("

    "); + w.Write(sw.ToString()); + w.WriteLine("

    "); + } + w.WriteLine("

    "); + w.WriteLine("

    "); + w.Flush(); + } + } + + return OutputFile; + } + + /* /// DOES NOT SUPPORT NESTED FOLDERS (apparently) + private string ExportUsingBookmarksManagerNugetPackage(TabsContainer tabsContainer, string title) //does not support nested folders apparently. + { + var bookmarks = new BookmarksManager.BookmarkFolder(title); + + List baseUrls = tabsContainer.BaseUrlToTabInfCollectionMap.Keys.ToList(); + if (ConfigHelper.SortGroupsInGroupedHtmlAndNetscapeBookmarksAlphabetically) + { + baseUrls.Sort(); + } + + foreach (var baseUrl in baseUrls) + { + var currFolder = new BookmarksManager.BookmarkFolder(baseUrl); + foreach (var tabInf in tabsContainer.BaseUrlToTabInfCollectionMap[baseUrl]) + { + var link = new BookmarksManager.BookmarkLink(tabInf.URL, tabInf.LastKnownTitle); + currFolder.Add(link); + } + bookmarks.Add(currFolder); + } + + + var writer = new BookmarksManager.NetscapeBookmarksWriter(bookmarks); + writer.OutputEncoding = Encoding.UTF8; //Encoding.GetEncoding(1257); + + + using (var file = File.Open(OutputFile, FileMode.Create)) + { + writer.Write(file); + } + + return OutputFile; + } + */ + } +} diff --git a/Data/ITabsExporter.cs b/Data/ITabsExporter.cs new file mode 100644 index 0000000..c08f292 --- /dev/null +++ b/Data/ITabsExporter.cs @@ -0,0 +1,15 @@ +using ChromeDroid_TabMan.DTOs; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ChromeDroid_TabMan.Data +{ + internal interface ITabsExporter + { + public string OutputFile { get; } + public string Export(ITabsContainer tabsContainer); + } +} diff --git a/Data/NetscapeHtmlBookmarksExporter.cs b/Data/NetscapeHtmlBookmarksExporter.cs new file mode 100644 index 0000000..663c9ce --- /dev/null +++ b/Data/NetscapeHtmlBookmarksExporter.cs @@ -0,0 +1,53 @@ +using ChromeDroid_TabMan.Auxiliary; +using ChromeDroid_TabMan.DTOs; +using ChromeDroid_TabMan.Models; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ChromeDroid_TabMan.Data +{ + internal class NetscapeHtmlBookmarksExporter : ITabsExporter + { + public string OutputFile { get; } + + public NetscapeHtmlBookmarksExporter(string outputFile = "") + { + if (outputFile.Length == 0 || !outputFile.Trim('"').ToLower().EndsWith(".html")) + outputFile = ConfigHelper.FileNamesAndPaths.OutputPathDefaultExportDirectory + ConfigHelper.FileNamesAndPaths.BookmarksDefaultFileName; + OutputFile= outputFile; + } + + public string Export(ITabsContainer tabsContainer) + { + string title = "Recovered tabs exported on " + DateTime.Now.ToString() + "."; + return ExportUsingBookmarksManagerNugetPackage(tabsContainer, title); + } + + private string ExportUsingBookmarksManagerNugetPackage(ITabsContainer tabsContainer, string title) //does not support nested folders apparently. + { + var bookmarks = new BookmarksManager.BookmarkFolder(title); + + foreach (TabInf tab in tabsContainer.AllTabInfs) + { + var link = new BookmarksManager.BookmarkLink(tab.URL, tab.LastKnownTitle); + bookmarks.Add(link); + } + + + var writer = new BookmarksManager.NetscapeBookmarksWriter(bookmarks); + writer.OutputEncoding = Encoding.UTF8; //Encoding.GetEncoding(1257); + + + using (var file = File.Open(OutputFile, FileMode.Create)) + { + writer.Write(file); + } + + return OutputFile; + } + } +} diff --git a/Data/SQLiteTabsExporter.cs b/Data/SQLiteTabsExporter.cs new file mode 100644 index 0000000..90f19ab --- /dev/null +++ b/Data/SQLiteTabsExporter.cs @@ -0,0 +1,35 @@ +using ChromeDroid_TabMan.Auxiliary; +using ChromeDroid_TabMan.DTOs; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ChromeDroid_TabMan.Data +{ + internal class SQLiteTabsExporter : ITabsExporter + { + TabsDbContext _tabsDbContext; + public string OutputFile { get; } + + public SQLiteTabsExporter(string outputFile="") + { + if (outputFile.Length == 0 || !outputFile.Trim('"').EndsWith(ConfigHelper.Database.DbFileExtensionWithDot)) + outputFile = ConfigHelper.FileNamesAndPaths.OutputPathDefaultExportDirectory + ConfigHelper.Database.DbFileName; + OutputFile = outputFile; + + _tabsDbContext = new TabsDbContext(OutputFile); + } + + public string Export(ITabsContainer tabsContainer) + { + System.IO.File.Delete(OutputFile); //Deletes if file already exists. //though due to having date in file name, it's impossible. + _tabsDbContext.Database.EnsureCreated(); + _tabsDbContext.Tabs.AddRange(tabsContainer.AllTabInfs); + _tabsDbContext.SaveChanges(); + + return OutputFile; + } + } +} diff --git a/Data/TabsDbContext.cs b/Data/TabsDbContext.cs new file mode 100644 index 0000000..f66a04d --- /dev/null +++ b/Data/TabsDbContext.cs @@ -0,0 +1,31 @@ +using ChromeDroid_TabMan.Auxiliary; +using ChromeDroid_TabMan.Models; +using Microsoft.EntityFrameworkCore; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ChromeDroid_TabMan.Data +{ + internal class TabsDbContext: DbContext + { + public DbSet Tabs { get; set; } + + public string DbPath { get; } + + public TabsDbContext(string dbPath) + { + //var folder = Environment.SpecialFolder.LocalApplicationData; + //var path = Environment.GetFolderPath(folder); + //DbPath = System.IO.Path.Join(path, "tabs.db"); + + DbPath = dbPath; + } + + // The following configures EF to create a Sqlite database file. + protected override void OnConfiguring(DbContextOptionsBuilder options) + => options.UseSqlite($"Data Source={DbPath}"); + } +} diff --git a/Form1.Designer.cs b/Form1.Designer.cs index 8f5aec9..768fa65 100644 --- a/Form1.Designer.cs +++ b/Form1.Designer.cs @@ -1,5 +1,4 @@ - -namespace ChromeDroid_TabMan +namespace ChromeDroid_TabMan { partial class MainForm { @@ -29,8 +28,9 @@ protected override void Dispose(bool disposing) /// private void InitializeComponent() { - System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle13 = new System.Windows.Forms.DataGridViewCellStyle(); - System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle14 = new System.Windows.Forms.DataGridViewCellStyle(); + this.components = new System.ComponentModel.Container(); + System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle1 = new System.Windows.Forms.DataGridViewCellStyle(); + System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle2 = new System.Windows.Forms.DataGridViewCellStyle(); this.tabListTree = new System.Windows.Forms.TreeView(); this.tabControl1 = new System.Windows.Forms.TabControl(); this.tabPosList = new System.Windows.Forms.TabPage(); @@ -39,16 +39,22 @@ private void InitializeComponent() this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel(); this.groupBox1 = new System.Windows.Forms.GroupBox(); this.tableLayoutPanel3 = new System.Windows.Forms.TableLayoutPanel(); + this.button_ExportAsBookmarks = new System.Windows.Forms.Button(); + this.button_exportCSV = new System.Windows.Forms.Button(); + this.button_ExportAsSQLiteDB = new System.Windows.Forms.Button(); + this.button_ExportAsBookmarksGrouped = new System.Windows.Forms.Button(); + this.button_exportListHTMLGrouped = new System.Windows.Forms.Button(); this.importAndProcessGroupbox = new System.Windows.Forms.GroupBox(); + this.linkLabel1 = new System.Windows.Forms.LinkLabel(); this.button_ImportAndProcess = new System.Windows.Forms.Button(); this.connectGroupBox = new System.Windows.Forms.GroupBox(); + this.button_ManuallyDiscoverDevToolsSockets = new System.Windows.Forms.Button(); this.tableLayoutPanel2 = new System.Windows.Forms.TableLayoutPanel(); this.label1 = new System.Windows.Forms.Label(); this.button_connectfetchjson = new System.Windows.Forms.Button(); this.button_selectjson = new System.Windows.Forms.Button(); - this.button_exportListHTML = new System.Windows.Forms.Button(); - this.button_ExportAsBookmarks = new System.Windows.Forms.Button(); - this.linkLabel1 = new System.Windows.Forms.LinkLabel(); + this.comboBox_BrowserSelect = new System.Windows.Forms.ComboBox(); + this.browserDetailsBindingSource = new System.Windows.Forms.BindingSource(this.components); this.tabControl1.SuspendLayout(); this.tabPosList.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).BeginInit(); @@ -59,6 +65,7 @@ private void InitializeComponent() this.importAndProcessGroupbox.SuspendLayout(); this.connectGroupBox.SuspendLayout(); this.tableLayoutPanel2.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.browserDetailsBindingSource)).BeginInit(); this.SuspendLayout(); // // tabListTree @@ -66,7 +73,7 @@ private void InitializeComponent() this.tabListTree.Dock = System.Windows.Forms.DockStyle.Fill; this.tabListTree.Location = new System.Drawing.Point(3, 3); this.tabListTree.Name = "tabListTree"; - this.tabListTree.Size = new System.Drawing.Size(780, 292); + this.tabListTree.Size = new System.Drawing.Size(1242, 459); this.tabListTree.TabIndex = 0; // // tabControl1 @@ -79,7 +86,7 @@ private void InitializeComponent() this.tabControl1.Location = new System.Drawing.Point(3, 3); this.tabControl1.Name = "tabControl1"; this.tabControl1.SelectedIndex = 0; - this.tabControl1.Size = new System.Drawing.Size(794, 331); + this.tabControl1.Size = new System.Drawing.Size(1256, 498); this.tabControl1.TabIndex = 1; // // tabPosList @@ -88,7 +95,7 @@ private void InitializeComponent() this.tabPosList.Location = new System.Drawing.Point(4, 29); this.tabPosList.Name = "tabPosList"; this.tabPosList.Padding = new System.Windows.Forms.Padding(3); - this.tabPosList.Size = new System.Drawing.Size(786, 298); + this.tabPosList.Size = new System.Drawing.Size(1248, 465); this.tabPosList.TabIndex = 1; this.tabPosList.Text = "Tab List"; this.tabPosList.UseVisualStyleBackColor = true; @@ -97,30 +104,30 @@ private void InitializeComponent() // this.dataGridView1.AutoSizeColumnsMode = System.Windows.Forms.DataGridViewAutoSizeColumnsMode.Fill; this.dataGridView1.BackgroundColor = System.Drawing.Color.White; - dataGridViewCellStyle13.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft; - dataGridViewCellStyle13.BackColor = System.Drawing.Color.LightBlue; - dataGridViewCellStyle13.Font = new System.Drawing.Font("Segoe UI Semibold", 9F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point); - dataGridViewCellStyle13.ForeColor = System.Drawing.SystemColors.WindowText; - dataGridViewCellStyle13.SelectionBackColor = System.Drawing.SystemColors.Highlight; - dataGridViewCellStyle13.SelectionForeColor = System.Drawing.SystemColors.HighlightText; - dataGridViewCellStyle13.WrapMode = System.Windows.Forms.DataGridViewTriState.True; - this.dataGridView1.ColumnHeadersDefaultCellStyle = dataGridViewCellStyle13; + dataGridViewCellStyle1.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft; + dataGridViewCellStyle1.BackColor = System.Drawing.Color.LightBlue; + dataGridViewCellStyle1.Font = new System.Drawing.Font("Segoe UI Semibold", 9F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point); + dataGridViewCellStyle1.ForeColor = System.Drawing.SystemColors.WindowText; + dataGridViewCellStyle1.SelectionBackColor = System.Drawing.SystemColors.Highlight; + dataGridViewCellStyle1.SelectionForeColor = System.Drawing.SystemColors.HighlightText; + dataGridViewCellStyle1.WrapMode = System.Windows.Forms.DataGridViewTriState.True; + this.dataGridView1.ColumnHeadersDefaultCellStyle = dataGridViewCellStyle1; this.dataGridView1.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize; - dataGridViewCellStyle14.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft; - dataGridViewCellStyle14.BackColor = System.Drawing.SystemColors.Window; - dataGridViewCellStyle14.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - dataGridViewCellStyle14.ForeColor = System.Drawing.SystemColors.ControlText; - dataGridViewCellStyle14.SelectionBackColor = System.Drawing.SystemColors.Highlight; - dataGridViewCellStyle14.SelectionForeColor = System.Drawing.SystemColors.HighlightText; - dataGridViewCellStyle14.WrapMode = System.Windows.Forms.DataGridViewTriState.False; - this.dataGridView1.DefaultCellStyle = dataGridViewCellStyle14; + dataGridViewCellStyle2.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft; + dataGridViewCellStyle2.BackColor = System.Drawing.SystemColors.Window; + dataGridViewCellStyle2.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + dataGridViewCellStyle2.ForeColor = System.Drawing.SystemColors.ControlText; + dataGridViewCellStyle2.SelectionBackColor = System.Drawing.SystemColors.Highlight; + dataGridViewCellStyle2.SelectionForeColor = System.Drawing.SystemColors.HighlightText; + dataGridViewCellStyle2.WrapMode = System.Windows.Forms.DataGridViewTriState.False; + this.dataGridView1.DefaultCellStyle = dataGridViewCellStyle2; this.dataGridView1.Dock = System.Windows.Forms.DockStyle.Fill; this.dataGridView1.GridColor = System.Drawing.SystemColors.ControlDarkDark; this.dataGridView1.Location = new System.Drawing.Point(3, 3); this.dataGridView1.Name = "dataGridView1"; this.dataGridView1.RowHeadersWidth = 51; this.dataGridView1.RowTemplate.Height = 29; - this.dataGridView1.Size = new System.Drawing.Size(780, 292); + this.dataGridView1.Size = new System.Drawing.Size(1242, 459); this.dataGridView1.TabIndex = 0; // // tabTreeView @@ -131,7 +138,7 @@ private void InitializeComponent() this.tabTreeView.Location = new System.Drawing.Point(4, 29); this.tabTreeView.Name = "tabTreeView"; this.tabTreeView.Padding = new System.Windows.Forms.Padding(3); - this.tabTreeView.Size = new System.Drawing.Size(786, 298); + this.tabTreeView.Size = new System.Drawing.Size(1248, 465); this.tabTreeView.TabIndex = 0; this.tabTreeView.Text = "Tab Tree View"; this.tabTreeView.UseVisualStyleBackColor = true; @@ -152,7 +159,7 @@ private void InitializeComponent() this.tableLayoutPanel1.RowCount = 2; this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 75F)); this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 25F)); - this.tableLayoutPanel1.Size = new System.Drawing.Size(800, 450); + this.tableLayoutPanel1.Size = new System.Drawing.Size(1262, 673); this.tableLayoutPanel1.TabIndex = 2; this.tableLayoutPanel1.Paint += new System.Windows.Forms.PaintEventHandler(this.tableLayoutPanel1_Paint); // @@ -162,9 +169,9 @@ private void InitializeComponent() this.groupBox1.Dock = System.Windows.Forms.DockStyle.Fill; this.groupBox1.Font = new System.Drawing.Font("Segoe UI", 9F, ((System.Drawing.FontStyle)((System.Drawing.FontStyle.Bold | System.Drawing.FontStyle.Italic))), System.Drawing.GraphicsUnit.Point); this.groupBox1.ForeColor = System.Drawing.Color.White; - this.groupBox1.Location = new System.Drawing.Point(531, 340); + this.groupBox1.Location = new System.Drawing.Point(835, 507); this.groupBox1.Name = "groupBox1"; - this.groupBox1.Size = new System.Drawing.Size(266, 107); + this.groupBox1.Size = new System.Drawing.Size(424, 163); this.groupBox1.TabIndex = 4; this.groupBox1.TabStop = false; this.groupBox1.Text = "Export Tabs"; @@ -172,34 +179,133 @@ private void InitializeComponent() // // tableLayoutPanel3 // - this.tableLayoutPanel3.ColumnCount = 1; - this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); - this.tableLayoutPanel3.Controls.Add(this.button_ExportAsBookmarks, 0, 1); - this.tableLayoutPanel3.Controls.Add(this.button_exportListHTML, 0, 0); - this.tableLayoutPanel3.Controls.Add(this.linkLabel1, 0, 2); - this.tableLayoutPanel3.Dock = System.Windows.Forms.DockStyle.Fill; + this.tableLayoutPanel3.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.tableLayoutPanel3.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; + this.tableLayoutPanel3.ColumnCount = 2; + this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F)); + this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F)); + this.tableLayoutPanel3.Controls.Add(this.button_ExportAsBookmarks, 2, 1); + this.tableLayoutPanel3.Controls.Add(this.button_exportCSV, 1, 0); + this.tableLayoutPanel3.Controls.Add(this.button_ExportAsSQLiteDB, 0, 2); + this.tableLayoutPanel3.Controls.Add(this.button_ExportAsBookmarksGrouped, 0, 1); + this.tableLayoutPanel3.Controls.Add(this.button_exportListHTMLGrouped, 0, 0); this.tableLayoutPanel3.Location = new System.Drawing.Point(3, 23); this.tableLayoutPanel3.Name = "tableLayoutPanel3"; this.tableLayoutPanel3.RowCount = 3; - this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 40F)); - this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 40F)); - this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 20F)); - this.tableLayoutPanel3.Size = new System.Drawing.Size(260, 81); + this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 33.33333F)); + this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 33.33333F)); + this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 33.33333F)); + this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); + this.tableLayoutPanel3.Size = new System.Drawing.Size(418, 137); this.tableLayoutPanel3.TabIndex = 0; // + // button_ExportAsBookmarks + // + this.button_ExportAsBookmarks.AutoSize = true; + this.button_ExportAsBookmarks.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; + this.button_ExportAsBookmarks.Dock = System.Windows.Forms.DockStyle.Fill; + this.button_ExportAsBookmarks.Font = new System.Drawing.Font("Segoe UI Semibold", 8F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point); + this.button_ExportAsBookmarks.ForeColor = System.Drawing.Color.Black; + this.button_ExportAsBookmarks.Location = new System.Drawing.Point(212, 48); + this.button_ExportAsBookmarks.Name = "button_ExportAsBookmarks"; + this.button_ExportAsBookmarks.Size = new System.Drawing.Size(203, 39); + this.button_ExportAsBookmarks.TabIndex = 4; + this.button_ExportAsBookmarks.Text = "To Bookmarks"; + this.button_ExportAsBookmarks.UseVisualStyleBackColor = true; + this.button_ExportAsBookmarks.Click += new System.EventHandler(this.button_ExportAsBookmarks_Click); + // + // button_exportCSV + // + this.button_exportCSV.AutoSize = true; + this.button_exportCSV.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; + this.button_exportCSV.Dock = System.Windows.Forms.DockStyle.Fill; + this.button_exportCSV.Font = new System.Drawing.Font("Segoe UI Semibold", 8F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point); + this.button_exportCSV.ForeColor = System.Drawing.Color.Black; + this.button_exportCSV.Location = new System.Drawing.Point(212, 3); + this.button_exportCSV.Name = "button_exportCSV"; + this.button_exportCSV.Size = new System.Drawing.Size(203, 39); + this.button_exportCSV.TabIndex = 3; + this.button_exportCSV.Text = "To CSV Text File"; + this.button_exportCSV.UseVisualStyleBackColor = true; + this.button_exportCSV.Click += new System.EventHandler(this.button_exportCSV_Click); + // + // button_ExportAsSQLiteDB + // + this.button_ExportAsSQLiteDB.AutoSize = true; + this.button_ExportAsSQLiteDB.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; + this.tableLayoutPanel3.SetColumnSpan(this.button_ExportAsSQLiteDB, 2); + this.button_ExportAsSQLiteDB.Dock = System.Windows.Forms.DockStyle.Fill; + this.button_ExportAsSQLiteDB.Font = new System.Drawing.Font("Segoe UI Semibold", 8F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point); + this.button_ExportAsSQLiteDB.ForeColor = System.Drawing.Color.Black; + this.button_ExportAsSQLiteDB.Location = new System.Drawing.Point(3, 93); + this.button_ExportAsSQLiteDB.Name = "button_ExportAsSQLiteDB"; + this.button_ExportAsSQLiteDB.Size = new System.Drawing.Size(412, 41); + this.button_ExportAsSQLiteDB.TabIndex = 2; + this.button_ExportAsSQLiteDB.Text = "Export as SQLite DB"; + this.button_ExportAsSQLiteDB.UseVisualStyleBackColor = true; + this.button_ExportAsSQLiteDB.Click += new System.EventHandler(this.button_ExportAsSQLiteDB_Click); + // + // button_ExportAsBookmarksGrouped + // + this.button_ExportAsBookmarksGrouped.AutoSize = true; + this.button_ExportAsBookmarksGrouped.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; + this.button_ExportAsBookmarksGrouped.Dock = System.Windows.Forms.DockStyle.Fill; + this.button_ExportAsBookmarksGrouped.Font = new System.Drawing.Font("Segoe UI Semibold", 8F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point); + this.button_ExportAsBookmarksGrouped.ForeColor = System.Drawing.Color.Black; + this.button_ExportAsBookmarksGrouped.Location = new System.Drawing.Point(3, 48); + this.button_ExportAsBookmarksGrouped.Name = "button_ExportAsBookmarksGrouped"; + this.button_ExportAsBookmarksGrouped.Size = new System.Drawing.Size(203, 39); + this.button_ExportAsBookmarksGrouped.TabIndex = 1; + this.button_ExportAsBookmarksGrouped.Text = "To Bookmarks (Grouped)"; + this.button_ExportAsBookmarksGrouped.UseVisualStyleBackColor = true; + this.button_ExportAsBookmarksGrouped.Click += new System.EventHandler(this.button_ExportAsBookmarksGrouped_Click); + // + // button_exportListHTMLGrouped + // + this.button_exportListHTMLGrouped.AutoSize = true; + this.button_exportListHTMLGrouped.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; + this.button_exportListHTMLGrouped.Dock = System.Windows.Forms.DockStyle.Fill; + this.button_exportListHTMLGrouped.Font = new System.Drawing.Font("Segoe UI Semibold", 8F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point); + this.button_exportListHTMLGrouped.ForeColor = System.Drawing.Color.Black; + this.button_exportListHTMLGrouped.Location = new System.Drawing.Point(3, 3); + this.button_exportListHTMLGrouped.Name = "button_exportListHTMLGrouped"; + this.button_exportListHTMLGrouped.Size = new System.Drawing.Size(203, 39); + this.button_exportListHTMLGrouped.TabIndex = 0; + this.button_exportListHTMLGrouped.Text = "To HTML List (Grouped)"; + this.button_exportListHTMLGrouped.UseVisualStyleBackColor = true; + this.button_exportListHTMLGrouped.Click += new System.EventHandler(this.button_exportListHTMLGrouped_Click); + // // importAndProcessGroupbox // + this.importAndProcessGroupbox.Controls.Add(this.linkLabel1); this.importAndProcessGroupbox.Controls.Add(this.button_ImportAndProcess); this.importAndProcessGroupbox.Dock = System.Windows.Forms.DockStyle.Fill; this.importAndProcessGroupbox.Font = new System.Drawing.Font("Segoe UI", 9F, ((System.Drawing.FontStyle)((System.Drawing.FontStyle.Bold | System.Drawing.FontStyle.Italic))), System.Drawing.GraphicsUnit.Point); this.importAndProcessGroupbox.ForeColor = System.Drawing.Color.White; - this.importAndProcessGroupbox.Location = new System.Drawing.Point(267, 340); + this.importAndProcessGroupbox.Location = new System.Drawing.Point(419, 507); this.importAndProcessGroupbox.Name = "importAndProcessGroupbox"; - this.importAndProcessGroupbox.Size = new System.Drawing.Size(258, 107); + this.importAndProcessGroupbox.Size = new System.Drawing.Size(410, 163); this.importAndProcessGroupbox.TabIndex = 3; this.importAndProcessGroupbox.TabStop = false; this.importAndProcessGroupbox.Text = "Tabs Import and Processing"; // + // linkLabel1 + // + this.linkLabel1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.linkLabel1.AutoSize = true; + this.linkLabel1.Font = new System.Drawing.Font("Segoe UI Semilight", 7.8F, System.Drawing.FontStyle.Italic, System.Drawing.GraphicsUnit.Point); + this.linkLabel1.LinkColor = System.Drawing.Color.LightSkyBlue; + this.linkLabel1.Location = new System.Drawing.Point(161, 140); + this.linkLabel1.Name = "linkLabel1"; + this.linkLabel1.Size = new System.Drawing.Size(87, 17); + this.linkLabel1.TabIndex = 3; + this.linkLabel1.TabStop = true; + this.linkLabel1.Text = "nomi.github.io"; + this.linkLabel1.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + // // button_ImportAndProcess // this.button_ImportAndProcess.Dock = System.Windows.Forms.DockStyle.Top; @@ -207,7 +313,7 @@ private void InitializeComponent() this.button_ImportAndProcess.ForeColor = System.Drawing.Color.Black; this.button_ImportAndProcess.Location = new System.Drawing.Point(3, 23); this.button_ImportAndProcess.Name = "button_ImportAndProcess"; - this.button_ImportAndProcess.Size = new System.Drawing.Size(252, 29); + this.button_ImportAndProcess.Size = new System.Drawing.Size(404, 29); this.button_ImportAndProcess.TabIndex = 0; this.button_ImportAndProcess.Text = "Import and Process"; this.button_ImportAndProcess.UseVisualStyleBackColor = true; @@ -215,60 +321,77 @@ private void InitializeComponent() // // connectGroupBox // + this.connectGroupBox.Controls.Add(this.button_ManuallyDiscoverDevToolsSockets); this.connectGroupBox.Controls.Add(this.tableLayoutPanel2); this.connectGroupBox.Dock = System.Windows.Forms.DockStyle.Fill; this.connectGroupBox.Font = new System.Drawing.Font("Segoe UI", 9F, ((System.Drawing.FontStyle)((System.Drawing.FontStyle.Bold | System.Drawing.FontStyle.Italic))), System.Drawing.GraphicsUnit.Point); this.connectGroupBox.ForeColor = System.Drawing.Color.Orange; - this.connectGroupBox.Location = new System.Drawing.Point(3, 340); + this.connectGroupBox.Location = new System.Drawing.Point(3, 507); this.connectGroupBox.Name = "connectGroupBox"; - this.connectGroupBox.Size = new System.Drawing.Size(258, 107); + this.connectGroupBox.Size = new System.Drawing.Size(410, 163); this.connectGroupBox.TabIndex = 2; this.connectGroupBox.TabStop = false; this.connectGroupBox.Text = "Device Connection"; this.connectGroupBox.Enter += new System.EventHandler(this.groupBox1_Enter); // + // button_ManuallyDiscoverDevToolsSockets + // + this.button_ManuallyDiscoverDevToolsSockets.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.button_ManuallyDiscoverDevToolsSockets.BackColor = System.Drawing.SystemColors.Info; + this.button_ManuallyDiscoverDevToolsSockets.Font = new System.Drawing.Font("Segoe UI Light", 7.8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.button_ManuallyDiscoverDevToolsSockets.ForeColor = System.Drawing.Color.Black; + this.button_ManuallyDiscoverDevToolsSockets.Location = new System.Drawing.Point(202, -4); + this.button_ManuallyDiscoverDevToolsSockets.Name = "button_ManuallyDiscoverDevToolsSockets"; + this.button_ManuallyDiscoverDevToolsSockets.Size = new System.Drawing.Size(202, 24); + this.button_ManuallyDiscoverDevToolsSockets.TabIndex = 4; + this.button_ManuallyDiscoverDevToolsSockets.Text = "Fix or Discover DevTools Sockets"; + this.button_ManuallyDiscoverDevToolsSockets.UseVisualStyleBackColor = false; + this.button_ManuallyDiscoverDevToolsSockets.Click += new System.EventHandler(this.button_FixOrDiscoverDevToolsSockets_Click); + // // tableLayoutPanel2 // this.tableLayoutPanel2.ColumnCount = 1; this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); - this.tableLayoutPanel2.Controls.Add(this.label1, 0, 1); - this.tableLayoutPanel2.Controls.Add(this.button_connectfetchjson, 0, 0); - this.tableLayoutPanel2.Controls.Add(this.button_selectjson, 0, 2); + this.tableLayoutPanel2.Controls.Add(this.label1, 0, 2); + this.tableLayoutPanel2.Controls.Add(this.button_connectfetchjson, 0, 1); + this.tableLayoutPanel2.Controls.Add(this.button_selectjson, 0, 3); + this.tableLayoutPanel2.Controls.Add(this.comboBox_BrowserSelect, 0, 0); this.tableLayoutPanel2.Dock = System.Windows.Forms.DockStyle.Fill; this.tableLayoutPanel2.Location = new System.Drawing.Point(3, 23); this.tableLayoutPanel2.Name = "tableLayoutPanel2"; - this.tableLayoutPanel2.RowCount = 3; - this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 40F)); + this.tableLayoutPanel2.RowCount = 4; this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 20F)); - this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 40F)); - this.tableLayoutPanel2.Size = new System.Drawing.Size(252, 81); + this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 35F)); + this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 10F)); + this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 35F)); + this.tableLayoutPanel2.Size = new System.Drawing.Size(404, 137); this.tableLayoutPanel2.TabIndex = 0; // // label1 // - this.label1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) - | System.Windows.Forms.AnchorStyles.Left) - | System.Windows.Forms.AnchorStyles.Right))); this.label1.AutoSize = true; + this.label1.Dock = System.Windows.Forms.DockStyle.Fill; this.label1.Font = new System.Drawing.Font("Segoe UI", 7.8F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point); this.label1.ForeColor = System.Drawing.Color.AliceBlue; - this.label1.Location = new System.Drawing.Point(3, 32); + this.label1.Location = new System.Drawing.Point(3, 74); this.label1.Name = "label1"; - this.label1.Size = new System.Drawing.Size(246, 16); + this.label1.Size = new System.Drawing.Size(398, 13); this.label1.TabIndex = 0; this.label1.Text = "--- OR ---"; this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; // // button_connectfetchjson // - this.button_connectfetchjson.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) - | System.Windows.Forms.AnchorStyles.Left) - | System.Windows.Forms.AnchorStyles.Right))); + this.button_connectfetchjson.AutoSize = true; + this.button_connectfetchjson.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; + this.button_connectfetchjson.Dock = System.Windows.Forms.DockStyle.Fill; this.button_connectfetchjson.Font = new System.Drawing.Font("Segoe UI Semibold", 9F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point); this.button_connectfetchjson.ForeColor = System.Drawing.SystemColors.WindowText; - this.button_connectfetchjson.Location = new System.Drawing.Point(3, 3); + this.button_connectfetchjson.Location = new System.Drawing.Point(3, 30); this.button_connectfetchjson.Name = "button_connectfetchjson"; - this.button_connectfetchjson.Size = new System.Drawing.Size(246, 26); + this.button_connectfetchjson.Size = new System.Drawing.Size(398, 41); this.button_connectfetchjson.TabIndex = 1; this.button_connectfetchjson.Text = "Connect and Fetch JSON"; this.button_connectfetchjson.UseVisualStyleBackColor = true; @@ -276,65 +399,37 @@ private void InitializeComponent() // // button_selectjson // - this.button_selectjson.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) - | System.Windows.Forms.AnchorStyles.Left) - | System.Windows.Forms.AnchorStyles.Right))); + this.button_selectjson.AutoSize = true; + this.button_selectjson.Dock = System.Windows.Forms.DockStyle.Fill; this.button_selectjson.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.button_selectjson.ForeColor = System.Drawing.SystemColors.WindowText; - this.button_selectjson.Location = new System.Drawing.Point(3, 51); + this.button_selectjson.Location = new System.Drawing.Point(3, 90); this.button_selectjson.Name = "button_selectjson"; - this.button_selectjson.Size = new System.Drawing.Size(246, 27); + this.button_selectjson.Size = new System.Drawing.Size(398, 44); this.button_selectjson.TabIndex = 2; this.button_selectjson.Text = "Select pre-fetched JSON"; this.button_selectjson.UseVisualStyleBackColor = true; this.button_selectjson.Click += new System.EventHandler(this.button_selectjson_Click); // - // button_exportListHTML + // comboBox_BrowserSelect // - this.button_exportListHTML.Dock = System.Windows.Forms.DockStyle.Fill; - this.button_exportListHTML.Font = new System.Drawing.Font("Segoe UI Semilight", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - this.button_exportListHTML.ForeColor = System.Drawing.Color.Black; - this.button_exportListHTML.Location = new System.Drawing.Point(3, 3); - this.button_exportListHTML.Name = "button_exportListHTML"; - this.button_exportListHTML.Size = new System.Drawing.Size(254, 26); - this.button_exportListHTML.TabIndex = 0; - this.button_exportListHTML.Text = "Export as List (grouped)"; - this.button_exportListHTML.UseVisualStyleBackColor = true; - this.button_exportListHTML.Click += new System.EventHandler(this.button_exportListHTML_Click); - // - // button_ExportAsBookmarks + this.comboBox_BrowserSelect.BackColor = System.Drawing.SystemColors.Info; + this.comboBox_BrowserSelect.FormattingEnabled = true; + this.comboBox_BrowserSelect.Location = new System.Drawing.Point(3, 3); + this.comboBox_BrowserSelect.Name = "comboBox_BrowserSelect"; + this.comboBox_BrowserSelect.Size = new System.Drawing.Size(398, 28); + this.comboBox_BrowserSelect.TabIndex = 3; // - this.button_ExportAsBookmarks.Dock = System.Windows.Forms.DockStyle.Fill; - this.button_ExportAsBookmarks.Font = new System.Drawing.Font("Segoe UI Semibold", 9F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point); - this.button_ExportAsBookmarks.ForeColor = System.Drawing.Color.Black; - this.button_ExportAsBookmarks.Location = new System.Drawing.Point(3, 35); - this.button_ExportAsBookmarks.Name = "button_ExportAsBookmarks"; - this.button_ExportAsBookmarks.Size = new System.Drawing.Size(254, 26); - this.button_ExportAsBookmarks.TabIndex = 1; - this.button_ExportAsBookmarks.Text = "Export as Bookmarks"; - this.button_ExportAsBookmarks.UseVisualStyleBackColor = true; - this.button_ExportAsBookmarks.Click += new System.EventHandler(this.button_ExportAsBookmarks_Click); - // - // linkLabel1 + // browserDetailsBindingSource // - this.linkLabel1.AutoSize = true; - this.linkLabel1.Dock = System.Windows.Forms.DockStyle.Fill; - this.linkLabel1.Font = new System.Drawing.Font("Segoe UI Semilight", 7.8F, System.Drawing.FontStyle.Italic, System.Drawing.GraphicsUnit.Point); - this.linkLabel1.LinkColor = System.Drawing.Color.LightSkyBlue; - this.linkLabel1.Location = new System.Drawing.Point(3, 64); - this.linkLabel1.Name = "linkLabel1"; - this.linkLabel1.Size = new System.Drawing.Size(254, 17); - this.linkLabel1.TabIndex = 2; - this.linkLabel1.TabStop = true; - this.linkLabel1.Text = "nomi.github.io"; - this.linkLabel1.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + this.browserDetailsBindingSource.CurrentChanged += new System.EventHandler(this.browserDetailsBindingSource_CurrentChanged); // // MainForm // this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 20F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(0)))), ((int)(((byte)(0))))); - this.ClientSize = new System.Drawing.Size(800, 450); + this.ClientSize = new System.Drawing.Size(1262, 673); this.Controls.Add(this.tableLayoutPanel1); this.Name = "MainForm"; this.Text = "ChromeDroid TabMan"; @@ -347,9 +442,11 @@ private void InitializeComponent() this.tableLayoutPanel3.ResumeLayout(false); this.tableLayoutPanel3.PerformLayout(); this.importAndProcessGroupbox.ResumeLayout(false); + this.importAndProcessGroupbox.PerformLayout(); this.connectGroupBox.ResumeLayout(false); this.tableLayoutPanel2.ResumeLayout(false); this.tableLayoutPanel2.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.browserDetailsBindingSource)).EndInit(); this.ResumeLayout(false); } @@ -365,15 +462,21 @@ private void InitializeComponent() private System.Windows.Forms.GroupBox connectGroupBox; private System.Windows.Forms.GroupBox groupBox1; private System.Windows.Forms.GroupBox importAndProcessGroupbox; + private System.Windows.Forms.Button button_ImportAndProcess; + private System.Windows.Forms.TableLayoutPanel tableLayoutPanel3; + private System.Windows.Forms.LinkLabel linkLabel1; + private System.Windows.Forms.Button button_ExportAsSQLiteDB; + private System.Windows.Forms.Button button_ExportAsBookmarks; + private System.Windows.Forms.Button button_exportCSV; + private System.Windows.Forms.Button button_ExportAsBookmarksGrouped; + private System.Windows.Forms.Button button_exportListHTMLGrouped; private System.Windows.Forms.TableLayoutPanel tableLayoutPanel2; private System.Windows.Forms.Label label1; private System.Windows.Forms.Button button_connectfetchjson; private System.Windows.Forms.Button button_selectjson; - private System.Windows.Forms.Button button_ImportAndProcess; - private System.Windows.Forms.TableLayoutPanel tableLayoutPanel3; - private System.Windows.Forms.Button button_ExportAsBookmarks; - private System.Windows.Forms.Button button_exportListHTML; - private System.Windows.Forms.LinkLabel linkLabel1; + private System.Windows.Forms.ComboBox comboBox_BrowserSelect; + private System.Windows.Forms.BindingSource browserDetailsBindingSource; + private System.Windows.Forms.Button button_ManuallyDiscoverDevToolsSockets; } } diff --git a/Form1.cs b/Form1.cs index 7e8eef8..d2c18ea 100644 --- a/Form1.cs +++ b/Form1.cs @@ -2,29 +2,43 @@ using System.Collections.Generic; using System.Data; using System.Drawing; +using System.Threading.Tasks; using System.Windows.Forms; +using ChromeDroid_TabMan.Data; +using ChromeDroid_TabMan.Models; +using Microsoft.EntityFrameworkCore; +using ChromeDroid_TabMan.Auxiliary; +using AdvancedSharpAdbClient; +using ChromeDroid_TabMan.Connection_and_Import; +using ChromeDroid_TabMan.DTOs; +using System.Linq; namespace ChromeDroid_TabMan { public partial class MainForm : Form { - TabsList tabbys =null; - string manuallySetJsonLocation = string.Empty; + string AdbPath { get; set; } + string jsonLocation = string.Empty; DataTable dt = new DataTable(); + ITabsContainer tabsContainer =null; + public MainForm() { - dt.Columns.Add("Tab Position"); + dt.Columns.Add("TabNum",typeof(int)); dt.Columns.Add("Title"); dt.Columns.Add("URL"); dt.Columns.Add("Base URL"); - InitializeComponent(); + InitializeComponent(); + + WinFormsUtils.InitializeOrResetBrowserListComboBox(comboBox_BrowserSelect); - //FillMyTreeView(tabbys); - //tabbys.ExportToHTML(); - //tabbys.ExportToNetscapeBookmarksHTML(); + //var tabsList = TabsList.GetInstance(); + //FillMyTreeView(tabsList); + //tabsList.ExportToHTML(); + //tabsList.ExportToNetscapeBookmarksHTML(); } //private void dataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e) @@ -42,38 +56,17 @@ public MainForm() // // End If // //End If //} - private void FillMyTreeView(TabsList tabs) + private void FillMyTreeView() { - List gtl = new List(tabs.tabs); - - gtl.Sort(); tabListTree.BeginUpdate(); - List basur = new List(tabs.baseURLs); - basur.Sort(); - tabListTree.Nodes.Add(new TreeNode("**Unidentified BaseURLs**")); - foreach (string baseUrl in basur) + int baseUrlIdx = 0; + foreach (var baseUrl in tabsContainer.BaseUrlToTabInfCollectionMap.Keys) { + var currMap = tabsContainer.BaseUrlToTabInfCollectionMap; tabListTree.Nodes.Add(new TreeNode(baseUrl)); int childNodesCount=0; - foreach (TabInf t in gtl) - { - if (t.baseWebsite!=baseUrl) - { - if(!basur.Contains(t.baseWebsite)) - { - childNodesCount++; - tabListTree.Nodes[0].Nodes.Add(new TreeNode(t.url)); - } - else - { - break; - } - } - tabListTree.Nodes[basur.IndexOf(baseUrl)+1] - .Nodes.Add(new TreeNode(t.url)); - childNodesCount++; - } - gtl.RemoveRange(0, childNodesCount); + tabListTree.Nodes[baseUrlIdx].Nodes.AddRange(currMap[baseUrl].Select(x => new TreeNode(x.URL)).ToArray()); + baseUrlIdx++; } tabListTree.EndUpdate(); tabListTree.Update(); @@ -81,26 +74,16 @@ private void FillMyTreeView(TabsList tabs) private void FillDataGridView1() { - foreach (TabInf tab in tabbys.tabs) + foreach (TabInf tab in tabsContainer.AllTabInfs) { - //this.listView1.Items.Add(tab.url); DataRow dr = dt.NewRow(); - dr["Tab Position"] = tab.tabPosition; - dr["Title"] = tab.lastKnownTitle; - dr["URL"] = tab.url; - dr["Base URL"] = tab.baseWebsite; + dr["TabNum"] = tab.TabNum; + dr["Title"] = tab.LastKnownTitle; + dr["URL"] = tab.URL; + dr["Base URL"] = tab.BaseWebsite; dt.Rows.Add(dr); } this.dataGridView1.DataSource = dt; - //////this.dataGridView1.GridColor = Color.BlueViolet; - //////this.dataGridView1.BorderStyle = BorderStyle.Fixed3D; - - ////DataGridViewCellStyle DefaultStyle = new DataGridViewCellStyle(); - ////DefaultStyle.Font = new Font(dataGridView1.Font,FontStyle.Regular); - ////DefaultStyle.BackColor = Color.LightCyan; - ////DefaultStyle.ForeColor = Color.Black; - ////dataGridView1.DefaultCellStyle = DefaultStyle; - dataGridView1.Refresh(); } private void tableLayoutPanel1_Paint(object sender, PaintEventArgs e) @@ -120,23 +103,42 @@ private void groupBox1_Enter_1(object sender, EventArgs e) private void button_connectfetchjson_Click(object sender, EventArgs e) { - string clickMessage = "Make sure to:\n 1) Have ADB and proper ADB drivers for your device.\n"; - clickMessage += "2) Have \"USB Debugging\" enabled on the device to recover from.\n"; - clickMessage += "3) Connect ONLY the Android device you want to recover from.\n"; - clickMessage += "4) Allow ADB Debugging from the pop-up on your device.\n"; - clickMessage += "5) Have Chrome open on your Android device."; - MessageBox.Show(clickMessage, "REQUIREMENTS/INSTRUCTIONS", MessageBoxButtons.OK, MessageBoxIcon.Information); - groupBox1.ForeColor = Color.White; - importAndProcessGroupbox.ForeColor = Color.White; - connectGroupBox.ForeColor = Color.Orange; + //string clickMessage = "Make sure to:\n 1) Have ADB and proper ADB drivers for your device.\n"; + //clickMessage += "2) Have \"USB Debugging\" enabled on the device to recover from.\n"; + //clickMessage += "3) Connect ONLY the Android device you want to recover from.\n"; + //clickMessage += "4) Allow ADB Debugging from the pop-up on your device.\n"; + //clickMessage += "5) Have Chrome open on your Android device."; + //MessageBox.Show(clickMessage, "REQUIREMENTS/INSTRUCTIONS", MessageBoxButtons.OK, MessageBoxIcon.Information); + //groupBox1.ForeColor = Color.White; + //importAndProcessGroupbox.ForeColor = Color.White; + //connectGroupBox.ForeColor = Color.Orange; //need to add adb location selection window and an argument to take that in the StartChr... function. //ImportUtilities.StartChromeAndroidJsonListServer(string.Empty); //for testing/debugging - string adbPath = string.Empty; - adbPath = ImportUtilities.GetADBPathDialog(); - if (adbPath == "-1") return; - ImportUtilities.StartChromeAndroidJsonListServer(adbPath); - ImportUtilities.DownloadTabListJSON(); + if (this.AdbPath == null || this.AdbPath.Length == 0) + { + AdbPath = WinFormsUtils.GetADBPathDialog(); + if (AdbPath == "-1") + { + AdbPath = string.Empty; + return; + } + } + //string adbPath = "C:\\Program Files (x86)\\Minimal ADB and Fastboot\\adb.exe"; + //IAdbConnector adbConnector = new StaticSocketNameChromiumAdbConnector(adbPath, ConfigHelper.ADB.Chrome_PackageName, ConfigHelper.ADB.Chrome_ForwardParameter_Remote); + IAdbConnector adbConnector; //= new DynamicSocketNamePidAtEndChromiumAdbConnector(adbPath, ConfigHelper.ADB.Edge_PackageName, ConfigHelper.ADB.EdgeAndBrave_Base_ForwardParameterRemote__MissingPidAtEnd); + BrowserDetailsStruct browserDetails = (BrowserDetailsStruct) comboBox_BrowserSelect.SelectedValue;//.SelectedItem).BrowserDetails; + if (browserDetails.PackageName == null && browserDetails.IsSocketNameFull) + adbConnector = new DiscoveredSocketOnlyAdbConnector(AdbPath, browserDetails.SocketNameFullOrPartial); + else if (browserDetails.IsSocketNameFull) + adbConnector = new StaticSocketNameChromiumAdbConnector(AdbPath, browserDetails.PackageName, browserDetails.SocketNameFullOrPartial); + else + adbConnector = new DynamicSocketNamePidAtEndChromiumAdbConnector(AdbPath, browserDetails.PackageName, browserDetails.SocketNameFullOrPartial); + + ITabsJsonFetcher tabsJsonFetcher = new AdbTabsJsonFetcher(adbConnector); + jsonLocation = tabsJsonFetcher.FetchTabsJson(); + + comboBox_BrowserSelect.Enabled= false; connectGroupBox.ForeColor = Color.Lime; importAndProcessGroupbox.ForeColor = Color.Orange; @@ -148,12 +150,15 @@ private void button_ImportAndProcess_Click(object sender, EventArgs e) importAndProcessGroupbox.ForeColor = Color.Orange; dt.Clear(); + dataGridView1.Refresh(); tabListTree.Nodes.Clear(); - ImportUtilities.GetURLtxtAndTITLEtxtFromJSON(manuallySetJsonLocation); - tabbys = new TabsList(false); + tabListTree.Refresh(); + + ITabsImporter tabsImporter = new JsonToTabsImporter(jsonLocation); + tabsContainer = tabsImporter.Import(); FillDataGridView1(); - FillMyTreeView(tabbys); + FillMyTreeView(); importAndProcessGroupbox.ForeColor = Color.Lime; @@ -165,23 +170,29 @@ private void label2_Click(object sender, EventArgs e) } - private void button_exportListHTML_Click(object sender, EventArgs e) + private void button_exportListHTMLGrouped_Click(object sender, EventArgs e) { //add select path dialog box?? - string outputPath = tabbys.ExportToHTML(); + ITabsExporter tabsExporter = new GroupedBasicHtmlListTabsExporter(); + var outputPath = tabsExporter.Export(tabsContainer); + if(groupBox1.ForeColor!=Color.Lime) { groupBox1.ForeColor = Color.Yellow; } MessageBox.Show("The HTML List has been exported to: " + outputPath, "List Exported!", MessageBoxButtons.OK); + button_exportListHTMLGrouped.ForeColor = Color.Lime; } - private void button_ExportAsBookmarks_Click(object sender, EventArgs e) + private void button_ExportAsBookmarksGrouped_Click(object sender, EventArgs e) { //add select path dialog box?? - string outputPath= tabbys.ExportToNetscapeBookmarksHTML(); + ITabsExporter tabsExporter = new GroupedNetscapeHtmlBookmarksExporter(); + var outputPath = tabsExporter.Export(tabsContainer); + groupBox1.ForeColor = Color.Lime; - MessageBox.Show("The Bookmarks file has been exported to: " + outputPath, "Bookmarks Exported!", MessageBoxButtons.OK); + MessageBox.Show("The Bookmarks (grouped by base URL) file has been exported to: " + outputPath, "Bookmarks (grouped) Exported!", MessageBoxButtons.OK); + button_ExportAsBookmarksGrouped.ForeColor = Color.Lime; } private void button_selectjson_Click(object sender, EventArgs e) @@ -191,21 +202,70 @@ private void button_selectjson_Click(object sender, EventArgs e) connectGroupBox.ForeColor = Color.Orange; MessageBox.Show("Button functionality may not be fully stable.", "!!! WORK IN PROGRESS !!!", MessageBoxButtons.OK,MessageBoxIcon.Exclamation); - using (OpenFileDialog openFileDialog = new OpenFileDialog()) - { - openFileDialog.InitialDirectory = "c:\\"; - openFileDialog.Filter = "JSON and JSON.BAK files (*.json, *.json.bak)|*.json;*.json.bak|All Files (*.*)|*.*"; - openFileDialog.FilterIndex = 1; - openFileDialog.RestoreDirectory = true; + ITabsJsonFetcher tabsJsonFetcher = new SelectFileDialogTabsJsonFetcher(); + jsonLocation = tabsJsonFetcher.FetchTabsJson(); + + connectGroupBox.ForeColor = Color.Lime; + importAndProcessGroupbox.ForeColor = Color.Orange; + } + + private void button_ExportAsSQLiteDB_Click(object sender, EventArgs e) + { + //add select path dialog box?? + ITabsExporter tabsExporter = new SQLiteTabsExporter(); + var outputPath = tabsExporter.Export(tabsContainer); + groupBox1.ForeColor = Color.Lime; + MessageBox.Show("The SQLite3 Database has been exported to: " + outputPath, "SQLite Database Exported!", MessageBoxButtons.OK); + button_ExportAsSQLiteDB.ForeColor = Color.Lime; + } + + private void button_exportCSV_Click(object sender, EventArgs e) + { + //add select path dialog box?? + ITabsExporter tabsExporter = new CSVTextFilePairTabsExporter(); + var outputPath = tabsExporter.Export(tabsContainer); + groupBox1.ForeColor = Color.Lime; + MessageBox.Show("The CSV text file has been exported to: " + outputPath, "CSV Exported!", MessageBoxButtons.OK); + button_exportCSV.ForeColor = Color.Lime; + } - if (openFileDialog.ShowDialog() == DialogResult.OK) + private void button_ExportAsBookmarks_Click(object sender, EventArgs e) + { + //add select path dialog box?? + ITabsExporter tabsExporter = new NetscapeHtmlBookmarksExporter(); + var outputPath = tabsExporter.Export(tabsContainer); + groupBox1.ForeColor = Color.Lime; + MessageBox.Show("The Bookmarks file has been exported to: " + outputPath, "Bookmarks Exported!", MessageBoxButtons.OK); + button_ExportAsBookmarks.ForeColor = Color.Lime; + } + + private void browserDetailsBindingSource_CurrentChanged(object sender, EventArgs e) + { + + } + + private void button_FixOrDiscoverDevToolsSockets_Click(object sender, EventArgs e)//open your targeted browser on your android phone to make sure its devtools socket is open. + { + MessageBox.Show("This feature will discover/rediscover and verify DevTools sockets available on your device. \nMake sure your browser of interest is open on your device and your device is connected.\n If one of the listed browsers isn't being verified, it may be listed below as a separate search result.", "READ ME!", MessageBoxButtons.OK, MessageBoxIcon.Information); + + if (this.AdbPath == null || this.AdbPath.Length == 0) + { + AdbPath = WinFormsUtils.GetADBPathDialog(); + if (AdbPath == "-1") { - manuallySetJsonLocation = openFileDialog.FileName; + AdbPath = string.Empty; + return; } } - connectGroupBox.ForeColor = Color.Lime; - importAndProcessGroupbox.ForeColor = Color.Orange; + var devToolsSocketsFound = BrowserDiscoveryUtils.GetDevToolsSockets(AdbPath); + + var newComboItemsList = BrowserDiscoveryUtils.GetDefaultBrowserComboItems(); + BrowserDiscoveryUtils.VerifyExistingSockets(newComboItemsList, devToolsSocketsFound, AdbPath); + BrowserDiscoveryUtils.DiscoverNewSocketsAndOrFixKnownBrowsersWithUnexpectedSocketNames(newComboItemsList, devToolsSocketsFound, AdbPath); + + + WinFormsUtils.InitializeOrResetBrowserListComboBox(comboBox_BrowserSelect, newComboItemsList); } } diff --git a/Form1.resx b/Form1.resx index f298a7b..e9b0c3c 100644 --- a/Form1.resx +++ b/Form1.resx @@ -57,4 +57,7 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 17, 17 + \ No newline at end of file diff --git a/ImportUtilities.cs b/ImportUtilities.cs deleted file mode 100644 index 69a2ef8..0000000 --- a/ImportUtilities.cs +++ /dev/null @@ -1,198 +0,0 @@ -using System; -using System.IO; -using System.Diagnostics; -using System.Net; -using System.Windows.Forms; - -enum NextStepImpUtil -{ - StartADB, - ConnectToDevice, - Autumn, - Winter -} -public static class ImportUtilities -{ - private static System.Diagnostics.Process proc=null; - private static NextStepImpUtil nextStep = NextStepImpUtil.StartADB; - public static void StartChromeAndroidJsonListServer(string adbPath) - { - if(nextStep!=NextStepImpUtil.StartADB) - { - //Implement error message here - throw new NotImplementedException(); - } - ProcessStartInfo procStartInfo; - if (adbPath == string.Empty) //this if/else is just for testing right now. It can't be triggered normally, so it's fine. Will remove it some day. - procStartInfo = new ProcessStartInfo(@"C:\Program Files (x86)\Minimal ADB and Fastboot\adb.exe"); - else - procStartInfo = new ProcessStartInfo(adbPath); - procStartInfo.WindowStyle = ProcessWindowStyle.Hidden; - procStartInfo.CreateNoWindow = true; - procStartInfo.RedirectStandardInput = true; - procStartInfo.RedirectStandardOutput = true; - procStartInfo.RedirectStandardError = true; - procStartInfo.UseShellExecute = false; - //procStartInfo.FileName = "adb.exe"; - procStartInfo.Arguments= "-d forward tcp:9222 localabstract:chrome_devtools_remote"; - //procStartInfo.WorkingDirectory = "C:\\Program Files(x86)\\Minimal ADB and Fastboot\\"; - proc = new Process(); - proc.StartInfo = procStartInfo; - proc.Start(); - //string result= proc.StandardOutput.ReadLine() + "\n"; - nextStep = NextStepImpUtil.ConnectToDevice; - proc.Dispose(); - } - - //public static void ConnectToDevice() - //{ - // if (nextStep != NextStepImpUtil.ConnectToDevice) - // { - // //Implement error message here - // throw new NotImplementedException(); - // } - // proc.StandardInput.WriteLine("cd \"C:\\Program Files(x86)\\Minimal ADB and Fastboot\""); - // proc.StandardInput.WriteLine("./adb.exe devices"); - // string result = ""; - // int i = 0; - // while(i!=5)//!proc.StandardOutput.EndOfStream) - // { - // result += proc.StandardOutput.ReadLine()+ "\n"; - // result += proc.StandardOutput.ReadLine() + "\n"; - // i++; - // } - // result.ToLower(); - //} - - public static void DownloadTabListJSON() - { - //if(nextStep==NextStepImpUtil.StartADB) - //{ - // //Implement error message here - // throw new NotImplementedException(); - //} - HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create("http://localhost:9222/json/list"); - httpWebRequest.Method = WebRequestMethods.Http.Get; - httpWebRequest.Accept = "application/json"; - httpWebRequest.ContentType = "application/json; charset=utf-8"; - string text; - var response = (HttpWebResponse)httpWebRequest.GetResponse(); - - using (var sr = new StreamReader(response.GetResponseStream())) - { - text = sr.ReadToEnd(); - } - - using (FileStream fs = new FileStream("_chromtabJSON.json", FileMode.Create)) - { - using (StreamWriter w = new StreamWriter(fs, System.Text.Encoding.UTF8)) - { - w.Write(text); - w.Flush(); - } - } - } - - - public static void GetURLtxtAndTITLEtxtFromJSON(string jsonPath="") - { - bool usingDefaultPath = false; - if (jsonPath == "") - { - jsonPath = "\"" + System.AppContext.BaseDirectory + "_chromtabJSON.json\""; - usingDefaultPath = true; - } - - Process proc = new Process(); - proc.StartInfo.UseShellExecute = false; - proc.StartInfo.RedirectStandardOutput = false; - proc.StartInfo.RedirectStandardInput = false; - proc.StartInfo.CreateNoWindow = true; - proc.StartInfo.FileName = "cmd.exe"; - //proc.StartInfo.Arguments = String.Format("/C " + Environment.CurrentDirectory.Replace('\\','/') + "/jq/jq.exe .[].url _chromtabJSON.json > lolnono.txt"); - string jqLocation = System.AppContext.BaseDirectory + @"\_redist\jq\";//jq.exe"; //"\""+System.AppContext.BaseDirectory + @"\_redist\jq\jq.exe" + "\""; - proc.StartInfo.WorkingDirectory = jqLocation; - proc.StartInfo.Arguments = String.Format("/C jq.exe .[].url \"" + jsonPath +"\" > \"" + System.AppContext.BaseDirectory+ "CurrentListOfURLs.txt\""); - proc.Start(); - proc.WaitForExit(); - - //proc.StartInfo.Arguments = String.Format("/C " + Environment.CurrentDirectory.Replace('\\','/') + "/jq/jq.exe .[].url _chromtabJSON.json > lolnono.txt"); - proc.StartInfo.Arguments = String.Format("/C jq.exe .[].title \"" + jsonPath + "\" > \"" + System.AppContext.BaseDirectory + "CurrentListOfTitles.txt\""); - proc.Start(); - proc.WaitForExit(); - proc.Dispose(); - - if(usingDefaultPath) - { - ///The following is to rename old .json to .json.bak: - // Source file to be renamed - //string sourceFile = "_chromtabJSON.json"; - // Creating FileInfo - System.IO.FileInfo file = new System.IO.FileInfo(jsonPath);//(sourceFile); - // Checking if file exists. - if (file.Exists) - { - // Move file with a new name. Hence renamed. - file.MoveTo("_chromtabJSON.json.bak"); - //Console.WriteLine("File Renamed."); - } - } - - } - - - public static string GetADBPathDialog() - { - //var fileContent = string.Empty; - var filePath = string.Empty; - bool IsCancelled = false; - while (filePath == string.Empty && !IsCancelled) - { - using (OpenFileDialog openFileDialog = new OpenFileDialog()) - { - openFileDialog.InitialDirectory = "c:\\"; - openFileDialog.Filter = "ADB Executable (adb.exe)|adb.exe|All Executables (*.exe)|*.exe"; - openFileDialog.FilterIndex = 1; - openFileDialog.RestoreDirectory = true; - - - if (openFileDialog.ShowDialog() == DialogResult.OK) - { - //Get the path of specified file - - filePath = openFileDialog.FileName; - if (filePath == string.Empty) - { - if (DialogResult.Cancel == MessageBox.Show("No file selected.", "Notice", MessageBoxButtons.RetryCancel, MessageBoxIcon.Exclamation)) - { - IsCancelled = true; - return "-1"; - } - } - - - ////Read the contents of the file into a stream - //var fileStream = openFileDialog.OpenFile(); - - //using (StreamReader reader = new StreamReader(fileStream)) - //{ - // fileContent = reader.ReadToEnd(); - //} - } - else - { - if (DialogResult.Cancel == MessageBox.Show("No file selected.", "Notice", MessageBoxButtons.RetryCancel, MessageBoxIcon.Exclamation)) - { - IsCancelled = true; - return "-1"; - } - } - } - } - - //MessageBox.Show(fileContent, "File Content at path: " + filePath, MessageBoxButtons.OK); - MessageBox.Show("Selected executable: " + filePath, "ADB Executable Selected!" + filePath, MessageBoxButtons.OK); - - return filePath; - } -} diff --git a/TabInf.cs b/Models/TabInf.cs similarity index 59% rename from TabInf.cs rename to Models/TabInf.cs index e8991e6..16a1787 100644 --- a/TabInf.cs +++ b/Models/TabInf.cs @@ -5,53 +5,73 @@ using System.Text; using System.Text.Json.Serialization; using System.Threading.Tasks; +using System.ComponentModel.DataAnnotations; +using ChromeDroid_TabMan.Auxiliary; -namespace ChromeDroid_TabMan +namespace ChromeDroid_TabMan.Models { - class TabInf: IComparable + public class TabInf : IComparable { + [Key] [JsonIgnore] - public readonly int tabPosition; + public int TabNum { get; set; } //might have something to do with position of tabs or the order in which they were opened. [JsonPropertyName("url")] - public string url; - [JsonIgnore] - public readonly string title; - [JsonIgnore] - public readonly string baseWebsite; + public string URL { get; set; } + //[JsonIgnore] + //public string currentTitle { get; set; } [JsonPropertyName("title")] - public string lastKnownTitle; + public string LastKnownTitle { get; set; } + [JsonIgnore] + public string BaseWebsite { get; set; } - public TabInf(string url, string lkTitle) - { - this.url = url; - this.title = "title-to-be-implemented"; - this.lastKnownTitle = lkTitle; - this.tabPosition = -1; - baseWebsite = GetBasewebsite(); - } - public TabInf(string url, string title, int tabPos) + + public TabInf() { } //exists for entity framework SQLite DB operations. + //public TabInf(string url, string lkTitle) + //{ + // this.URL = url; + // //currentTitle = "title-to-be-implemented"; + // LastKnownTitle = lkTitle; + // TabNum = -1; + // BaseWebsite = GetBaseWebsite(); + //} + public TabInf(string url, string lkTitle, int tabNum) { - this.url = url; - this.title = title; - this.tabPosition = tabPos; - baseWebsite = GetBasewebsite(); + this.URL = url; + this.LastKnownTitle = lkTitle; + if (LastKnownTitle.Length == 0) + LastKnownTitle = url; + TabNum = tabNum; + BaseWebsite = GetBaseWebsite(); } - private string GetBasewebsite() + private string GetBaseWebsite() { - string baseURL = string.Empty; - if (url.Contains("://")) + string baseURL = ConfigHelper.UnidentifiedBaseUrlString; + //The following approach should be faster than regex I think. + if (URL.Contains("://")) { - int indexAfterColonDoubleSlash = url.IndexOf("://", 0) + "://".Length; - int indexNextSlash = url.IndexOf("/", indexAfterColonDoubleSlash); + int indexAfterColonDoubleSlash = URL.IndexOf("://", 0) + "://".Length; + int indexNextSlash = URL.IndexOf("/", indexAfterColonDoubleSlash); + if (indexNextSlash == -1) + indexNextSlash = URL.Length; int ssLen = indexNextSlash - indexAfterColonDoubleSlash; - baseURL = url.Substring(indexAfterColonDoubleSlash, ssLen); + if (ssLen>4) + { + if (URL[indexAfterColonDoubleSlash]=='w' && URL[indexAfterColonDoubleSlash+1] == 'w' && URL[indexAfterColonDoubleSlash+2]=='w' && URL[indexAfterColonDoubleSlash+3]=='.') + { + indexAfterColonDoubleSlash += 4; + ssLen= indexNextSlash - indexAfterColonDoubleSlash; + } + } + baseURL = URL.Substring(indexAfterColonDoubleSlash, ssLen); + if (!baseURL.Contains(".")) + baseURL = ConfigHelper.UnidentifiedBaseUrlString; } return baseURL; } public int CompareTo(TabInf tab2) { - return this.baseWebsite.CompareTo(tab2.baseWebsite); + return BaseWebsite.CompareTo(tab2.BaseWebsite); } } } diff --git a/Program.cs b/Program.cs index d761d4a..2413202 100644 --- a/Program.cs +++ b/Program.cs @@ -1,8 +1,11 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Reflection.PortableExecutable; using System.Threading.Tasks; using System.Windows.Forms; +using ChromeDroid_TabMan.Auxiliary; +using System.IO; namespace ChromeDroid_TabMan { @@ -14,6 +17,11 @@ static class Program [STAThread] static void Main() { + /// My additions: + ConfigHelper.InitializeConfig(); + Directory.CreateDirectory(ConfigHelper.FileNamesAndPaths.OutputPathDefaultExportDirectory); + + /// Pre-existing code: Application.SetHighDpiMode(HighDpiMode.SystemAware); Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); diff --git a/Properties/DataSources/ChromeDroid_TabMan.DTOs.BrowserDetails.datasource b/Properties/DataSources/ChromeDroid_TabMan.DTOs.BrowserDetails.datasource new file mode 100644 index 0000000..ca7de5d --- /dev/null +++ b/Properties/DataSources/ChromeDroid_TabMan.DTOs.BrowserDetails.datasource @@ -0,0 +1,10 @@ + + + + ChromeDroid_TabMan.DTOs.BrowserDetails, ChromeDroid TabMan, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + \ No newline at end of file diff --git a/README.md b/README.md index 1037f95..3c59eba 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,9 @@ # DOCUMENTATION IS UNDER PROGRESS. # ChromeDroid-TabMan A personal project for trying to retrieve all the more than 3000 tabs I have open on my Chrome (Android version). It will probably be useful to others as well, but I'm mostly doing it for myself. + + +## Build (Release): +```powershell +dotnet publish -c Release -r win-x64 --self-contained -p:PublishSingleFile=True -p:PublishTrimmed=True -p:TrimMode=CopyUsed -p:PublishReadyToRun=True +``` \ No newline at end of file diff --git a/jq/jq.exe b/jq/jq.exe deleted file mode 100644 index cf9f37e..0000000 Binary files a/jq/jq.exe and /dev/null differ diff --git a/jq/license_info.txt b/jq/license_info.txt deleted file mode 100644 index 348cd62..0000000 --- a/jq/license_info.txt +++ /dev/null @@ -1,16 +0,0 @@ -I did not make jq, it is an open-source software licensed under the MIT license (code) and the CC-BY-3.0 license (docs) by the rights-holder. - -Visit https://stedolan.github.io/jq/ for more information. - -Here's a copy of the general MIT license: - - ------------------ -The MIT License (MIT) -Copyright © 2022 - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file