Skip to content
This repository was archived by the owner on May 25, 2025. It is now read-only.

Commit 25fd4a7

Browse files
committed
feat(gmail): demo2
1 parent 08ff00c commit 25fd4a7

File tree

5 files changed

+586
-39
lines changed

5 files changed

+586
-39
lines changed

src/apps/modules/src/actors/NRWebContentModifierChild.sys.mts

Lines changed: 191 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,12 @@ const { setTimeout } = ChromeUtils.importESModule(
66
"resource://gre/modules/Timer.sys.mjs",
77
);
88

9+
// Define a type for the Gmail callback
10+
type GmailCallback = (result: { success: boolean; message?: string }) => void;
11+
912
export class NRWebContentModifierChild extends JSWindowActorChild {
1013
private oneDriveFileListCallback: ((data: string) => void) | null = null;
14+
private gmailCallbacks: Map<string, GmailCallback> = new Map(); // Map to store Gmail callbacks
1115
private callbackTabId: string | null = null;
1216
private extractionAttempts: number = 0;
1317

@@ -19,6 +23,10 @@ export class NRWebContentModifierChild extends JSWindowActorChild {
1923
Cu.exportFunction(this.NRGetOneDriveFileNameList.bind(this), window, {
2024
defineAs: "NRGetOneDriveFileNameList",
2125
});
26+
// Export NRSendGmail
27+
Cu.exportFunction(this.NRSendGmail.bind(this), window, {
28+
defineAs: "NRSendGmail",
29+
});
2230
}
2331
}
2432

@@ -94,12 +102,33 @@ export class NRWebContentModifierChild extends JSWindowActorChild {
94102
// 別のタブから送られてきたファイルデータを処理
95103
if (this.oneDriveFileListCallback) {
96104
console.log(
97-
"NRWebContentModifier: Executing callback with file data from another tab",
105+
"NRWebContentModifier: Executing OneDrive callback with file data from another tab",
98106
);
99107
this.oneDriveFileListCallback(message.data.fileListJson);
100108
return { success: true };
101109
}
102-
return { success: false, reason: "No callback registered in this tab" };
110+
return {
111+
success: false,
112+
reason: "No OneDrive callback registered in this tab",
113+
};
114+
115+
// Handle message to fill and send Gmail
116+
case "WebContentModifier:FillAndSendGmail":
117+
console.log("NRWebContentModifier: Received FillAndSendGmail message");
118+
this.fillAndSendGmail(
119+
message.data.to,
120+
message.data.subject,
121+
message.data.body,
122+
message.data.callbackId,
123+
);
124+
return null;
125+
126+
// Handle result callback from Gmail tab
127+
// Asynchronous operation
128+
case "WebContentModifier:GmailResult":
129+
console.log("NRWebContentModifier: Received GmailResult message");
130+
this.handleGmailResult(message.data.callbackId, message.data.result);
131+
return null;
103132
}
104133
return null;
105134
}
@@ -478,4 +507,164 @@ export class NRWebContentModifierChild extends JSWindowActorChild {
478507
};
479508
}
480509
}
510+
511+
// Function called from settings page to initiate Gmail sending
512+
NRSendGmail(
513+
to: string,
514+
subject: string,
515+
body: string,
516+
callback: GmailCallback,
517+
): void {
518+
console.log("NRWebContentModifier: NRSendGmail called", {
519+
to,
520+
subject,
521+
body,
522+
});
523+
const callbackId = `gmail_${Date.now()}_${Math.random()}`;
524+
this.gmailCallbacks.set(callbackId, callback);
525+
console.log(
526+
`NRWebContentModifier: Registered Gmail callback with ID: ${callbackId}`,
527+
);
528+
529+
this.sendAsyncMessage("WebContentModifier:OpenGmailCompose", {
530+
to,
531+
subject,
532+
body,
533+
callbackId, // Send the callback ID to the parent
534+
});
535+
}
536+
537+
// Handles the result message from the parent actor
538+
handleGmailResult(
539+
callbackId: string,
540+
result: { success: boolean; message?: string },
541+
): void {
542+
const callback = this.gmailCallbacks.get(callbackId);
543+
if (callback) {
544+
console.log(
545+
`NRWebContentModifier: Executing Gmail callback for ID: ${callbackId}`,
546+
result,
547+
);
548+
try {
549+
callback(result);
550+
} catch (e) {
551+
console.error(
552+
"NRWebContentModifier: Error executing Gmail callback:",
553+
e,
554+
);
555+
}
556+
this.gmailCallbacks.delete(callbackId); // Clean up the callback
557+
} else {
558+
console.warn(
559+
`NRWebContentModifier: No Gmail callback found for ID: ${callbackId}`,
560+
);
561+
}
562+
}
563+
564+
// This function runs in the Gmail compose tab
565+
async fillAndSendGmail(
566+
to: string,
567+
subject: string,
568+
body: string,
569+
callbackId: string,
570+
): Promise<void> {
571+
console.log("NRWebContentModifier: Attempting to fill and send Gmail", {
572+
to,
573+
subject,
574+
/* body shortened */ body: body.substring(0, 50) + "...",
575+
callbackId,
576+
});
577+
578+
// --- SELECTORS TO BE DEFINED LATER --- // <<< EDIT ME: Replace with actual selectors when known
579+
const toSelector = "input[aria-expanded='false']";
580+
const subjectSelector = "input[name='subjectbox']";
581+
const bodySelector = "div[writingsuggestions='false']";
582+
const sendButtonSelector = "[jslog^='32601;']";
583+
// --- END OF SELECTORS --- //
584+
585+
try {
586+
// Wait for elements to appear (simple delay for now, robust checking needed)
587+
await new Promise((resolve) => setTimeout(resolve, 5000)); // Wait 5 seconds for compose window
588+
589+
console.log("NRWebContentModifier: Looking for Gmail fields...");
590+
591+
const toElement = this.document?.querySelector(
592+
toSelector,
593+
) as HTMLTextAreaElement;
594+
const subjectElement = this.document?.querySelector(
595+
subjectSelector,
596+
) as HTMLInputElement;
597+
const bodyElement = this.document?.querySelector(
598+
bodySelector,
599+
) as HTMLDivElement;
600+
const sendButtonElement = this.document?.querySelector(
601+
sendButtonSelector,
602+
) as HTMLDivElement;
603+
604+
if (!toElement || !subjectElement || !bodyElement || !sendButtonElement) {
605+
console.error(
606+
"NRWebContentModifier: Could not find all Gmail elements.",
607+
{
608+
toElement: !!toElement,
609+
subjectElement: !!subjectElement,
610+
bodyElement: !!bodyElement,
611+
sendButtonElement: !!sendButtonElement,
612+
},
613+
);
614+
throw new Error("Could not find all required Gmail compose elements.");
615+
}
616+
617+
console.log(
618+
"NRWebContentModifier: Found Gmail elements, filling fields...",
619+
);
620+
621+
// Fill the fields
622+
// For 'To', directly setting value might work, or might need input simulation
623+
toElement.value = to;
624+
// Dispatch input event if needed
625+
toElement.dispatchEvent(new Event("input", { bubbles: true }));
626+
toElement.dispatchEvent(new Event("change", { bubbles: true }));
627+
628+
subjectElement.value = subject;
629+
subjectElement.dispatchEvent(new Event("input", { bubbles: true }));
630+
631+
// Body might be a contentEditable div
632+
bodyElement.focus(); // Ensure focus before manipulating
633+
// Clear existing content if necessary
634+
// bodyElement.innerHTML = '';
635+
// Set new content - plain text for now
636+
bodyElement.textContent = body;
637+
// Dispatch input event to simulate typing
638+
bodyElement.dispatchEvent(new Event("input", { bubbles: true }));
639+
640+
// Short delay before clicking send
641+
await new Promise((resolve) => setTimeout(resolve, 1000));
642+
643+
console.log("NRWebContentModifier: Clicking send button...");
644+
sendButtonElement.click();
645+
646+
console.log(
647+
"NRWebContentModifier: Send button clicked. Assuming success for now.",
648+
);
649+
650+
// Send success result back to parent
651+
this.sendAsyncMessage("WebContentModifier:GmailSent", {
652+
callbackId: callbackId,
653+
result: { success: true },
654+
});
655+
} catch (error) {
656+
console.error(
657+
"NRWebContentModifier: Error filling or sending Gmail:",
658+
error,
659+
);
660+
// Send failure result back to parent
661+
this.sendAsyncMessage("WebContentModifier:GmailSent", {
662+
callbackId: callbackId,
663+
result: {
664+
success: false,
665+
message: error instanceof Error ? error.message : String(error),
666+
},
667+
});
668+
}
669+
}
481670
}

0 commit comments

Comments
 (0)