diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/CentralRepoSettings.java b/Core/src/org/sleuthkit/autopsy/centralrepository/CentralRepoSettings.java
index b7ec071f27390e9db817a84a14751cf7f1c051ae..d24b6245a6f8f8c8c546df5325d1f6c21c0f3f39 100644
--- a/Core/src/org/sleuthkit/autopsy/centralrepository/CentralRepoSettings.java
+++ b/Core/src/org/sleuthkit/autopsy/centralrepository/CentralRepoSettings.java
@@ -44,6 +44,8 @@ public static CentralRepoSettings getInstance() {
 
     private static final String DEFAULT_DB_PARENT_PATH = Paths.get(CENTRAL_REPO_BASE_PATH, "LocalDatabase").toString();
     private static final String DEFAULT_DB_NAME = "central_repository.db";
+
+    // NOTE: if this changes, an equivalent fix will be needed in CentralRepoDatamodelTest for the String PROPERTIES_FILE
     private static final String MODULE_SETTINGS_KEY = Paths.get(
             Paths.get(PlatformUtil.getUserConfigDirectory()).relativize(Paths.get(PlatformUtil.getModuleConfigDirectory())).toString(),
             CENTRAL_REPOSITORY_FOLDER,
diff --git a/Core/src/org/sleuthkit/autopsy/commandlineingest/CommandLineIngestManager.java b/Core/src/org/sleuthkit/autopsy/commandlineingest/CommandLineIngestManager.java
index 39aea28933fe877ea2140ee6183a800b49ecd856..ffc31fff1c0889b442abc380dbc6a3e1b79ef30e 100755
--- a/Core/src/org/sleuthkit/autopsy/commandlineingest/CommandLineIngestManager.java
+++ b/Core/src/org/sleuthkit/autopsy/commandlineingest/CommandLineIngestManager.java
@@ -56,6 +56,7 @@
 import org.sleuthkit.autopsy.ingest.IngestModuleError;
 import org.sleuthkit.autopsy.ingest.IngestProfiles;
 import org.sleuthkit.autopsy.ingest.IngestProfiles.IngestProfile;
+import org.sleuthkit.autopsy.ingest.profile.IngestProfilePaths;
 import org.sleuthkit.autopsy.modules.interestingitems.FilesSet;
 import org.sleuthkit.autopsy.modules.interestingitems.FilesSetsManager;
 import org.sleuthkit.autopsy.report.infrastructure.ReportGenerator;
@@ -75,9 +76,9 @@ public class CommandLineIngestManager extends CommandLineManager {
     private Case caseForJob = null;
     private AutoIngestDataSource dataSource = null;
 
-    static int CL_SUCCESS = 0;
-    static int CL_RUN_FAILURE = -1;
-    static int CL_PROCESS_FAILURE = 1;
+    static final int CL_SUCCESS = 0;
+    static final int CL_RUN_FAILURE = -1;
+    static final int CL_PROCESS_FAILURE = -2;
 
     public CommandLineIngestManager() {
     }
@@ -260,7 +261,7 @@ public void run() {
                                 // run ingest
                                 String ingestProfile = inputs.get(CommandLineCommand.InputType.INGEST_PROFILE_NAME.name());
                                 analyze(dataSource, ingestProfile);
-                            } catch (InterruptedException | CaseActionException ex) {
+                            } catch (InterruptedException | CaseActionException | AnalysisStartupException ex) {
                                 String dataSourcePath = command.getInputs().get(CommandLineCommand.InputType.DATA_SOURCE_PATH.name());
                                 LOGGER.log(Level.SEVERE, "Error running ingest on data source " + dataSourcePath, ex);
                                 System.out.println("Error running ingest on data source " + dataSourcePath);
@@ -520,7 +521,7 @@ private void analyze(AutoIngestDataSource dataSource, String ingestProfileName)
                     // unable to find the user specified profile
                     LOGGER.log(Level.SEVERE, "Unable to find ingest profile: {0}. Ingest cancelled!", ingestProfileName);
                     System.out.println("Unable to find ingest profile: " + ingestProfileName + ". Ingest cancelled!");
-                    return;
+                    throw new AnalysisStartupException("Unable to find ingest profile: " + ingestProfileName + ". Ingest cancelled!");
                 }
 
                 // get FileSet filter associated with this profile
@@ -529,7 +530,7 @@ private void analyze(AutoIngestDataSource dataSource, String ingestProfileName)
                     // unable to find the user specified profile
                     LOGGER.log(Level.SEVERE, "Unable to find file filter {0} for ingest profile: {1}. Ingest cancelled!", new Object[]{selectedProfile.getFileIngestFilter(), ingestProfileName});
                     System.out.println("Unable to find file filter " + selectedProfile.getFileIngestFilter() + " for ingest profile: " + ingestProfileName + ". Ingest cancelled!");
-                    return;
+                    throw new AnalysisStartupException("Unable to find file filter " + selectedProfile.getFileIngestFilter() + " for ingest profile: " + ingestProfileName + ". Ingest cancelled!");
                 }
             }
 
@@ -543,7 +544,7 @@ private void analyze(AutoIngestDataSource dataSource, String ingestProfileName)
                         ingestJobSettings = new IngestJobSettings(UserPreferences.getCommandLineModeIngestModuleContextString());
                     } else {
                         // load the custom ingest 
-                        ingestJobSettings = new IngestJobSettings(selectedProfile.toString());
+                        ingestJobSettings = new IngestJobSettings(IngestProfilePaths.getInstance().getIngestProfilePrefix() + selectedProfile.toString());
                         ingestJobSettings.setFileFilter(selectedFileSet);
                     }
 
diff --git a/Core/src/org/sleuthkit/autopsy/commandlineingest/CommandLineOptionProcessor.java b/Core/src/org/sleuthkit/autopsy/commandlineingest/CommandLineOptionProcessor.java
index 0bb42295a042d2000d5137ea72914c5081aaf44b..921c2e0a6590ee84850f3c42fff2aadcdbcf4735 100755
--- a/Core/src/org/sleuthkit/autopsy/commandlineingest/CommandLineOptionProcessor.java
+++ b/Core/src/org/sleuthkit/autopsy/commandlineingest/CommandLineOptionProcessor.java
@@ -271,6 +271,7 @@ protected void process(Env env, Map<Option, String[]> values) throws CommandExce
                 newCommand.addInputValue(CommandLineCommand.InputType.CASES_BASE_DIR_PATH.name(), caseBaseDir);
                 newCommand.addInputValue(CommandLineCommand.InputType.DATA_SOURCE_ID.name(), dataSourceId);
                 newCommand.addInputValue(CommandLineCommand.InputType.INGEST_PROFILE_NAME.name(), ingestProfile);
+                newCommand.addInputValue(CommandLineCommand.InputType.DATA_SOURCE_PATH.name(), dataSourcePath);
                 commands.add(newCommand);
                 runFromCommandLine(true);
             }
diff --git a/Core/src/org/sleuthkit/autopsy/ingest/IngestJobSettings.java b/Core/src/org/sleuthkit/autopsy/ingest/IngestJobSettings.java
index 85052e0aedef6f4ba381a0478454a2dda701e160..a6b5f897dd1e1649721383a3e63fb093788364ae 100644
--- a/Core/src/org/sleuthkit/autopsy/ingest/IngestJobSettings.java
+++ b/Core/src/org/sleuthkit/autopsy/ingest/IngestJobSettings.java
@@ -199,7 +199,7 @@ public IngestJobSettings(String executionContext, IngestType ingestType, Collect
     public Path getSavedModuleSettingsFolder() {
         return getSavedModuleSettingsFolder(executionContext);
     }
-
+    
     /**
      * Saves these ingest job settings.
      */
diff --git a/Core/src/org/sleuthkit/autopsy/ingest/IngestProfiles.java b/Core/src/org/sleuthkit/autopsy/ingest/IngestProfiles.java
index a821f418de4a05166e38c9765e7c92f99f23c64f..2bca1c810c197fa43008675e7fd5d2bcc23b72e4 100644
--- a/Core/src/org/sleuthkit/autopsy/ingest/IngestProfiles.java
+++ b/Core/src/org/sleuthkit/autopsy/ingest/IngestProfiles.java
@@ -202,15 +202,24 @@ public String getFileIngestFilter() {
          * @param selectedProfile
          */
         synchronized static void deleteProfile(IngestProfile selectedProfile) {
+            deleteProfile(selectedProfile.getName());
+        }
+        
+        /**
+         * Deletes all of the files which are currently storing a profile.
+         *
+         * @param profile name
+         */
+        synchronized static void deleteProfile(String profileName) {
             try {
-                File rootSettingsFile = getRootSettingsFile(selectedProfile.getName());
-                File settingsDirectory = getSettingsDirectory(selectedProfile.getName());
+                File rootSettingsFile = getRootSettingsFile(profileName);
+                File settingsDirectory = getSettingsDirectory(profileName);
                 Files.deleteIfExists(rootSettingsFile.toPath());
                 FileUtils.deleteDirectory(settingsDirectory);
             } catch (IOException ex) {
-                logger.log(Level.WARNING, "Error deleting directory for profile " + selectedProfile.getName(), ex);
+                logger.log(Level.WARNING, "Error deleting directory for profile " + profileName, ex);
             }
-        }
+        }        
 
         /**
          * Renames the files and directories associated with a profile
diff --git a/Core/src/org/sleuthkit/autopsy/ingest/ProfilePanel.java b/Core/src/org/sleuthkit/autopsy/ingest/ProfilePanel.java
index 826ca6c2c94577ce889a6a4e4bdb415f2d8d429a..3f00cc048b58ddce555e81905e253182c8787780 100644
--- a/Core/src/org/sleuthkit/autopsy/ingest/ProfilePanel.java
+++ b/Core/src/org/sleuthkit/autopsy/ingest/ProfilePanel.java
@@ -85,7 +85,15 @@ String getProfileDesc() {
     IngestJobSettings getSettings() {
         return ingestSettingsPanel.getSettings();
     }
-
+    
+    String getIngestProfileName() {
+        if (profile != null) {
+            return profile.getName();
+        } else {
+            return NEW_PROFILE_NAME;
+        }
+    }
+    
     /**
      * This method is called from within the constructor to initialize the form.
      * WARNING: Do NOT modify this code. The content of this method is always
diff --git a/Core/src/org/sleuthkit/autopsy/ingest/ProfileSettingsPanel.java b/Core/src/org/sleuthkit/autopsy/ingest/ProfileSettingsPanel.java
index b341b287525fbff54b7120f669c2d70757e722d2..a28a5e6aa8f5a63a9c1c667d15693e101fcc308f 100644
--- a/Core/src/org/sleuthkit/autopsy/ingest/ProfileSettingsPanel.java
+++ b/Core/src/org/sleuthkit/autopsy/ingest/ProfileSettingsPanel.java
@@ -391,7 +391,7 @@ private void editProfileButtonActionPerformed(java.awt.event.ActionEvent evt) {/
      */
     private void doProfileDialog(IngestProfile selectedProfile) {
         // Create a files set defintion panel.
-         final AdvancedConfigurationDialog dialog = new AdvancedConfigurationDialog(true);
+        final AdvancedConfigurationDialog dialog = new AdvancedConfigurationDialog(true);
         this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
         //start wait cursor for ingest job settings construction
         if (selectedProfile != null) {
@@ -430,6 +430,15 @@ private void doProfileDialog(IngestProfile selectedProfile) {
             }
             panel.saveSettings();
             load();
+        } else if (option == JOptionPane.CANCEL_OPTION) {
+            if (selectedProfile == null) {
+                // for new profiles, if user canlessed a profile create/edit then delete the temp empty profile that was created. 
+                // Otherwise it will remain in "config/ModuleSettings/IngestSettings" and then will get loaded
+                // next time we open ProfilePanel(), causing an NPE (JIRA-8404). This only needs to be done when creating
+                // a new ingest profile. If user cancelled editing of an existing profile, then we should not delete
+                // that profile.
+                IngestProfile.deleteProfile(panel.getIngestProfileName());
+            }
         }
     }
 
@@ -479,7 +488,12 @@ public void valueChanged(ListSelectionEvent e) {
                     for (FilesSet fSet : FilesSetsManager.getStandardFileIngestFilters()) {
                         fileIngestFilters.put(fSet.getName(), fSet);
                     }
-                    filterDescArea.setText(fileIngestFilters.get(selectedProfile.getFileIngestFilter()).getDescription());
+                    String selectedFilter = selectedProfile.getFileIngestFilter();
+                    if (selectedFilter == null) {
+                        filterDescArea.setText(NbBundle.getMessage(ProfileSettingsPanel.class, "ProfileSettingsPanel.messages.filterLoadFailed"));
+                    } else {
+                        filterDescArea.setText(fileIngestFilters.get(selectedFilter).getDescription());
+                    }
                 } catch (FilesSetsManager.FilesSetsManagerException ex) {
                     filterDescArea.setText(NbBundle.getMessage(ProfileSettingsPanel.class, "ProfileSettingsPanel.messages.filterLoadFailed"));
                 }
diff --git a/Core/src/org/sleuthkit/autopsy/python/JythonModuleLoader.java b/Core/src/org/sleuthkit/autopsy/python/JythonModuleLoader.java
index dab8969c94497372c61737fd27851552cd405090..beb3e712070733d0b0843cb0bac785d262d911d2 100644
--- a/Core/src/org/sleuthkit/autopsy/python/JythonModuleLoader.java
+++ b/Core/src/org/sleuthkit/autopsy/python/JythonModuleLoader.java
@@ -43,6 +43,7 @@
 import org.sleuthkit.autopsy.report.GeneralReportModule;
 import java.io.BufferedReader;
 import java.io.FileReader;
+import java.util.Comparator;
 
 /**
  * Finds and loads Autopsy modules written using the Jython variant of the
@@ -124,6 +125,8 @@ private static <T> List<T> getInterfaceImplementations(LineFilter filter, Class<
                 }
             }
         }
+        
+        Collections.sort(objects, Comparator.comparing((T obj) -> obj.getClass().getSimpleName(), (s1, s2) -> s1.compareToIgnoreCase(s2)));
         return objects;
     }
 
diff --git a/Core/src/org/sleuthkit/autopsy/report/infrastructure/ReportGenerationException.java b/Core/src/org/sleuthkit/autopsy/report/infrastructure/ReportGenerationException.java
new file mode 100755
index 0000000000000000000000000000000000000000..4002abc1e10c751a8a60c26104e3d91a7c2b8200
--- /dev/null
+++ b/Core/src/org/sleuthkit/autopsy/report/infrastructure/ReportGenerationException.java
@@ -0,0 +1,47 @@
+/*
+ * Autopsy Forensic Browser
+ *
+ * Copyright 2022 Basis Technology Corp.
+ * Contact: carrier <at> sleuthkit <dot> org
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.sleuthkit.autopsy.report.infrastructure;
+
+/**
+ * Instances of this exception class are thrown when there is an error while
+ * generating a report.
+ */
+public final class ReportGenerationException extends Exception {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * Constructs a new exception with the specified message.
+     *
+     * @param message The message.
+     */
+    public ReportGenerationException(String message) {
+        super(message);
+    }
+
+    /**
+     * Constructs a new exception with the specified message and cause.
+     *
+     * @param message The message.
+     * @param cause The cause.
+     */
+    public ReportGenerationException(String message, Throwable cause) {
+        super(message, cause);
+    }
+}
diff --git a/Core/src/org/sleuthkit/autopsy/report/infrastructure/ReportGenerator.java b/Core/src/org/sleuthkit/autopsy/report/infrastructure/ReportGenerator.java
index 3894af6e2e7c1ca61a15ba8c1d1750d2b0ff7446..12b2a1e4bc583962f277082ee0245eb2ebe75519 100644
--- a/Core/src/org/sleuthkit/autopsy/report/infrastructure/ReportGenerator.java
+++ b/Core/src/org/sleuthkit/autopsy/report/infrastructure/ReportGenerator.java
@@ -1,7 +1,7 @@
 /*
  * Autopsy Forensic Browser
  *
- * Copyright 2013-2020 Basis Technology Corp.
+ * Copyright 2013-2022 Basis Technology Corp.
  * Contact: carrier <at> sleuthkit <dot> org
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -107,7 +107,7 @@ public ReportGenerator(String configName, ReportProgressIndicator progressIndica
         this.reportGenerationPanel = null;
         this.configName = configName;
     }
-    
+
     /**
      * Constructs a report generator that generates one or more reports by
      * running user-selected report modules and uses a report generation panel
@@ -121,12 +121,15 @@ public ReportGenerator(String configName, ReportProgressIndicator progressIndica
         this.progressIndicator = panel.getProgressPanel();
         this.configName = configName;
     }
-    
+
     /**
-     * Generates the reports specified by the reporting configuration passed 
-     * in via the constructor. Does lookup of all existing report modules.
+     * Generates the reports specified by the reporting configuration passed in
+     * via the constructor. Does lookup of all existing report modules.
+     *
+     * @throws ReportGenerationException if an error occurred while generating
+     *                                   the report.
      */
-    public void generateReports() {
+    public void generateReports() throws ReportGenerationException {
         // load all report modules 
         Map<String, ReportModule> modules = new HashMap<>();
         for (TableReportModule module : ReportModuleLoader.getTableReportModules()) {
@@ -143,38 +146,51 @@ public void generateReports() {
 
         // special case for PortableCaseReportModule
         modules.put(FactoryClassNameNormalizer.normalize(PortableCaseReportModule.class.getCanonicalName()), new PortableCaseReportModule());
-        
+
         generateReports(modules);
     }
 
+    @NbBundle.Messages({
+        "ReportGenerator.error.noReportModules=No report modules found",
+        "# {0} - report configuration name", "ReportGenerator.error.unableToLoadConfig=Unable to load reporting configuration {0}.",
+        "# {0} - report module name", "ReportGenerator.error.moduleNotFound=Report module {0} not found",
+        "# {0} - report module name", "ReportGenerator.error.noTableReportSettings=No table report settings for report module {0}",
+        "# {0} - report module name", "ReportGenerator.error.noFileReportSettings=No file report settings for report module {0}",
+        "# {0} - report module name", "ReportGenerator.error.invalidSettings=Invalid settings for report module {0}",
+        "# {0} - report module name", "ReportGenerator.error.unsupportedType=Report module {0} has unsupported report module type",
+        "# {0} - report module name", "ReportGenerator.error.exception=Exception while running report module {0}"})
     /**
      * Generates the reports specified by the reporting configuration passed in
-     * via the constructor. 
-     * 
-     * @param modules Map of report module objects to use. This is useful when we want to 
-     *                re-use the module instances or limit which reports are generated.
+     * via the constructor.
+     *
+     * @param modules Map of report module objects to use. This is useful when
+     *                we want to re-use the module instances or limit which
+     *                reports are generated.
+     *
+     * @throws ReportGenerationException if an error occurred while generating
+     *                                   the report.
      */
-    public void generateReports(Map<String, ReportModule> modules) {
-        
+    public void generateReports(Map<String, ReportModule> modules) throws ReportGenerationException {
+
         if (modules == null || modules.isEmpty()) {
-            logger.log(Level.SEVERE, "No report modules found");
-            progressIndicator.updateStatusLabel("No report modules found. Exiting");
-            return;            
+            logger.log(Level.SEVERE, Bundle.ReportGenerator_error_noReportModules());
+            progressIndicator.updateStatusLabel(Bundle.ReportGenerator_error_noReportModules());
+            throw new ReportGenerationException(Bundle.ReportGenerator_error_noReportModules());
         }
-        
+
         ReportingConfig config = null;
         try {
             config = ReportingConfigLoader.loadConfig(configName);
         } catch (ReportConfigException ex) {
-            logger.log(Level.SEVERE, "Unable to load reporting configuration " + configName + ". Exiting", ex);
-            progressIndicator.updateStatusLabel("Unable to load reporting configuration " + configName + ". Exiting");
-            return;
+            logger.log(Level.SEVERE, Bundle.ReportGenerator_error_unableToLoadConfig(configName), ex);
+            progressIndicator.updateStatusLabel(Bundle.ReportGenerator_error_unableToLoadConfig(configName));
+            throw new ReportGenerationException(Bundle.ReportGenerator_error_unableToLoadConfig(configName));
         }
 
         if (config == null) {
-            logger.log(Level.SEVERE, "Unable to load reporting configuration {0}. Exiting", configName);
-            progressIndicator.updateStatusLabel("Unable to load reporting configuration " + configName + ". Exiting");
-            return;
+            logger.log(Level.SEVERE, Bundle.ReportGenerator_error_unableToLoadConfig(configName));
+            progressIndicator.updateStatusLabel(Bundle.ReportGenerator_error_unableToLoadConfig(configName));
+            throw new ReportGenerationException(Bundle.ReportGenerator_error_unableToLoadConfig(configName));
         }
 
         try {
@@ -189,8 +205,8 @@ public void generateReports(Map<String, ReportModule> modules) {
                 String moduleName = entry.getKey();
                 ReportModule module = modules.get(moduleName);
                 if (module == null) {
-                    logger.log(Level.SEVERE, "Report module {0} not found", moduleName);
-                    progressIndicator.updateStatusLabel("Report module " + moduleName + " not found");
+                    logger.log(Level.SEVERE, Bundle.ReportGenerator_error_moduleNotFound(moduleName));
+                    progressIndicator.updateStatusLabel(Bundle.ReportGenerator_error_moduleNotFound(moduleName));
                     continue;
                 }
 
@@ -216,8 +232,8 @@ public void generateReports(Map<String, ReportModule> modules) {
                         // get table report settings
                         TableReportSettings tableSettings = config.getTableReportSettings();
                         if (tableSettings == null) {
-                            logger.log(Level.SEVERE, "No table report settings for report module {0}", moduleName);
-                            progressIndicator.updateStatusLabel("No table report settings for report module " + moduleName);
+                            logger.log(Level.SEVERE, Bundle.ReportGenerator_error_noTableReportSettings(moduleName)); 
+                            progressIndicator.updateStatusLabel(Bundle.ReportGenerator_error_noTableReportSettings(moduleName));
                             continue;
                         }
 
@@ -228,8 +244,8 @@ public void generateReports(Map<String, ReportModule> modules) {
                         // get file report settings
                         FileReportSettings fileSettings = config.getFileReportSettings();
                         if (fileSettings == null) {
-                            logger.log(Level.SEVERE, "No file report settings for report module {0}", moduleName);
-                            progressIndicator.updateStatusLabel("No file report settings for report module " + moduleName);
+                            logger.log(Level.SEVERE, Bundle.ReportGenerator_error_noFileReportSettings(moduleName));
+                            progressIndicator.updateStatusLabel(Bundle.ReportGenerator_error_noFileReportSettings(moduleName));
                             continue;
                         }
 
@@ -240,20 +256,20 @@ public void generateReports(Map<String, ReportModule> modules) {
                         if (settings instanceof NoReportModuleSettings) {
                             settings = new PortableCaseReportModuleSettings();
                         } else if (!(settings instanceof PortableCaseReportModuleSettings)) {
-                            logger.log(Level.SEVERE, "Invalid settings for report module {0}", moduleName);
-                            progressIndicator.updateStatusLabel("Invalid settings for report module " + moduleName);
+                            logger.log(Level.SEVERE, Bundle.ReportGenerator_error_invalidSettings(moduleName)); 
+                            progressIndicator.updateStatusLabel(Bundle.ReportGenerator_error_invalidSettings(moduleName));
                             continue;
                         }
 
                         generatePortableCaseReport((PortableCaseReportModule) module, (PortableCaseReportModuleSettings) settings);
 
                     } else {
-                        logger.log(Level.SEVERE, "Report module {0} has unsupported report module type", moduleName);
-                        progressIndicator.updateStatusLabel("Report module " + moduleName + " has unsupported report module type");
+                        logger.log(Level.SEVERE, Bundle.ReportGenerator_error_unsupportedType(moduleName)); 
+                        progressIndicator.updateStatusLabel(Bundle.ReportGenerator_error_unsupportedType(moduleName));
                     }
                 } catch (IOException e) {
-                    logger.log(Level.SEVERE, "Exception while running report module {0}: {1}", new Object[]{moduleName, e.getMessage()});
-                    progressIndicator.updateStatusLabel("Exception while running report module " + moduleName);
+                    logger.log(Level.SEVERE, Bundle.ReportGenerator_error_exception(moduleName)); 
+                    progressIndicator.updateStatusLabel(Bundle.ReportGenerator_error_exception(moduleName));
                 }
             }
         } finally {
@@ -321,15 +337,15 @@ private void generateTableReport(TableReportModule tableReport, TableReportSetti
             TableReportGenerator generator = new TableReportGenerator(tableReportSettings, progressIndicator, tableReport);
             generator.execute();
             tableReport.endReport();
-            
+
             // finish progress, wrap up
             errorList = generator.getErrorList();
-            
+
             // if error list is empty, the operation has completed successfully.  If not there is an error
-            ReportProgressPanel.ReportStatus finalStatus = (errorList == null || errorList.isEmpty()) ?
-                ReportProgressPanel.ReportStatus.COMPLETE :
-                ReportProgressPanel.ReportStatus.ERROR;
-            
+            ReportProgressPanel.ReportStatus finalStatus = (errorList == null || errorList.isEmpty())
+                    ? ReportProgressPanel.ReportStatus.COMPLETE
+                    : ReportProgressPanel.ReportStatus.ERROR;
+
             progressIndicator.complete(finalStatus);
         }
     }
@@ -368,10 +384,10 @@ private void generateFileListReport(FileReportModule fileReportModule, FileRepor
             int i = 0;
             // Add files to report.
             for (AbstractFile file : files) {
-                if(shouldFilterFromReport(file, fileReportSettings)) {
+                if (shouldFilterFromReport(file, fileReportSettings)) {
                     continue;
                 }
-                
+
                 // Check to see if any reports have been cancelled.
                 if (progressIndicator.getStatus() == ReportStatus.CANCELED) {
                     return;
@@ -393,9 +409,9 @@ private void generateFileListReport(FileReportModule fileReportModule, FileRepor
             progressIndicator.complete(ReportStatus.COMPLETE);
         }
     }
-    
+
     private boolean shouldFilterFromReport(AbstractFile file, FileReportSettings fileReportSettings) {
-        if(fileReportSettings.getSelectedDataSources() == null) {
+        if (fileReportSettings.getSelectedDataSources() == null) {
             return false;
         }
         // Filter if the data source id is not in the list to process
diff --git a/Core/src/org/sleuthkit/autopsy/report/infrastructure/ReportWizardAction.java b/Core/src/org/sleuthkit/autopsy/report/infrastructure/ReportWizardAction.java
index f2c419eee7fad77078220970d0e00111b88b1400..c15a5ceef90bdbd46471b4e713bf1f0b2b496278 100644
--- a/Core/src/org/sleuthkit/autopsy/report/infrastructure/ReportWizardAction.java
+++ b/Core/src/org/sleuthkit/autopsy/report/infrastructure/ReportWizardAction.java
@@ -2,7 +2,7 @@
  *
  * Autopsy Forensic Browser
  *
- * Copyright 2012-2020 Basis Technology Corp.
+ * Copyright 2012-2022 Basis Technology Corp.
  *
  * Copyright 2012 42six Solutions.
  * Contact: aebadirad <at> 42six <dot> com
@@ -108,7 +108,12 @@ public static void doReportWizard(String configName, boolean displayCaseSpecific
                 Map<String, ReportModule> modules = (Map<String, ReportModule>) wiz.getProperty("modules");
                 ReportGenerator generator = new ReportGenerator(configName, panel); //NON-NLS
                 ReportWorker worker = new ReportWorker(() -> {
-                    generator.generateReports(modules);
+                    try {
+                        generator.generateReports(modules);
+                    } catch (ReportGenerationException ex) {
+                        // do nothing. the error message will be logged and 
+                        // displayed by the progress panel.
+                    }
                 });
                 worker.execute();
                 generator.displayProgressPanel();
diff --git a/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java b/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java
index d4b188d7db59d212f58637712f19a1aa4a53bf27..c2c122f1fab940122f378c88cbef2e7b8baae509 100755
--- a/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java
+++ b/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java
@@ -43,7 +43,6 @@
 import org.sleuthkit.autopsy.coreutils.ModuleSettings;
 import org.sleuthkit.datamodel.TskData;
 import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
-import org.sleuthkit.autopsy.centralrepository.CentralRepoSettings;
 import org.sleuthkit.autopsy.coreutils.FileUtil;
 
 /**
@@ -57,7 +56,10 @@
  */
 public class CentralRepoDatamodelTest extends TestCase {
 
-    private static final String PROPERTIES_FILE = CentralRepoSettings.getInstance().getModuleSettingsKey();
+    // Classloader for qa functional tests is having trouble with loading NbBundle.  
+    // Path is hard-coded to avoid that issue instead of using 
+    // CentralRepoSettings.getInstance().getModuleSettingsKey()
+    private static final String PROPERTIES_FILE = "ModuleConfig/CentralRepository/CentralRepository";
     private static final String CR_DB_NAME = "testcentralrepo.db";
 
     private static final Path testDirectory = Paths.get(System.getProperty("java.io.tmpdir"), "CentralRepoDatamodelTest");
diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Bundle.properties b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Bundle.properties
index 602dc5b0a07aa4352f7a1374e828a45a07495219..b9a385e3b8b3c62f4a5658e59e810202e58dda81 100644
--- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Bundle.properties
+++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Bundle.properties
@@ -3,6 +3,14 @@ OpenIDE-Module-Long-Description=Recent Activity ingest module.\n\n The module ex
 OpenIDE-Module-Name=RecentActivity
 OpenIDE-Module-Short-Description=Recent Activity finder ingest module
 Chrome.moduleName=Chromium Analyzer
+Chrome.getLocalState.errMsg.errGettingFiles=Error when trying to get Local State file.
+Chrome.getLocalState.errMsg.couldntFindAnyFiles=Could not find any allocated Chrome Local State files.
+Chrome.getLocalState.errMsg.errAnalyzingFile={0}: Error while trying to analyze file:{1}
+Chrome.getLocalState.displayName=Chromium Profiles
+Chrome.getExtensions.errMsg.errGettingFiles=Error when trying to get Secure Preferences file.
+Chrome.getExtensions.errMsg.couldntFindAnyFiles=Could not find any allocated Chrome Secure Preferences file.
+Chrome.getExtensions.errMsg.errAnalyzingFile={0}: Error while trying to analyze file:{1}
+Chrome.getExtensions.displayName=Chromium Extensions
 Chrome.getHistory.errMsg.errGettingFiles=Error when trying to get Chrome history files.
 Chrome.getHistory.errMsg.couldntFindAnyFiles=Could not find any allocated Chrome history files.
 Chrome.getHistory.errMsg.errAnalyzingFile={0}: Error while trying to analyze file:{1}
@@ -15,6 +23,10 @@ Chrome.getCookie.errMsg.errGettingFiles=Error when trying to get Chrome history
 Chrome.getCookie.errMsg.errAnalyzeFile={0}: Error while trying to analyze file:{1}
 Chrome.getDownload.errMsg.errGettingFiles=Error when trying to get Chrome history files.
 Chrome.getDownload.errMsg.errAnalyzeFiles1={0}: Error while trying to analyze file:{1}
+Chrome.getFavicon.errMsg.errGettingFiles=Error when trying to get Chrome favicon files.
+Chrome.getFavicon.errMsg.errAnalyzeFiles1={0}: Error while trying to analyze file:{1}
+Chrome.getFavicon.errMsg.errCreateArtifact=Error creating Favicon artifact 
+Chrome.getFavicon.displayName=Favicon
 Chrome.getLogin.errMsg.errGettingFiles=Error when trying to get Chrome history files.
 Chrome.getLogin.errMsg.errAnalyzingFiles={0}: Error while trying to analyze file:{1}
 Chrome.getAutofill.errMsg.errGettingFiles=Error when trying to get Chrome Web Data files.
diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Bundle.properties-MERGED b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Bundle.properties-MERGED
index c73bf456d5b0d22afe493e3b1ebb70f39b322c03..43b84b5fe6d5b7c1862b1d49dbb8ecd90b1e641d 100755
--- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Bundle.properties-MERGED
+++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Bundle.properties-MERGED
@@ -12,7 +12,6 @@ ChromeCacheExtractor.progressMsg={0}: Extracting cache entry {1} of {2} entries
 DataSourceUsage_AndroidMedia=Android Media Card
 DataSourceUsage_DJU_Drone_DAT=DJI Internal SD Card
 DataSourceUsage_FlashDrive=Flash Drive
-# {0} - OS name
 DataSourceUsageAnalyzer.customVolume.label=OS Drive ({0})
 DataSourceUsageAnalyzer.displayName=Data Source Usage Analyzer
 DefaultPriorityDomainCategorizer_searchEngineCategory=Search Engine
@@ -25,7 +24,7 @@ ExtractEdge_process_errMsg_errGettingWebCacheFiles=Error trying to retrieving Ed
 ExtractEdge_process_errMsg_spartanFail=Failure processing Microsoft Edge spartan.edb file
 ExtractEdge_process_errMsg_unableFindESEViewer=Unable to find ESEDatabaseViewer
 ExtractEdge_process_errMsg_webcacheFail=Failure processing Microsoft Edge WebCacheV01.dat file
-# {0} - sub module name
+ExtractFavicon_Display_Name=Favicon
 ExtractIE_executePasco_errMsg_errorRunningPasco={0}: Error analyzing Internet Explorer web history
 ExtractOs.androidOs.label=Android
 ExtractOs.androidVolume.label=OS Drive (Android)
@@ -58,7 +57,6 @@ ExtractOs.windowsVolume.label=OS Drive (Windows)
 ExtractOs.yellowDogLinuxOs.label=Linux (Yellow Dog)
 ExtractOs.yellowDogLinuxVolume.label=OS Drive (Linux Yellow Dog)
 ExtractOS_progressMessage=Checking for OS
-# {0} - sub module name
 ExtractPrefetch_errMsg_prefetchParsingFailed={0}: Error analyzing prefetch files
 ExtractPrefetch_module_name=Windows Prefetch Analyzer
 ExtractRecycleBin_module_name=Recycle Bin Analyzer
@@ -93,6 +91,14 @@ OpenIDE-Module-Long-Description=Recent Activity ingest module.\n\n The module ex
 OpenIDE-Module-Name=RecentActivity
 OpenIDE-Module-Short-Description=Recent Activity finder ingest module
 Chrome.moduleName=Chromium Analyzer
+Chrome.getLocalState.errMsg.errGettingFiles=Error when trying to get Local State file.
+Chrome.getLocalState.errMsg.couldntFindAnyFiles=Could not find any allocated Chrome Local State files.
+Chrome.getLocalState.errMsg.errAnalyzingFile={0}: Error while trying to analyze file:{1}
+Chrome.getLocalState.displayName=Chromium Profiles
+Chrome.getExtensions.errMsg.errGettingFiles=Error when trying to get Secure Preferences file.
+Chrome.getExtensions.errMsg.couldntFindAnyFiles=Could not find any allocated Chrome Secure Preferences file.
+Chrome.getExtensions.errMsg.errAnalyzingFile={0}: Error while trying to analyze file:{1}
+Chrome.getExtensions.displayName=Chromium Extensions
 Chrome.getHistory.errMsg.errGettingFiles=Error when trying to get Chrome history files.
 Chrome.getHistory.errMsg.couldntFindAnyFiles=Could not find any allocated Chrome history files.
 Chrome.getHistory.errMsg.errAnalyzingFile={0}: Error while trying to analyze file:{1}
@@ -105,6 +111,10 @@ Chrome.getCookie.errMsg.errGettingFiles=Error when trying to get Chrome history
 Chrome.getCookie.errMsg.errAnalyzeFile={0}: Error while trying to analyze file:{1}
 Chrome.getDownload.errMsg.errGettingFiles=Error when trying to get Chrome history files.
 Chrome.getDownload.errMsg.errAnalyzeFiles1={0}: Error while trying to analyze file:{1}
+Chrome.getFavicon.errMsg.errGettingFiles=Error when trying to get Chrome favicon files.
+Chrome.getFavicon.errMsg.errAnalyzeFiles1={0}: Error while trying to analyze file:{1}
+Chrome.getFavicon.errMsg.errCreateArtifact=Error creating Favicon artifact 
+Chrome.getFavicon.displayName=Favicon
 Chrome.getLogin.errMsg.errGettingFiles=Error when trying to get Chrome history files.
 Chrome.getLogin.errMsg.errAnalyzingFiles={0}: Error while trying to analyze file:{1}
 Chrome.getAutofill.errMsg.errGettingFiles=Error when trying to get Chrome Web Data files.
@@ -166,11 +176,14 @@ Progress_Message_Chrome_Cache=Chrome Cache
 Progress_Message_Chrome_Cookies=Chrome Cookies Browser {0}
 # {0} - browserName
 Progress_Message_Chrome_Downloads=Chrome Downloads Browser {0}
+Progress_Message_Chrome_Extensions=Chrome Extensions {0}
+Progress_Message_Chrome_Favicons=Chrome Downloads Favicons {0}
 Progress_Message_Chrome_FormHistory=Chrome Form History
 # {0} - browserName
 Progress_Message_Chrome_History=Chrome History Browser {0}
 # {0} - browserName
 Progress_Message_Chrome_Logins=Chrome Logins Browser {0}
+Progress_Message_Chrome_Profiles=Chrome Profiles {0}
 Progress_Message_Edge_Bookmarks=Microsoft Edge Bookmarks
 Progress_Message_Edge_Cookies=Microsoft Edge Cookies
 Progress_Message_Edge_History=Microsoft Edge History
@@ -225,7 +238,6 @@ Recently_Used_Artifacts_Winrar=Recently opened according to WinRAR MRU
 Registry_System_Bam=Recently Executed according to Background Activity Moderator (BAM)
 RegRipperFullNotFound=Full version RegRipper executable not found.
 RegRipperNotFound=Autopsy RegRipper executable not found.
-# {0} - file name
 SearchEngineURLQueryAnalyzer.init.exception.msg=Unable to find {0}.
 SearchEngineURLQueryAnalyzer.moduleName.text=Search Engine Query Analyzer
 SearchEngineURLQueryAnalyzer.engineName.none=NONE
diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Chromium.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Chromium.java
index 1d22f930b9394708b90225aa554f76241361dd7f..41eefc21f8ad572d3cb315191bfc786b323d7210 100644
--- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Chromium.java
+++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Chromium.java
@@ -42,6 +42,7 @@
 import java.util.HashMap;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Set;
 import org.apache.commons.io.FilenameUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.openide.util.NbBundle.Messages;
@@ -86,13 +87,24 @@ class Chromium extends Extract {
     private static final String WEBFORM_ADDRESS_QUERY_V8X = "SELECT first_name, middle_name, last_name, full_name, street_address, city, state, zipcode, country_code, number, email, date_modified, use_date, use_count"
             + " FROM autofill_profiles, autofill_profile_names, autofill_profile_emails, autofill_profile_phones"
             + " WHERE autofill_profiles.guid = autofill_profile_names.guid AND autofill_profiles.guid = autofill_profile_emails.guid AND autofill_profiles.guid = autofill_profile_phones.guid";
+    private static final String FAVICON_QUERY = "SELECT page_url, last_updated, last_requested FROM icon_mapping, favicon_bitmaps "
+            + " WHERE icon_mapping.icon_id = favicon_bitmaps.icon_id";
+    private static final String LOCALSTATE_FILE_NAME = "Local State";
+    private static final String EXTENSIONS_FILE_NAME = "Secure Preferences";
     private static final String HISTORY_FILE_NAME = "History";
     private static final String BOOKMARK_FILE_NAME = "Bookmarks";
     private static final String COOKIE_FILE_NAME = "Cookies";
     private static final String LOGIN_DATA_FILE_NAME = "Login Data";
     private static final String WEB_DATA_FILE_NAME = "Web Data";
+    private static final String FAVICON_DATA_FILE_NAME = "Favicons";
     private static final String UC_BROWSER_NAME = "UC Browser";
+    private static final String OPERA_BROWSER_NAME = "Opera";
     private static final String ENCRYPTED_FIELD_MESSAGE = "The data was encrypted.";
+    private static final String GOOGLE_PROFILE_NAME = "Profile";
+    private static final String GOOGLE_PROFILE = "Google Chrome ";
+    private static final String FAVICON_ARTIFACT_NAME = "TSK_FAVICON"; //NON-NLS
+    private static final String LOCAL_STATE_ARTIFACT_NAME = "TSK_LOCAL_STATE"; //NON-NLS
+    private static final String EXTENSIONS_ARTIFACT_NAME = "TSK_CHROME_EXTENSIONS"; //NON-NLS
 
     private Boolean databaseEncrypted = false;
     private Boolean fieldEncrypted = false;
@@ -101,14 +113,17 @@ class Chromium extends Extract {
     private Content dataSource;
     private final IngestJobContext context;
 
+    private Map<String, String> userProfiles;
+    private Map<String, String> browserLocations;
+    
     private static final Map<String, String> BROWSERS_MAP = ImmutableMap.<String, String>builder()
-            .put("Microsoft Edge", "Microsoft/Edge/User Data/Default")
-            .put("Yandex", "YandexBrowser/User Data/Default")
+            .put("Microsoft Edge", "Microsoft/Edge/User Data")
+            .put("Yandex", "YandexBrowser/User Data")
             .put("Opera", "Opera Software/Opera Stable")
-            .put("SalamWeb", "SalamWeb/User Data/Default")
-            .put("UC Browser", "UCBrowser/User Data%/Default")
-            .put("Brave", "BraveSoftware/Brave-Browser/User Data/Default")
-            .put("Google Chrome", "Chrome/User Data/Default")
+            .put("SalamWeb", "SalamWeb/User Data")
+            .put("UC Browser", "UCBrowser/User Data%")
+            .put("Brave", "BraveSoftware/Brave-Browser/User Data")
+            .put("Google Chrome", "Chrome/User Data")
             .build();
 
     @Messages({"# {0} - browserName",
@@ -119,6 +134,9 @@ class Chromium extends Extract {
         "Progress_Message_Chrome_Cookies=Chrome Cookies Browser {0}",
         "# {0} - browserName",
         "Progress_Message_Chrome_Downloads=Chrome Downloads Browser {0}",
+        "Progress_Message_Chrome_Profiles=Chrome Profiles {0}",
+        "Progress_Message_Chrome_Extensions=Chrome Extensions {0}",
+        "Progress_Message_Chrome_Favicons=Chrome Downloads Favicons {0}",
         "Progress_Message_Chrome_FormHistory=Chrome Form History",
         "# {0} - browserName",
         "Progress_Message_Chrome_AutoFill=Chrome Auto Fill Browser {0}",
@@ -137,40 +155,62 @@ public void process(Content dataSource, DataSourceIngestModuleProgress progressB
         dataFound = false;
         long ingestJobId = context.getJobId();
 
+        userProfiles = new HashMap<>();
+        browserLocations = new HashMap<>();
         for (Map.Entry<String, String> browser : BROWSERS_MAP.entrySet()) {
-            String browserName = browser.getKey();
+            progressBar.progress(NbBundle.getMessage(this.getClass(), "Progress_Message_Chrome_Profiles", browser.getKey()));
+            getProfiles(browser.getKey(), browser.getValue(), ingestJobId);
+            if (context.dataSourceIngestIsCancelled()) {
+                return;
+            }
+        }
+        for (Map.Entry<String, String> profile : userProfiles.entrySet()) {
+            String browserLocation = profile.getKey(); 
+            String browserName = browserLocations.get(browserLocation);
+            String userName = profile.getValue();
+            progressBar.progress(NbBundle.getMessage(this.getClass(), "Progress_Message_Chrome_Extensions", browserName));
+            this.getExtensions(browserName, browserLocation, userName, ingestJobId);
+            if (context.dataSourceIngestIsCancelled()) {
+                return;
+            }
             progressBar.progress(NbBundle.getMessage(this.getClass(), "Progress_Message_Chrome_History", browserName));
-            this.getHistory(browser.getKey(), browser.getValue(), ingestJobId);
+            this.getHistory(browserName, browserLocation, userName, ingestJobId);
             if (context.dataSourceIngestIsCancelled()) {
                 return;
             }
 
             progressBar.progress(NbBundle.getMessage(this.getClass(), "Progress_Message_Chrome_Bookmarks", browserName));
-            this.getBookmark(browser.getKey(), browser.getValue(), ingestJobId);
+            this.getBookmark(browserName, browserLocation, userName, ingestJobId);
             if (context.dataSourceIngestIsCancelled()) {
                 return;
             }
 
             progressBar.progress(NbBundle.getMessage(this.getClass(), "Progress_Message_Chrome_Cookies", browserName));
-            this.getCookie(browser.getKey(), browser.getValue(), ingestJobId);
+            this.getCookie(browserName, browserLocation, userName, ingestJobId);
             if (context.dataSourceIngestIsCancelled()) {
                 return;
             }
 
             progressBar.progress(NbBundle.getMessage(this.getClass(), "Progress_Message_Chrome_Logins", browserName));
-            this.getLogins(browser.getKey(), browser.getValue(), ingestJobId);
+            this.getLogins(browserName, browserLocation, userName, ingestJobId);
             if (context.dataSourceIngestIsCancelled()) {
                 return;
             }
 
             progressBar.progress(NbBundle.getMessage(this.getClass(), "Progress_Message_Chrome_AutoFill", browserName));
-            this.getAutofill(browser.getKey(), browser.getValue(), ingestJobId);
+            this.getAutofill(browserName, browserLocation, userName, ingestJobId);
             if (context.dataSourceIngestIsCancelled()) {
                 return;
             }
 
             progressBar.progress(NbBundle.getMessage(this.getClass(), "Progress_Message_Chrome_Downloads", browserName));
-            this.getDownload(browser.getKey(), browser.getValue(), ingestJobId);
+            this.getDownload(browserName, browserLocation, userName, ingestJobId);
+            if (context.dataSourceIngestIsCancelled()) {
+                return;
+            }
+
+            progressBar.progress(NbBundle.getMessage(this.getClass(), "Progress_Message_Chrome_Favicons", browserName));
+            this.getFavicons(browserName, browserLocation, userName, ingestJobId);
             if (context.dataSourceIngestIsCancelled()) {
                 return;
             }
@@ -181,6 +221,425 @@ public void process(Content dataSource, DataSourceIngestModuleProgress progressB
         chromeCacheExtractor.processCaches();
     }
 
+    /**
+     * Query for profiles and add artifacts
+     *
+     * @param browser
+     * @param browserLocation
+     * @param ingestJobId     The ingest job id.
+     */
+    private void getProfiles(String browser, String browserLocation, long ingestJobId) {
+        FileManager fileManager = currentCase.getServices().getFileManager();
+        String browserName = browser;
+        List<AbstractFile> localStateFiles;
+        String localStateName = LOCALSTATE_FILE_NAME;
+        if (browserName.equals(UC_BROWSER_NAME)) {
+            localStateName = LOCALSTATE_FILE_NAME + "%";
+        }
+        try {
+            localStateFiles = fileManager.findFiles(dataSource, localStateName, browserLocation); //NON-NLS                                
+        } catch (TskCoreException ex) {
+            String msg = NbBundle.getMessage(this.getClass(), "Chrome.getLocalState.errMsg.errGettingFiles");
+            logger.log(Level.SEVERE, msg, ex);
+            this.addErrorMessage(this.getDisplayName() + ": " + msg);
+            return;
+        }
+
+        // get only the allocated ones, for now
+        List<AbstractFile> allocatedLocalStateFiles = new ArrayList<>();
+        for (AbstractFile localStateFile : localStateFiles) {
+            if (localStateFile.isMetaFlagSet(TskData.TSK_FS_META_FLAG_ENUM.ALLOC)) {
+                allocatedLocalStateFiles.add(localStateFile);
+            }
+        }
+
+        // log a message if we don't have any allocated Local State files
+        if (allocatedLocalStateFiles.isEmpty()) {
+            String msg = NbBundle.getMessage(this.getClass(), "Chrome.getLocalState.errMsg.couldntFindAnyFiles");
+            logger.log(Level.INFO, msg);
+            return;
+        }
+
+        dataFound = true;
+        Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
+        int j = 0;
+        while (j < allocatedLocalStateFiles.size()) {
+            if (browser.contains(GOOGLE_PROFILE_NAME)) {
+                String parentPath = FilenameUtils.normalizeNoEndSeparator(allocatedLocalStateFiles.get(j).getParentPath());
+                browserName = GOOGLE_PROFILE + " " + FilenameUtils.getBaseName(parentPath);
+            }
+            String temps = RAImageIngestModule.getRATempPath(currentCase, browserName, ingestJobId) + File.separator + allocatedLocalStateFiles.get(j).getName() + j; //NON-NLS
+            final AbstractFile localStateFile = allocatedLocalStateFiles.get(j++);
+            if ((localStateFile.getSize() == 0) || (localStateFile.getName().toLowerCase().contains("-slack"))
+                    || (localStateFile.getName().toLowerCase().contains("cache")) || (localStateFile.getName().toLowerCase().contains("media"))
+                    || (localStateFile.getName().toLowerCase().contains("index"))) {
+                continue;
+            }
+            try {
+                ContentUtils.writeToFile(localStateFile, new File(temps), context::dataSourceIngestIsCancelled);
+            } catch (ReadContentInputStreamException ex) {
+                logger.log(Level.WARNING, String.format("Error reading Chrome web Local State artifacts file '%s' (id=%d).",
+                        localStateFile.getName(), localStateFile.getId()), ex); //NON-NLS
+                this.addErrorMessage(NbBundle.getMessage(this.getClass(), "Chrome.getLocalState.errMsg.errAnalyzingFile",
+                        this.getDisplayName(), localStateFile.getName()));
+                continue;
+            } catch (IOException ex) {
+                logger.log(Level.SEVERE, String.format("Error writing temp file '%s' for Chrome Local State artifacts file '%s' (id=%d).",
+                        temps, localStateFile.getName(), localStateFile.getId()), ex); //NON-NLS
+                this.addErrorMessage(NbBundle.getMessage(this.getClass(), "Chrome.getLocalState.errMsg.errAnalyzingFile",
+                        this.getDisplayName(), localStateFile.getName()));
+                continue;
+            }
+
+            if (context.dataSourceIngestIsCancelled()) {
+                break;
+            }
+ 
+            FileReader tempReader;
+            try {
+                tempReader = new FileReader(temps);
+            } catch (FileNotFoundException ex) {
+                logger.log(Level.WARNING, "Error while trying to read into the LocalState file.", ex); //NON-NLS
+                continue;
+            }
+
+            JsonElement jsonElement;
+            JsonObject jElement, jProfile, jInfoCache;
+
+            try {
+                jsonElement = JsonParser.parseReader(tempReader);
+                jElement = jsonElement.getAsJsonObject();
+                if (jElement.has("profile")) {
+                    jProfile = jElement.get("profile").getAsJsonObject(); //NON-NLS
+                    jInfoCache = jProfile.get("info_cache").getAsJsonObject();
+                } else {
+                    continue;
+                }
+            } catch (JsonIOException | JsonSyntaxException | IllegalStateException ex) {
+                logger.log(Level.WARNING, "Error parsing Json from LocalState.", ex); //NON-NLS
+                this.addErrorMessage(NbBundle.getMessage(this.getClass(), "Chrome.getlocalState.errMsg.errAnalyzingFile",
+                        this.getDisplayName(), localStateFile.getName()));
+                continue;
+            }
+
+            BlackboardArtifact.Type localStateArtifactType;
+
+            try {
+                localStateArtifactType = createArtifactType(LOCAL_STATE_ARTIFACT_NAME, NbBundle.getMessage(this.getClass(), "Chrome.getLocalState.displayName"));
+            } catch (TskCoreException ex) {
+                logger.log(Level.SEVERE, String.format("Error creating artifact type for LocalState."), ex); //NON-NLS
+                this.addErrorMessage(NbBundle.getMessage(this.getClass(), "Chrome.getfavicon.errMsg.errCreateArtifact"));
+                continue;
+                
+            }
+            Set<String> profileNames = jInfoCache.keySet();
+            for (String profileName : profileNames) {
+                JsonElement result = jInfoCache.get(profileName);
+                JsonObject profile = result.getAsJsonObject();
+                if (profile == null) {
+                    continue;
+                }
+                JsonElement gaiaIdEl = profile.get("gaia_id"); //NON-NLS
+                String gaiaId;
+                if (gaiaIdEl != null) {
+                    gaiaId = gaiaIdEl.getAsString();
+                } else {
+                    gaiaId = "";
+                }
+                String hostedDomain;
+                JsonElement hostedDomainEl = profile.get("hosted_domain"); //NON-NLS
+                if (hostedDomainEl != null) {
+                    hostedDomain = hostedDomainEl.getAsString();
+                } else {
+                     hostedDomain= "";
+                }
+                String shortcutName;
+                JsonElement shortcutNameEl = profile.get("shortcut_name"); //NON-NLS
+                if (shortcutNameEl != null) {
+                    shortcutName = shortcutNameEl.getAsString();
+                } else {
+                    shortcutName = "";
+                }
+                String name;
+                JsonElement nameEl = profile.get("name"); //NON-NLS
+                if (nameEl != null) {
+                    name = nameEl.getAsString();
+                } else {
+                     name= "";
+                }
+                String userName; 
+                JsonElement userNameEl = profile.get("user_name"); //NON-NLS
+                if (userNameEl != null) {
+                    userName = userNameEl.getAsString();
+                } else {
+                    userName = "";
+                }              
+
+                if (userName.contains("")) {
+                    userProfiles.put(browserLocation + "/" + profileName, name);
+                    browserLocations.put(browserLocation + "/" + profileName, browser);                    
+                } else {
+                    userProfiles.put(browserLocation + "/" + profileName, userName);
+                    browserLocations.put(browserLocation + "/" + profileName, browser);                    
+                }
+
+                Collection<BlackboardAttribute> bbattributes = new ArrayList<>();
+                bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH,
+                        RecentActivityExtracterModuleFactory.getModuleName(), profileName));
+                bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_ID,
+                        RecentActivityExtracterModuleFactory.getModuleName(), gaiaId));
+                bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
+                        RecentActivityExtracterModuleFactory.getModuleName(), hostedDomain));
+                bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_SHORTCUT,
+                        RecentActivityExtracterModuleFactory.getModuleName(), shortcutName));
+                bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME,
+                        RecentActivityExtracterModuleFactory.getModuleName(), name));
+                bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_NAME,
+                        RecentActivityExtracterModuleFactory.getModuleName(), userName));
+                bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME,
+                        RecentActivityExtracterModuleFactory.getModuleName(), browserName));
+
+                try {
+                    bbartifacts.add(createArtifactWithAttributes(localStateArtifactType, localStateFile, bbattributes));
+                } catch (TskCoreException ex) {
+                    logger.log(Level.SEVERE, String.format("Failed to create bookmark artifact for file (%d)", localStateFile.getId()), ex);
+                }
+
+            }
+
+            if (!context.dataSourceIngestIsCancelled()) {
+                postArtifacts(bbartifacts);
+            }
+            bbartifacts.clear();
+ 
+        }
+        // Check if Default, Guest Profile and System Profile are in the usersProfiles, if they are not then add them
+        if (!userProfiles.containsKey("Default")) {
+            userProfiles.put(browserLocation + "/" + "Default", "Default");
+            browserLocations.put(browserLocation + "/" + "Default", browser);
+        }
+        if (!userProfiles.containsKey("Guest Profile")) {
+            userProfiles.put(browserLocation + "/" + "Guest Profile", "Guest");
+            browserLocations.put(browserLocation + "/" + "Guest Profile", browser);
+        }
+        if (!userProfiles.containsKey("System Profile")) {
+            userProfiles.put(browserLocation + "/" + "System Profile", "System");
+            browserLocations.put(browserLocation + "/" + "System Profile", browser);
+        }
+    }
+
+    /**
+     * Query for Extensions and add artifacts
+     *
+     * @param browser
+     * @param browserLocation
+     * @param ingestJobId     The ingest job id.
+     */
+    private void getExtensions(String browser, String browserLocation, String userName, long ingestJobId) {
+        FileManager fileManager = currentCase.getServices().getFileManager();
+        String browserName = browser;
+        List<AbstractFile> extensionFiles;
+        String extensionsName = EXTENSIONS_FILE_NAME;
+        if (browserName.equals(UC_BROWSER_NAME)) {
+            extensionsName = EXTENSIONS_FILE_NAME + "%";
+        }
+        try {
+            // Local State file is found in the directory about the browserLocation, that is why it is being removed
+            extensionFiles = fileManager.findFiles(dataSource, extensionsName, browserLocation); //NON-NLS
+        } catch (TskCoreException ex) {
+            String msg = NbBundle.getMessage(this.getClass(), "Chrome.getExtensions.errMsg.errGettingFiles");
+            logger.log(Level.SEVERE, msg, ex);
+            this.addErrorMessage(this.getDisplayName() + ": " + msg);
+            return;
+        }
+
+        // get only the allocated ones, for now
+        List<AbstractFile> allocatedExtensionsFiles = new ArrayList<>();
+        for (AbstractFile extensionFile : extensionFiles) {
+            if (extensionFile.isMetaFlagSet(TskData.TSK_FS_META_FLAG_ENUM.ALLOC)) {
+                allocatedExtensionsFiles.add(extensionFile);
+            }
+        }
+
+        // log a message if we don't have any allocated Local State files
+        if (allocatedExtensionsFiles.isEmpty()) {
+            String msg = NbBundle.getMessage(this.getClass(), "Chrome.getExtensions.errMsg.couldntFindAnyFiles");
+            logger.log(Level.INFO, msg);
+            return;
+        }
+
+        dataFound = true;
+        Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
+        int j = 0;
+        while (j < allocatedExtensionsFiles.size()) {
+            if (browser.contains(GOOGLE_PROFILE_NAME)) {
+                String parentPath = FilenameUtils.normalizeNoEndSeparator(allocatedExtensionsFiles.get(j).getParentPath());
+                browserName = GOOGLE_PROFILE + " " + FilenameUtils.getBaseName(parentPath);
+            }
+            String temps = RAImageIngestModule.getRATempPath(currentCase, browserName, ingestJobId) + File.separator + allocatedExtensionsFiles.get(j).getName() + j; //NON-NLS
+            final AbstractFile extensionFile = allocatedExtensionsFiles.get(j++);
+            if ((extensionFile.getSize() == 0) || (extensionFile.getName().toLowerCase().contains("-slack"))
+                    || (extensionFile.getName().toLowerCase().contains("cache")) || (extensionFile.getName().toLowerCase().contains("media"))
+                    || (extensionFile.getName().toLowerCase().contains("index"))) {
+                continue;
+            }
+            try {
+                ContentUtils.writeToFile(extensionFile, new File(temps), context::dataSourceIngestIsCancelled);
+            } catch (ReadContentInputStreamException ex) {
+                logger.log(Level.WARNING, String.format("Error reading Chrome web extension artifacts file '%s' (id=%d).",
+                        extensionFile.getName(), extensionFile.getId()), ex); //NON-NLS
+                this.addErrorMessage(NbBundle.getMessage(this.getClass(), "Chrome.getExtensions.errMsg.errAnalyzingFile",
+                        this.getDisplayName(), extensionFile.getName()));
+                continue;
+            } catch (IOException ex) {
+                logger.log(Level.SEVERE, String.format("Error writing temp file '%s' for Chrome Extensions artifacts file '%s' (id=%d).",
+                        temps, extensionFile.getName(), extensionFile.getId()), ex); //NON-NLS
+                this.addErrorMessage(NbBundle.getMessage(this.getClass(), "Chrome.getExtensions.errMsg.errAnalyzingFile",
+                        this.getDisplayName(), extensionFile.getName()));
+                continue;
+            }
+
+            if (context.dataSourceIngestIsCancelled()) {
+                break;
+            }
+ 
+            FileReader tempReader;
+            try {
+                tempReader = new FileReader(temps);
+            } catch (FileNotFoundException ex) {
+                logger.log(Level.WARNING, "Error while trying to read into the Secure Preferences file.", ex); //NON-NLS
+                continue;
+            }
+
+            BlackboardArtifact.Type localStateArtifactType;
+
+            try {
+                localStateArtifactType = createArtifactType(EXTENSIONS_ARTIFACT_NAME, NbBundle.getMessage(this.getClass(), "Chrome.getExtensions.displayName"));
+            } catch (TskCoreException ex) {
+                logger.log(Level.SEVERE, String.format("Error creating artifact type for Secure Preferences."), ex); //NON-NLS
+                this.addErrorMessage(NbBundle.getMessage(this.getClass(), "Chrome.getExtensions.errMsg.errCreateArtifact"));
+                continue;
+            }
+            
+            String profileName = FilenameUtils.getBaseName(StringUtils.chop(extensionFile.getParentPath()));
+            
+            JsonElement jsonElement;
+            JsonObject jElement, jExtensions, jSettings;
+
+            try {
+                jsonElement = JsonParser.parseReader(tempReader);
+                jElement = jsonElement.getAsJsonObject();
+                if (jElement.has("extensions")) {
+                    logger.log(Level.WARNING, String.format("Processing Secure Preferences from %s", extensionFile.getParentPath()));
+                    jExtensions = jElement.get("extensions").getAsJsonObject(); //NON-NLS
+                    if (!browserName.equals(OPERA_BROWSER_NAME)) {
+                        jSettings = jExtensions.get("settings").getAsJsonObject();
+                    } else {
+                        jSettings = jExtensions.get("opsettings").getAsJsonObject();
+                    }
+                } else {
+                    continue;
+                }
+            } catch (JsonIOException | JsonSyntaxException | IllegalStateException ex) {
+                logger.log(Level.WARNING, "Error parsing Json from Secure Preferences.", ex); //NON-NLS
+                this.addErrorMessage(NbBundle.getMessage(this.getClass(), "Chrome.getExtensoins.errMsg.errAnalyzingFile",
+                        this.getDisplayName(), extensionFile.getName()));
+                continue;
+            }
+
+            Set<String> extensions = jSettings.keySet();
+            for (String extension : extensions) {
+                JsonElement result = jSettings.get(extension);
+                JsonObject ext = result.getAsJsonObject();
+                if (ext == null) {
+                    continue;
+                }
+                JsonElement flagEl = ext.get("state"); //NON-NLS
+                String flag;
+                if (flagEl != null) {
+                    if (flagEl.getAsInt() == 1) {
+                        flag = "Enabled";
+                    } else {
+                        flag = "Disabled";
+                    }
+                } else {
+                    flag = "";
+                }
+                String apiGrantedPermissions = "";
+                if (ext.has("active_permissions")) {
+                    JsonObject permissions = ext.get("active_permissions").getAsJsonObject();
+                    JsonArray apiPermissions = permissions.get("api").getAsJsonArray();
+                    for (JsonElement apiPermission : apiPermissions) {
+                        String apigrantEl = apiPermission.getAsString();                   
+                        if (apigrantEl != null) {
+                            apiGrantedPermissions = apiGrantedPermissions + ", " + apigrantEl;
+                        } else {
+                            apiGrantedPermissions =  apiGrantedPermissions + "";
+                        }
+                    }                    
+                }
+                String version;
+                String description;
+                String extName;
+                if (ext.has("manifest")) {
+                    JsonObject manifest = ext.get("manifest").getAsJsonObject();
+                    JsonElement descriptionEl = manifest.get("description");
+                    if (descriptionEl != null) {
+                        description = descriptionEl.getAsString();
+                    } else {
+                        description = "";
+                    }
+                    JsonElement versionEl = manifest.get("version");
+                    if (versionEl != null) {
+                        version = versionEl.getAsString();
+                    } else {
+                        version = "";
+                    }
+                    JsonElement extNameEl = manifest.get("name");
+                    if (extNameEl != null) {
+                        extName = extNameEl.getAsString();
+                    } else {
+                        extName = "";
+                    }
+                } else {
+                    version = "";
+                    description = "";
+                    extName = "";
+                }                
+                Collection<BlackboardAttribute> bbattributes = new ArrayList<>();
+                bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_ID,
+                        RecentActivityExtracterModuleFactory.getModuleName(), extension));
+                bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME,
+                        RecentActivityExtracterModuleFactory.getModuleName(), extName));
+                bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DESCRIPTION,
+                        RecentActivityExtracterModuleFactory.getModuleName(), description));
+                bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_VERSION,
+                        RecentActivityExtracterModuleFactory.getModuleName(), version));
+                bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_FLAG,
+                        RecentActivityExtracterModuleFactory.getModuleName(), flag));
+                bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PERMISSIONS,
+                        RecentActivityExtracterModuleFactory.getModuleName(), apiGrantedPermissions.replaceFirst(", ", "")));
+                bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_NAME,
+                        RecentActivityExtracterModuleFactory.getModuleName(), userName));
+                bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME,
+                        RecentActivityExtracterModuleFactory.getModuleName(), browserName));
+
+                try {
+                    bbartifacts.add(createArtifactWithAttributes(localStateArtifactType, extensionFile, bbattributes));
+                } catch (TskCoreException ex) {
+                    logger.log(Level.SEVERE, String.format("Failed to create Extension artifact for file (%d)", extensionFile.getId()), ex);
+                }
+
+            }
+
+            if (!context.dataSourceIngestIsCancelled()) {
+                postArtifacts(bbartifacts);
+            }
+            bbartifacts.clear();
+ 
+        }
+    }
+
     /**
      * Query for history databases and add artifacts
      *
@@ -188,11 +647,12 @@ public void process(Content dataSource, DataSourceIngestModuleProgress progressB
      * @param browserLocation
      * @param ingestJobId     The ingest job id.
      */
-    private void getHistory(String browser, String browserLocation, long ingestJobId) {
+    private void getHistory(String browser, String browserLocation, String userName, long ingestJobId) {
         FileManager fileManager = currentCase.getServices().getFileManager();
+        String browserName = browser;
         List<AbstractFile> historyFiles;
         String historyFileName = HISTORY_FILE_NAME;
-        if (browser.equals(UC_BROWSER_NAME)) {
+        if (browserName.equals(UC_BROWSER_NAME)) {
             historyFileName = HISTORY_FILE_NAME + "%";
         }
         try {
@@ -223,7 +683,11 @@ private void getHistory(String browser, String browserLocation, long ingestJobId
         Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
         int j = 0;
         while (j < allocatedHistoryFiles.size()) {
-            String temps = RAImageIngestModule.getRATempPath(currentCase, browser, ingestJobId) + File.separator + allocatedHistoryFiles.get(j).getName() + j + ".db"; //NON-NLS
+            if (browser.contains(GOOGLE_PROFILE_NAME)) {
+                String parentPath = FilenameUtils.normalizeNoEndSeparator(allocatedHistoryFiles.get(j).getParentPath());
+                browserName = GOOGLE_PROFILE + " " + FilenameUtils.getBaseName(parentPath);
+            }
+            String temps = RAImageIngestModule.getRATempPath(currentCase, browserName, ingestJobId) + File.separator + allocatedHistoryFiles.get(j).getName() + j + ".db"; //NON-NLS
             final AbstractFile historyFile = allocatedHistoryFiles.get(j++);
             if ((historyFile.getSize() == 0) || (historyFile.getName().toLowerCase().contains("-slack"))
                     || (historyFile.getName().toLowerCase().contains("cache")) || (historyFile.getName().toLowerCase().contains("media"))
@@ -263,9 +727,9 @@ private void getHistory(String browser, String browserLocation, long ingestJobId
                         (Long.valueOf(result.get("last_visit_time").toString()) / 1000000) - Long.valueOf("11644473600"),
                         result.get("from_visit") == null ? "" : result.get("from_visit").toString(),
                         result.get("title") == null ? "" : result.get("title").toString(),
-                        browser,
+                        browserName,
                         extractedDomain,
-                        "");
+                        userName);
                                     
                     bbartifacts.add(createArtifactWithAttributes(BlackboardArtifact.Type.TSK_WEB_HISTORY, historyFile, bbattributes));
                 } catch (TskCoreException ex) {
@@ -287,11 +751,12 @@ private void getHistory(String browser, String browserLocation, long ingestJobId
      * @param browserLocation
      * @param ingestJobId     The ingest job id.
      */
-    private void getBookmark(String browser, String browserLocation, long ingestJobId) {
+    private void getBookmark(String browser, String browserLocation, String userName, long ingestJobId) {
         FileManager fileManager = currentCase.getServices().getFileManager();
         List<AbstractFile> bookmarkFiles;
+        String browserName = browser;
         String bookmarkFileName = BOOKMARK_FILE_NAME;
-        if (browser.equals(UC_BROWSER_NAME)) {
+        if (browserName.equals(UC_BROWSER_NAME)) {
             bookmarkFileName = BOOKMARK_FILE_NAME + "%";
         }
         try {
@@ -312,6 +777,11 @@ private void getBookmark(String browser, String browserLocation, long ingestJobI
         Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
         int j = 0;
         while (j < bookmarkFiles.size()) {
+            if (browser.contains(GOOGLE_PROFILE_NAME)) {
+                String parentPath = FilenameUtils.normalizeNoEndSeparator(bookmarkFiles.get(j).getParentPath());
+                browserName = GOOGLE_PROFILE + " " + FilenameUtils.getBaseName(parentPath);
+            }
+
             AbstractFile bookmarkFile = bookmarkFiles.get(j++);
             if ((bookmarkFile.getSize() == 0) || (bookmarkFile.getName().toLowerCase().contains("-slack"))
                     || (bookmarkFile.getName().toLowerCase().contains("extras")) || (bookmarkFile.getName().toLowerCase().contains("log"))
@@ -319,7 +789,7 @@ private void getBookmark(String browser, String browserLocation, long ingestJobI
                     || (bookmarkFile.getName().toLowerCase().contains("bak")) || (bookmarkFile.getParentPath().toLowerCase().contains("backup"))) {
                 continue;
             }
-            String temps = RAImageIngestModule.getRATempPath(currentCase, browser, ingestJobId) + File.separator + bookmarkFile.getName() + j + ".db"; //NON-NLS
+            String temps = RAImageIngestModule.getRATempPath(currentCase, browserName, ingestJobId) + File.separator + bookmarkFile.getName() + j + ".db"; //NON-NLS
             try {
                 ContentUtils.writeToFile(bookmarkFile, new File(temps), context::dataSourceIngestIsCancelled);
             } catch (ReadContentInputStreamException ex) {
@@ -352,15 +822,13 @@ private void getBookmark(String browser, String browserLocation, long ingestJobI
             }
 
             JsonElement jsonElement;
-            JsonObject jElement, jRoot, jBookmark;
-            JsonArray jBookmarkArray;
+            JsonObject jElement, jRoot;
 
             try {
                 jsonElement = JsonParser.parseReader(tempReader);
                 jElement = jsonElement.getAsJsonObject();
                 jRoot = jElement.get("roots").getAsJsonObject(); //NON-NLS
-                jBookmark = jRoot.get("bookmark_bar").getAsJsonObject(); //NON-NLS
-                jBookmarkArray = jBookmark.getAsJsonArray("children"); //NON-NLS
+                Set<String> bookmarkKeys = jRoot.keySet();
             } catch (JsonIOException | JsonSyntaxException | IllegalStateException ex) {
                 logger.log(Level.WARNING, "Error parsing Json from Chrome Bookmark.", ex); //NON-NLS
                 this.addErrorMessage(NbBundle.getMessage(this.getClass(), "Chrome.getBookmark.errMsg.errAnalyzingFile3",
@@ -368,54 +836,64 @@ private void getBookmark(String browser, String browserLocation, long ingestJobI
                 continue;
             }
 
-            for (JsonElement result : jBookmarkArray) {
-                JsonObject address = result.getAsJsonObject();
-                if (address == null) {
-                    continue;
-                }
-                JsonElement urlEl = address.get("url"); //NON-NLS
-                String url;
-                if (urlEl != null) {
-                    url = urlEl.getAsString();
-                } else {
-                    url = "";
-                }
-                String name;
-                JsonElement nameEl = address.get("name"); //NON-NLS
-                if (nameEl != null) {
-                    name = nameEl.getAsString();
-                } else {
-                    name = "";
-                }
-                Long date;
-                JsonElement dateEl = address.get("date_added"); //NON-NLS
-                if (dateEl != null) {
-                    date = dateEl.getAsLong();
-                } else {
-                    date = Long.valueOf(0);
-                }
-                String domain = NetworkUtils.extractDomain(url);
-                Collection<BlackboardAttribute> bbattributes = new ArrayList<>();
-                //TODO Revisit usage of deprecated constructor as per TSK-583
-                bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL,
-                        RecentActivityExtracterModuleFactory.getModuleName(), url));
-                bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_TITLE,
-                        RecentActivityExtracterModuleFactory.getModuleName(), name));
-                bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_CREATED,
-                        RecentActivityExtracterModuleFactory.getModuleName(), (date / 1000000) - Long.valueOf("11644473600")));
-                bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME,
-                        RecentActivityExtracterModuleFactory.getModuleName(), browser));
-                bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
-                        RecentActivityExtracterModuleFactory.getModuleName(), domain));
+            Set<String> bookmarkKeys = jRoot.keySet();
+            for (String bookmarkKey : bookmarkKeys) {
+                JsonObject jBookmark = jRoot.get(bookmarkKey).getAsJsonObject(); //NON-NLS
+                JsonArray jBookmarkArray = jBookmark.getAsJsonArray("children"); //NON-NLS
+                for (JsonElement result : jBookmarkArray) {
+                    JsonObject address = result.getAsJsonObject();
+                    if (address == null) {
+                        continue;
+                    }
+                    JsonElement urlEl = address.get("url"); //NON-NLS
+                    String url;
+                    if (urlEl != null) {
+                        url = urlEl.getAsString();
+                    } else {
+                        url = "";
+                    }
+                    String name;
+                    JsonElement nameEl = address.get("name"); //NON-NLS
+                    if (nameEl != null) {
+                        name = nameEl.getAsString();
+                    } else {
+                        name = "";
+                    }
+                    Long date;
+                    JsonElement dateEl = address.get("date_added"); //NON-NLS
+                    if (dateEl != null) {
+                        date = dateEl.getAsLong();
+                    } else {
+                        date = Long.valueOf(0);
+                    }
+                    String domain = NetworkUtils.extractDomain(url);
+                    Collection<BlackboardAttribute> bbattributes = new ArrayList<>();
+                    //TODO Revisit usage of deprecated constructor as per TSK-583
+                    bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL,
+                            RecentActivityExtracterModuleFactory.getModuleName(), url));
+                    bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_TITLE,
+                            RecentActivityExtracterModuleFactory.getModuleName(), name));
+                    bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_CREATED,
+                            RecentActivityExtracterModuleFactory.getModuleName(), (date / 1000000) - Long.valueOf("11644473600")));
+                    bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME,
+                            RecentActivityExtracterModuleFactory.getModuleName(), browserName));
+                    bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
+                            RecentActivityExtracterModuleFactory.getModuleName(), domain));
+                    bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_NAME,
+                            RecentActivityExtracterModuleFactory.getModuleName(), userName));
+                    bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_COMMENT,
+                            RecentActivityExtracterModuleFactory.getModuleName(), bookmarkKey));
+
+
+                    try {
+                        bbartifacts.add(createArtifactWithAttributes(BlackboardArtifact.Type.TSK_WEB_BOOKMARK, bookmarkFile, bbattributes));
+                    } catch (TskCoreException ex) {
+                        logger.log(Level.SEVERE, String.format("Failed to create bookmark artifact for file (%d)", bookmarkFile.getId()), ex);
+                    }
 
-                try {
-                    bbartifacts.add(createArtifactWithAttributes(BlackboardArtifact.Type.TSK_WEB_BOOKMARK, bookmarkFile, bbattributes));
-                } catch (TskCoreException ex) {
-                    logger.log(Level.SEVERE, String.format("Failed to create bookmark artifact for file (%d)", bookmarkFile.getId()), ex);
                 }
-
             }
-
+            
             if (!context.dataSourceIngestIsCancelled()) {
                 postArtifacts(bbartifacts);
             }
@@ -431,12 +909,13 @@ private void getBookmark(String browser, String browserLocation, long ingestJobI
      * @param browserLocation
      * @param ingestJobId     The ingest job id.
      */
-    private void getCookie(String browser, String browserLocation, long ingestJobId) {
+    private void getCookie(String browser, String browserLocation, String userName, long ingestJobId) {
 
         FileManager fileManager = currentCase.getServices().getFileManager();
         List<AbstractFile> cookiesFiles;
+        String browserName = browser;
         String cookieFileName = COOKIE_FILE_NAME;
-        if (browser.equals(UC_BROWSER_NAME)) {
+        if (browserName.equals(UC_BROWSER_NAME)) {
             // Wildcard on front and back of Cookies are there for Cookie files that start with something else
             // ie: UC browser has "Extension Cookies.9" as well as Cookies.9
             cookieFileName = "%" + COOKIE_FILE_NAME + "%";
@@ -459,11 +938,16 @@ private void getCookie(String browser, String browserLocation, long ingestJobId)
         Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
         int j = 0;
         while (j < cookiesFiles.size()) {
+            if (browser.contains(GOOGLE_PROFILE_NAME)) {
+                String parentPath = FilenameUtils.normalizeNoEndSeparator(cookiesFiles.get(j).getParentPath());
+                browserName = GOOGLE_PROFILE + FilenameUtils.getBaseName(parentPath);
+            }
+            
             AbstractFile cookiesFile = cookiesFiles.get(j++);
             if ((cookiesFile.getSize() == 0) || (cookiesFile.getName().toLowerCase().contains("-slack"))) {
                 continue;
             }
-            String temps = RAImageIngestModule.getRATempPath(currentCase, browser, ingestJobId) + File.separator + cookiesFile.getName() + j + ".db"; //NON-NLS
+            String temps = RAImageIngestModule.getRATempPath(currentCase, browserName, ingestJobId) + File.separator + cookiesFile.getName() + j + ".db"; //NON-NLS
             try {
                 ContentUtils.writeToFile(cookiesFile, new File(temps), context::dataSourceIngestIsCancelled);
             } catch (ReadContentInputStreamException ex) {
@@ -503,11 +987,13 @@ private void getCookie(String browser, String browserLocation, long ingestJobId)
                         RecentActivityExtracterModuleFactory.getModuleName(),
                         ((result.get("value").toString() != null) ? result.get("value").toString() : ""))); //NON-NLS
                 bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME,
-                        RecentActivityExtracterModuleFactory.getModuleName(), browser));
+                        RecentActivityExtracterModuleFactory.getModuleName(), browserName));
                 String domain = result.get("host_key").toString(); //NON-NLS
                 domain = domain.replaceFirst("^\\.+(?!$)", "");
                 bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
                         RecentActivityExtracterModuleFactory.getModuleName(), domain));
+                bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_NAME,
+                        RecentActivityExtracterModuleFactory.getModuleName(), userName));
 
                 try {
                     bbartifacts.add(createArtifactWithAttributes(BlackboardArtifact.Type.TSK_WEB_COOKIE, cookiesFile, bbattributes));
@@ -531,11 +1017,12 @@ private void getCookie(String browser, String browserLocation, long ingestJobId)
      * @param browserLocation
      * @param ingestJobId     The ingest job id.
      */
-    private void getDownload(String browser, String browserLocation, long ingestJobId) {
+    private void getDownload(String browser, String browserLocation, String userName, long ingestJobId) {
         FileManager fileManager = currentCase.getServices().getFileManager();
         List<AbstractFile> downloadFiles;
+        String browserName = browser;
         String historyFileName = HISTORY_FILE_NAME;
-        if (browser.equals(UC_BROWSER_NAME)) {
+        if (browserName.equals(UC_BROWSER_NAME)) {
             historyFileName = HISTORY_FILE_NAME + "%";
         }
         try {
@@ -556,13 +1043,18 @@ private void getDownload(String browser, String browserLocation, long ingestJobI
         Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
         int j = 0;
         while (j < downloadFiles.size()) {
+            if (browser.contains(GOOGLE_PROFILE_NAME)) {
+                String parentPath = FilenameUtils.normalizeNoEndSeparator(downloadFiles.get(j).getParentPath());
+                browserName = GOOGLE_PROFILE + FilenameUtils.getBaseName(parentPath);
+            }
+
             AbstractFile downloadFile = downloadFiles.get(j++);
             if ((downloadFile.getSize() == 0) || (downloadFile.getName().toLowerCase().contains("-slack"))
                     || (downloadFile.getName().toLowerCase().contains("cache")) || (downloadFile.getName().toLowerCase().contains("index"))) {
                 continue;
             }
 
-            String temps = RAImageIngestModule.getRATempPath(currentCase, browser, ingestJobId) + File.separator + downloadFile.getName() + j + ".db"; //NON-NLS
+            String temps = RAImageIngestModule.getRATempPath(currentCase, browserName, ingestJobId) + File.separator + downloadFile.getName() + j + ".db"; //NON-NLS
             try {
                 ContentUtils.writeToFile(downloadFile, new File(temps), context::dataSourceIngestIsCancelled);
             } catch (ReadContentInputStreamException ex) {
@@ -617,8 +1109,10 @@ private void getDownload(String browser, String browserLocation, long ingestJobI
                 String domain = NetworkUtils.extractDomain((result.get("url").toString() != null) ? result.get("url").toString() : ""); //NON-NLS
                 bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
                         RecentActivityExtracterModuleFactory.getModuleName(), domain));
+                bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_NAME,
+                        RecentActivityExtracterModuleFactory.getModuleName(), userName));
                 bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME,
-                        RecentActivityExtracterModuleFactory.getModuleName(), browser));
+                        RecentActivityExtracterModuleFactory.getModuleName(), browserName));
 
                 // find the downloaded file and create a TSK_ASSOCIATED_OBJECT for it, associating it with the TSK_WEB_DOWNLOAD artifact.
                 try {
@@ -642,6 +1136,118 @@ private void getDownload(String browser, String browserLocation, long ingestJobI
         }
     }
 
+    /**
+     * Queries the Favicons table and adds artifacts
+     *
+     * @param browser
+     * @param browserLocation
+     * @param ingestJobId     The ingest job id.
+     */
+    private void getFavicons(String browser, String browserLocation, String userName, long ingestJobId) {
+        FileManager fileManager = currentCase.getServices().getFileManager();
+        List<AbstractFile> faviconFiles;
+        String browserName = browser;
+        try {
+            faviconFiles = fileManager.findFiles(dataSource, FAVICON_DATA_FILE_NAME, browserLocation); //NON-NLS
+        } catch (TskCoreException ex) {
+            String msg = NbBundle.getMessage(this.getClass(), "Chrome.getFavicon.errMsg.errGettingFiles");
+            logger.log(Level.SEVERE, msg, ex);
+            this.addErrorMessage(this.getDisplayName() + ": " + msg);
+            return;
+        }
+
+        if (faviconFiles.isEmpty()) {
+            logger.log(Level.INFO, "Didn't find any Chrome favicon files."); //NON-NLS
+            return;
+        }
+
+        dataFound = true;
+        Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
+        int j = 0;
+        while (j < faviconFiles.size()) {
+            if (browser.contains(GOOGLE_PROFILE_NAME)) {
+                String parentPath = FilenameUtils.normalizeNoEndSeparator(faviconFiles.get(j).getParentPath());
+                browserName = GOOGLE_PROFILE + FilenameUtils.getBaseName(parentPath);
+            }
+            AbstractFile faviconFile = faviconFiles.get(j++);
+            if ((faviconFile.getSize() == 0) || (faviconFile.getName().toLowerCase().contains("-slack"))
+                    || (faviconFile.getName().toLowerCase().contains("cache")) || (faviconFile.getName().toLowerCase().contains("index"))) {
+                continue;
+            }
+
+            String temps = RAImageIngestModule.getRATempPath(currentCase, browserName, ingestJobId) + File.separator + faviconFile.getName() + j + ".db"; //NON-NLS
+            try {
+                ContentUtils.writeToFile(faviconFile, new File(temps), context::dataSourceIngestIsCancelled);
+            } catch (ReadContentInputStreamException ex) {
+                logger.log(Level.WARNING, String.format("Error reading Chrome favicons artifacts file '%s' (id=%d).",
+                        faviconFile.getName(), faviconFile.getId()), ex); //NON-NLS
+                this.addErrorMessage(NbBundle.getMessage(this.getClass(), "Chrome.getFavicon.errMsg.errAnalyzeFiles1",
+                        this.getDisplayName(), faviconFile.getName()));
+                continue;
+            } catch (IOException ex) {
+                logger.log(Level.SEVERE, String.format("Error writing temp sqlite db file '%s' for Chrome favicon artifacts file '%s' (id=%d).",
+                        temps, faviconFile.getName(), faviconFile.getId()), ex); //NON-NLS
+                this.addErrorMessage(NbBundle.getMessage(this.getClass(), "Chrome.getfavicon.errMsg.errAnalyzeFiles1",
+                        this.getDisplayName(), faviconFile.getName()));
+                continue;
+            }
+            File dbFile = new File(temps);
+            if (context.dataSourceIngestIsCancelled()) {
+                dbFile.delete();
+                break;
+            }
+
+            BlackboardArtifact.Type faviconArtifactType;
+
+            try {
+                faviconArtifactType = createArtifactType(FAVICON_ARTIFACT_NAME, NbBundle.getMessage(this.getClass(), "Chrome.getFavicon.displayName"));
+            } catch (TskCoreException ex) {
+                logger.log(Level.SEVERE, String.format("Error creating artifact type for Chrome favicon."), ex); //NON-NLS
+                this.addErrorMessage(NbBundle.getMessage(this.getClass(), "Chrome.getfavicon.errMsg.errCreateArtifact"));
+                continue;
+                
+            }
+            
+            List<HashMap<String, Object>> tempList;
+
+            tempList = this.querySQLiteDb(temps, FAVICON_QUERY);
+
+            logger.log(Level.INFO, "{0}- Now getting favicons from {1} with {2} artifacts identified.", new Object[]{getDisplayName(), temps, tempList.size()}); //NON-NLS
+            for (HashMap<String, Object> result : tempList) {
+                Collection<BlackboardAttribute> bbattributes = new ArrayList<>();
+                bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL,
+                        RecentActivityExtracterModuleFactory.getModuleName(),
+                        ((result.get("page_url").toString() != null) ? result.get("page_url").toString() : ""))); //NON-NLS
+                Long updatedTime = (Long.valueOf(result.get("last_updated").toString()) / 1000000) - Long.valueOf("11644473600"); //NON-NLS
+                bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_MODIFIED,
+                        RecentActivityExtracterModuleFactory.getModuleName(), updatedTime));
+                Long requestedTime = (Long.valueOf(result.get("last_requested").toString()) / 1000000) - Long.valueOf("11644473600"); //NON-NLS
+                bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED,
+                        RecentActivityExtracterModuleFactory.getModuleName(), requestedTime));
+                String domain = NetworkUtils.extractDomain((result.get("page_url").toString() != null) ? result.get("page_url").toString() : ""); //NON-NLS
+                bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
+                        RecentActivityExtracterModuleFactory.getModuleName(), domain));
+                bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_NAME,
+                        RecentActivityExtracterModuleFactory.getModuleName(), userName));
+                bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME,
+                        RecentActivityExtracterModuleFactory.getModuleName(), browserName));
+
+                try {
+                    bbartifacts.add(createArtifactWithAttributes(faviconArtifactType, faviconFile, bbattributes));
+                } catch (TskCoreException ex) {
+                    logger.log(Level.SEVERE, String.format("Failed to create cookie artifact for file (%d)", faviconFile.getId()), ex);
+                }
+
+            }
+
+            dbFile.delete();
+        }
+
+        if (!bbartifacts.isEmpty() && !context.dataSourceIngestIsCancelled()) {
+            postArtifacts(bbartifacts);
+        }
+    }
+
     /**
      * Gets user logins from Login Data sqlite database
      *
@@ -649,12 +1255,13 @@ private void getDownload(String browser, String browserLocation, long ingestJobI
      * @param browserLocation
      * @param ingestJobId     The ingest job id.
      */
-    private void getLogins(String browser, String browserLocation, long ingestJobId) {
+    private void getLogins(String browser, String browserLocation, String userName, long ingestJobId) {
 
         FileManager fileManager = currentCase.getServices().getFileManager();
         List<AbstractFile> loginDataFiles;
+        String browserName = browser;
         String loginDataFileName = LOGIN_DATA_FILE_NAME;
-        if (browser.equals(UC_BROWSER_NAME)) {
+        if (browserName.equals(UC_BROWSER_NAME)) {
             loginDataFileName = LOGIN_DATA_FILE_NAME + "%";
         }
 
@@ -676,11 +1283,15 @@ private void getLogins(String browser, String browserLocation, long ingestJobId)
         Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
         int j = 0;
         while (j < loginDataFiles.size()) {
+            if (browser.contains(GOOGLE_PROFILE_NAME)) {
+                String parentPath = FilenameUtils.normalizeNoEndSeparator(loginDataFiles.get(j).getParentPath());
+                browserName = GOOGLE_PROFILE + FilenameUtils.getBaseName(parentPath);
+            }
             AbstractFile loginDataFile = loginDataFiles.get(j++);
             if ((loginDataFile.getSize() == 0) || (loginDataFile.getName().toLowerCase().contains("-slack"))) {
                 continue;
             }
-            String temps = RAImageIngestModule.getRATempPath(currentCase, browser, ingestJobId) + File.separator + loginDataFile.getName() + j + ".db"; //NON-NLS
+            String temps = RAImageIngestModule.getRATempPath(currentCase, browserName, ingestJobId) + File.separator + loginDataFile.getName() + j + ".db"; //NON-NLS
             try {
                 ContentUtils.writeToFile(loginDataFile, new File(temps), context::dataSourceIngestIsCancelled);
             } catch (ReadContentInputStreamException ex) {
@@ -731,7 +1342,10 @@ private void getLogins(String browser, String browserLocation, long ingestJobId)
                         result.containsKey("signon_realm") ? NetworkUtils.extractDomain(result.get("signon_realm").toString()) : "")); //NON-NLS
 
                 bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME,
-                        RecentActivityExtracterModuleFactory.getModuleName(), browser));
+                        RecentActivityExtracterModuleFactory.getModuleName(), browserName));
+
+                bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_NAME,
+                        RecentActivityExtracterModuleFactory.getModuleName(), userName));
 
                 try {
                     bbartifacts.add(createArtifactWithAttributes(BlackboardArtifact.Type.TSK_SERVICE_ACCOUNT, loginDataFile, bbattributes));
@@ -756,12 +1370,13 @@ private void getLogins(String browser, String browserLocation, long ingestJobId)
      * @param browserLocation
      * @param ingestJobId     The ingest job id.
      */
-    private void getAutofill(String browser, String browserLocation, long ingestJobId) {
+    private void getAutofill(String browser, String browserLocation, String userName, long ingestJobId) {
 
         FileManager fileManager = currentCase.getServices().getFileManager();
         List<AbstractFile> webDataFiles;
+        String browserName = browser;
         String webDataFileName = WEB_DATA_FILE_NAME;
-        if (browser.equals(UC_BROWSER_NAME)) {
+        if (browserName.equals(UC_BROWSER_NAME)) {
             webDataFileName = WEB_DATA_FILE_NAME + "%";
         }
 
@@ -783,12 +1398,16 @@ private void getAutofill(String browser, String browserLocation, long ingestJobI
         Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
         int j = 0;
         while (j < webDataFiles.size()) {
+            if (browser.contains(GOOGLE_PROFILE_NAME)) {
+                String parentPath = FilenameUtils.normalizeNoEndSeparator(webDataFiles.get(j).getParentPath());
+                browserName = GOOGLE_PROFILE + FilenameUtils.getBaseName(parentPath);
+            }
             databaseEncrypted = false;
             AbstractFile webDataFile = webDataFiles.get(j++);
             if ((webDataFile.getSize() == 0) || (webDataFile.getName().toLowerCase().contains("-slack"))) {
                 continue;
             }
-            String tempFilePath = RAImageIngestModule.getRATempPath(currentCase, browser, ingestJobId) + File.separator + webDataFile.getName() + j + ".db"; //NON-NLS
+            String tempFilePath = RAImageIngestModule.getRATempPath(currentCase, browserName, ingestJobId) + File.separator + webDataFile.getName() + j + ".db"; //NON-NLS
             try {
                 ContentUtils.writeToFile(webDataFile, new File(tempFilePath), context::dataSourceIngestIsCancelled);
             } catch (ReadContentInputStreamException ex) {
@@ -814,12 +1433,12 @@ private void getAutofill(String browser, String browserLocation, long ingestJobI
             boolean isSchemaV8X = Util.checkColumn("date_created", "autofill", tempFilePath);
 
             // get form autofill artifacts
-            bbartifacts.addAll(getFormAutofillArtifacts(webDataFile, tempFilePath, isSchemaV8X, browser));
+            bbartifacts.addAll(getFormAutofillArtifacts(webDataFile, tempFilePath, isSchemaV8X, userName, browserName));
             try {
                 // get form address atifacts
                 getFormAddressArtifacts(webDataFile, tempFilePath, isSchemaV8X);
                 if (databaseEncrypted) {
-                    String comment = String.format("%s Autofill Database Encryption Detected", browser);
+                    String comment = String.format("%s Autofill Database Encryption Detected", browserName);
                     Collection<BlackboardAttribute> bbattributes = Arrays.asList(
                             new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_COMMENT,
                                     RecentActivityExtracterModuleFactory.getModuleName(), comment));
@@ -852,7 +1471,7 @@ private void getAutofill(String browser, String browserLocation, long ingestJobI
      *
      * @return collection of TSK_WEB_FORM_AUTOFILL artifacts
      */
-    private Collection<BlackboardArtifact> getFormAutofillArtifacts(AbstractFile webDataFile, String dbFilePath, boolean isSchemaV8X, String browser) {
+    private Collection<BlackboardArtifact> getFormAutofillArtifacts(AbstractFile webDataFile, String dbFilePath, boolean isSchemaV8X, String userName, String browser) {
 
         Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
 
@@ -890,6 +1509,8 @@ private Collection<BlackboardArtifact> getFormAutofillArtifacts(AbstractFile web
                         Long.valueOf(result.get("date_last_used").toString()))); //NON-NLS
             }
 
+            bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_NAME,
+                    RecentActivityExtracterModuleFactory.getModuleName(), userName));
             bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME,
                     RecentActivityExtracterModuleFactory.getModuleName(), browser));
             if (fieldEncrypted) {
@@ -1031,4 +1652,24 @@ private boolean isChromePreVersion30(String temps) {
 
         return false;
     }
+    
+        @Messages({
+        "ExtractFavicon_Display_Name=Favicon"
+    })
+    /**
+     * Create custom artifact type.
+     *
+     * @return the BlackboardArtifact.type of the artifact created
+     * @throws TskCoreException
+     */
+    private BlackboardArtifact.Type createArtifactType(String artifactName, String displayName) throws TskCoreException {
+        BlackboardArtifact.Type faviconArtifactType;
+        try {
+            faviconArtifactType = tskCase.getBlackboard().getOrAddArtifactType(artifactName, displayName); //NON-NLS
+        } catch (Blackboard.BlackboardException ex) {
+            throw new TskCoreException(String.format("An exception was thrown while defining artifact type %s", artifactName), ex);
+        }
+        return faviconArtifactType;
+    }
+
 }