Skip to content

Commit 3fcb7a5

Browse files
Merge pull request #60 from slai/google_chrome_profiles_add_path_col
google_chrome_profiles: add path column
2 parents 4aa0196 + efb8970 commit 3fcb7a5

File tree

2 files changed

+60
-4
lines changed

2 files changed

+60
-4
lines changed

tables/chromeuserprofiles/chrome_user_profiles.go

+23-1
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ func GoogleChromeProfilesColumns() []table.ColumnDefinition {
6363
table.TextColumn("email"),
6464
table.TextColumn("name"),
6565
table.IntegerColumn("ephemeral"),
66+
table.TextColumn("path"),
6667
}
6768
}
6869

@@ -77,18 +78,39 @@ func generateForPath(ctx context.Context, fileInfo userFileInfo) ([]map[string]s
7778
return nil, errors.Wrap(err, "unmarshalling chome local state")
7879
}
7980

80-
for _, profileInfo := range localState.Profile.InfoCache {
81+
for profileDir, profileInfo := range localState.Profile.InfoCache {
82+
profilePath, err := profilePathStat(fileInfo.path, profileDir)
83+
if errors.Is(err, os.ErrNotExist) {
84+
// the path is constructed from Chrome's internal data, so if it
85+
// doesn't exist for whatever reason, just leave it blank
86+
profilePath = ""
87+
} else if err != nil {
88+
return nil, errors.Wrap(err, "checking profile path exists")
89+
}
90+
8191
results = append(results, map[string]string{
8292
"username": fileInfo.user,
8393
"email": profileInfo.Email,
8494
"name": profileInfo.Name,
8595
"ephemeral": strconv.Itoa(btoi(profileInfo.Ephemeral)),
96+
"path": profilePath,
8697
})
8798
}
8899

89100
return results, nil
90101
}
91102

103+
func profilePathStat(localStatePath, profileDir string) (string, error) {
104+
localStateDir := filepath.Dir(localStatePath)
105+
profilePath := filepath.Join(localStateDir, profileDir)
106+
107+
if _, err := os.Stat(profilePath); err != nil {
108+
return "", err
109+
}
110+
111+
return profilePath, nil
112+
}
113+
92114
func GoogleChromeProfilesGenerate(ctx context.Context, queryContext table.QueryContext) ([]map[string]string, error) {
93115
osChromeLocalStateDirs, ok := chromeLocalStateDirs[runtime.GOOS]
94116
if !ok {

tables/chromeuserprofiles/chrome_user_profiles_test.go

+37-3
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@ func TestBtoi(t *testing.T) {
1717

1818
func TestGoogleChromeProfilesColumns(t *testing.T) {
1919
columns := GoogleChromeProfilesColumns()
20-
assert.Len(t, columns, 4)
20+
assert.Len(t, columns, 5)
2121

22-
expectedColumnNames := []string{"username", "email", "name", "ephemeral"}
22+
expectedColumnNames := []string{"username", "email", "name", "ephemeral", "path"}
2323
for i, column := range columns {
2424
assert.Equal(t, expectedColumnNames[i], column.Name)
2525
}
@@ -61,6 +61,12 @@ func TestGenerateForPath(t *testing.T) {
6161
// Create a temporary directory for testing
6262
tempDir := t.TempDir()
6363

64+
// Create a placeholder directory for one of the profiles - the name is the
65+
// info_cache map key, not the 'name' value
66+
profile1Path := filepath.Join(tempDir, "profile1")
67+
err := os.Mkdir(profile1Path, os.ModePerm)
68+
assert.NoError(t, err)
69+
6470
// Create a test Chrome local state file
6571
localStateFile := filepath.Join(tempDir, "Local State")
6672
localStateData := `{
@@ -80,7 +86,7 @@ func TestGenerateForPath(t *testing.T) {
8086
}
8187
}`
8288

83-
err := os.WriteFile(localStateFile, []byte(localStateData), os.ModePerm)
89+
err = os.WriteFile(localStateFile, []byte(localStateData), os.ModePerm)
8490
assert.NoError(t, err)
8591

8692
// Test generateForPath
@@ -99,14 +105,42 @@ func TestGenerateForPath(t *testing.T) {
99105
"email": "[email protected]",
100106
"name": "Profile 1",
101107
"ephemeral": "0",
108+
"path": profile1Path,
102109
},
103110
{
104111
"username": "testuser",
105112
"email": "[email protected]",
106113
"name": "Profile 2",
107114
"ephemeral": "1",
115+
// this profile directory doesn't exist, so the path should be blank
116+
"path": "",
108117
},
109118
}
110119

111120
assert.ElementsMatch(t, expectedProfiles, results)
112121
}
122+
123+
func TestProfilePathStat(t *testing.T) {
124+
t.Run("profile directory exists", func(t *testing.T) {
125+
tempDir := t.TempDir()
126+
127+
localStatePath := filepath.Join(tempDir, "Local State")
128+
129+
profilePath := filepath.Join(tempDir, "profile1")
130+
err := os.Mkdir(profilePath, os.ModePerm)
131+
assert.NoError(t, err)
132+
133+
actual, err := profilePathStat(localStatePath, "profile1")
134+
assert.NoError(t, err)
135+
assert.Equal(t, profilePath, actual)
136+
})
137+
138+
t.Run("profile directory does not exist", func(t *testing.T) {
139+
tempDir := t.TempDir()
140+
141+
localStatePath := filepath.Join(tempDir, "Local State")
142+
143+
_, err := profilePathStat(localStatePath, "profile-does-not-exist")
144+
assert.ErrorIs(t, err, os.ErrNotExist)
145+
})
146+
}

0 commit comments

Comments
 (0)