Skip to content

Implement Gmail activity tracking with optional metadata extraction#218

Open
RaoufGhrissi wants to merge 1 commit intoActivityWatch:masterfrom
RaoufGhrissi:feat/gmail-tracking
Open

Implement Gmail activity tracking with optional metadata extraction#218
RaoufGhrissi wants to merge 1 commit intoActivityWatch:masterfrom
RaoufGhrissi:feat/gmail-tracking

Conversation

@RaoufGhrissi
Copy link
Copy Markdown

ActivityWatch is used in timesheet tracking, and knowing just "reading" or "composing" email info is not very useful on its own. Extracting involved email metadata (Sender, Recipients, Subject) helps determine the context of the activity relative to project models and workflows in the used software.

A new setting has been added to allow users to enable or disable Gmail tracking.

Also added a build.sh script to simplify the build and test process for Chrome and Firefox.

@RaoufGhrissi RaoufGhrissi force-pushed the feat/gmail-tracking branch from b06c12e to 2c15ffd Compare April 4, 2026 17:39
@BelKed
Copy link
Copy Markdown
Contributor

BelKed commented Apr 4, 2026

Hi! I might be wrong, but it seems to me that aw-watcher-web is meant to stay pretty focused on web watching. Because of that, I’d probably suggest implementing this as a separate extension instead :)

RaoufGhrissi added a commit to odoo/aw-webui that referenced this pull request Apr 4, 2026
@RaoufGhrissi RaoufGhrissi force-pushed the feat/gmail-tracking branch from 2c15ffd to d3f63b9 Compare April 4, 2026 17:47
@RaoufGhrissi RaoufGhrissi changed the title Implement Gmail activity tracking with optional metadata extraction (Sender, Subject, Composing state) Implement Gmail activity tracking with optional metadata extraction Apr 4, 2026
@RaoufGhrissi RaoufGhrissi marked this pull request as ready for review April 4, 2026 17:50
@greptile-apps
Copy link
Copy Markdown

greptile-apps bot commented Apr 4, 2026

Greptile Summary

This PR adds opt-in Gmail activity tracking: a content script scrapes compose/reading metadata (sender, recipients, subject) and forwards it to the background via a message channel, where performHeartbeat handles finalization and storage. Most of the issues raised in earlier review rounds have been resolved — polling interval, dynamic enable/disable, finalizeOnly storage correctness, and sender.tab usage are all addressed.

Confidence Score: 5/5

Safe to merge — all prior P0/P1 concerns are resolved; remaining findings are minor style and UX suggestions.

All issues from previous review rounds (polling frequency, dynamic enable/disable, finalizeOnly correctness, ghost finalization, sender.tab usage, type safety, shebang) have been addressed. The three remaining comments are P2: a redundant storage read, a missing UI disclosure about captured data scope, and a low-probability async race on the alarm/message interleave path.

src/background/heartbeat.ts (async race), src/popup/index.html (UX disclosure)

Vulnerabilities

  • Email metadata (sender address, recipient addresses, subject line) is extracted from the DOM and sent to a local ActivityWatch server. This is intentional, but users are not explicitly informed in the UI about the scope of data captured when they enable "Gmail details."
  • No credentials, tokens, or email body content are extracted.
  • The message handler in setupMessageListener correctly validates sender.tab.url against mail.google.com before processing, preventing spoofed messages from arbitrary content scripts.

Important Files Changed

Filename Overview
src/content/gmail.ts New content script: implements dual-interval (5 s detect + 60 s pulse) Gmail tracking with dynamic start/stop via storage.onChanged. Minor: startup double-read can be simplified.
src/background/heartbeat.ts Adds performHeartbeat() and setupMessageListener(); finalizeOnly path now correctly clears storage. Low-probability storage race between alarm and message handlers remains.
src/background/main.ts Wires setupMessageListener(client) into background init; clean and correct.
src/popup/index.html Adds Gmail-enabled checkbox; label "Gmail details:" doesn't communicate that PII (sender/recipients/subject) is being captured.
src/popup/main.ts Gmail checkbox wired up correctly; setGmailEnabled not awaited but consistent with existing setEnabled pattern.
src/storage.ts Adds getGmailEnabled/setGmailEnabled helpers following existing storage patterns; correct.
src/manifest.json Adds content_scripts entry for mail.google.com; .ts reference is consistent with how background scripts are declared and handled by the build system.
build.sh Convenience script for building both Chrome and Firefox artifacts; shebang is present, script is straightforward.

Sequence Diagram

sequenceDiagram
    participant GCS as gmail.ts (content script)
    participant BG as background/heartbeat.ts
    participant AW as ActivityWatch

    Note over GCS: detectIntervalId fires every 5s
    GCS->>GCS: sendGmailHeartbeat() — scrape DOM metadata
    GCS-->>BG: runtime.sendMessage(AW_GMAIL_HEARTBEAT, metadata)

    BG->>BG: setupMessageListener handler reads sender.tab, builds data
    BG->>BG: performHeartbeat(client, data)
    alt previousData differs from data
        BG->>AW: sendHeartbeat(previousData, now-1ms) — finalize old event
    end
    BG->>AW: sendHeartbeat(data, now) — record new event
    BG->>BG: setHeartbeatData(data)

    Note over GCS: pulseIntervalId fires every 60s
    GCS-->>BG: runtime.sendMessage(AW_GMAIL_HEARTBEAT, lastData)
    BG->>AW: sendHeartbeat(lastData, now) — keep event alive

    Note over BG: Alarm fires every 60s
    BG->>BG: heartbeat() — gmailEnabled=true on mail.google.com
    BG->>BG: performHeartbeat(genericGmailData, finalizeOnly:true)
    alt previousData (gmail metadata) differs from genericGmailData
        BG->>AW: sendHeartbeat(previousData, now-1ms) — finalize gmail event
    end
    BG->>BG: browser.storage.local.remove('heartbeatData')
Loading

Reviews (8): Last reviewed commit: "Implement Gmail activity tracking with o..." | Re-trigger Greptile

@RaoufGhrissi
Copy link
Copy Markdown
Author

RaoufGhrissi commented Apr 4, 2026

Hi! I might be wrong, but it seems to me that aw-watcher-web is meant to stay pretty focused on web watching. Because of that, I’d probably suggest implementing this as a separate extension instead :)

Hi @BelKed thanks,
Correct me if i'm wrong but Gmail still happens in the browser, so it is web watching
I tried to do it in the same extension and bucket to avoid making it hard for users to manage their setup via 2 extensions.

@RaoufGhrissi RaoufGhrissi marked this pull request as draft April 4, 2026 18:11
@RaoufGhrissi RaoufGhrissi force-pushed the feat/gmail-tracking branch 9 times, most recently from 5a79cb0 to 4907627 Compare April 8, 2026 08:45
@RaoufGhrissi RaoufGhrissi marked this pull request as ready for review April 8, 2026 08:47
@greptile-apps
Copy link
Copy Markdown

greptile-apps bot commented Apr 8, 2026

Tip:

Greploops — Automatically fix all review issues by running /greploops in Claude Code. It iterates: fix, push, re-review, repeat until 5/5 confidence.

Use the Greptile plugin for Claude Code to query reviews, search comments, and manage custom context directly from your terminal.

@RaoufGhrissi RaoufGhrissi force-pushed the feat/gmail-tracking branch from 4907627 to 86b92d7 Compare April 8, 2026 09:42
@RaoufGhrissi RaoufGhrissi marked this pull request as draft April 8, 2026 09:42
@RaoufGhrissi RaoufGhrissi marked this pull request as ready for review April 8, 2026 09:42
@RaoufGhrissi RaoufGhrissi force-pushed the feat/gmail-tracking branch from 86b92d7 to 767154a Compare April 8, 2026 11:41
@RaoufGhrissi RaoufGhrissi marked this pull request as draft April 8, 2026 11:41
@RaoufGhrissi RaoufGhrissi marked this pull request as ready for review April 8, 2026 11:41
@RaoufGhrissi RaoufGhrissi force-pushed the feat/gmail-tracking branch from 767154a to a7ce5f1 Compare April 8, 2026 16:43
@RaoufGhrissi RaoufGhrissi marked this pull request as draft April 8, 2026 16:44
@RaoufGhrissi RaoufGhrissi force-pushed the feat/gmail-tracking branch from a7ce5f1 to 70bff2d Compare April 8, 2026 16:46
@RaoufGhrissi RaoufGhrissi marked this pull request as ready for review April 8, 2026 16:46
@RaoufGhrissi RaoufGhrissi force-pushed the feat/gmail-tracking branch from 70bff2d to 1dd455c Compare April 8, 2026 21:38
@RaoufGhrissi RaoufGhrissi marked this pull request as draft April 8, 2026 21:38
@RaoufGhrissi RaoufGhrissi marked this pull request as ready for review April 8, 2026 21:38
@RaoufGhrissi RaoufGhrissi force-pushed the feat/gmail-tracking branch from 1dd455c to 544b800 Compare April 8, 2026 22:18
@RaoufGhrissi RaoufGhrissi marked this pull request as draft April 8, 2026 22:19
@RaoufGhrissi RaoufGhrissi marked this pull request as ready for review April 8, 2026 22:19
ActivityWatch is used in timesheet tracking, and knowing just "reading" or "composing"
email info is not very useful on its own. Extracting involved email metadata (Sender, Recipients, Subject)
helps determine the context of the activity relative to project models and workflows in the used software.

A new setting has been added to allow users to enable or disable Gmail tracking.

Also added a build.sh script to simplify the build and test process for Chrome and Firefox.

ui related changes: ActivityWatch/aw-webui#796
@RaoufGhrissi RaoufGhrissi force-pushed the feat/gmail-tracking branch from 544b800 to c598b86 Compare April 8, 2026 22:24
@RaoufGhrissi RaoufGhrissi marked this pull request as draft April 8, 2026 22:25
@RaoufGhrissi RaoufGhrissi marked this pull request as ready for review April 8, 2026 22:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants