-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathbootstrap.js
More file actions
181 lines (159 loc) · 5.88 KB
/
bootstrap.js
File metadata and controls
181 lines (159 loc) · 5.88 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
/* eslint-disable no-undef */
/* global Components, Services, Zotero, APP_SHUTDOWN */
/**
* Zoclau - Zotero 7 Bootstrap Entry Point
*
* Based on the official Zotero plugin template pattern:
* https://github.com/windingwind/zotero-plugin-template
*
* Lifecycle hooks: startup -> onMainWindowLoad -> onMainWindowUnload -> shutdown
*/
var chromeHandle;
var loadedWindows = new WeakSet();
function install(data, reason) { }
function zoclauLog(message) {
try {
var file = Services.dirsvc.get("ProfD", Components.interfaces.nsIFile);
file.append("zoclau-debug.log");
var foStream = Components.classes["@mozilla.org/network/file-output-stream;1"]
.createInstance(Components.interfaces.nsIFileOutputStream);
// write | create | append
foStream.init(file, 0x02 | 0x08 | 0x10, 420, 0);
var converter = Components.classes["@mozilla.org/intl/converter-output-stream;1"]
.createInstance(Components.interfaces.nsIConverterOutputStream);
converter.init(foStream, "UTF-8", 0, 0);
converter.writeString(new Date().toISOString() + " " + message + "\n");
converter.close();
} catch (e) {
try {
Services.console.logStringMessage("[Zoclau] log failure: " + e);
} catch {
// ignore
}
}
}
function formatError(err) {
if (!err) return "unknown error";
try {
var stack = err.stack ? ("\n" + err.stack) : "";
return String(err) + stack;
} catch {
return String(err);
}
}
function getPluginModule() {
if (!Zotero) return null;
return Zotero.Zoclau || Zotero.ZeClau || null;
}
function handleWindowLoad(window, reason) {
if (!window) return;
if (loadedWindows.has(window)) return;
loadedWindows.add(window);
var plugin = getPluginModule();
if (plugin && plugin.onMainWindowLoad) {
plugin.onMainWindowLoad(window);
zoclauLog("onMainWindowLoad handler executed (manual)");
} else {
zoclauLog("onMainWindowLoad skipped (missing handler, manual)");
}
}
async function startup({ id, version, resourceURI, rootURI }, reason) {
zoclauLog("startup begin reason=" + reason + " rootURI=" + rootURI);
try {
// Register chrome so we can use chrome:// URIs for content
var aomStartup = Components.classes[
"@mozilla.org/addons/addon-manager-startup;1"
].getService(Components.interfaces.amIAddonManagerStartup);
var manifestURI = Services.io.newURI(rootURI + "manifest.json");
chromeHandle = aomStartup.registerChrome(manifestURI, [
["content", "zoclau", rootURI + "content/"],
]);
zoclauLog("startup chrome registered");
// Load the main plugin script through chrome:// for packed/unpacked compatibility
Services.scriptloader.loadSubScript("chrome://zoclau/content/zoclau.js");
if (Zotero && Zotero.Zoclau && !Zotero.ZeClau) {
Zotero.ZeClau = Zotero.Zoclau;
}
var plugin = getPluginModule();
zoclauLog(
"startup subscript loaded, has Zotero.Zoclau=" +
!!(Zotero && Zotero.Zoclau) +
" has Zotero.ZeClau=" +
!!(Zotero && Zotero.ZeClau)
);
// Initialize plugin (non-window tasks: register prefs, detect CLI, etc.)
if (plugin && plugin.init) {
await plugin.init({ id, version, rootURI });
zoclauLog("startup init completed");
} else {
zoclauLog("startup init skipped (missing plugin.init)");
}
// At app startup, the main window can already be open before this addon finishes loading.
// Call onMainWindowLoad for existing browser windows to ensure UI is mounted.
try {
var windows = Services.wm.getEnumerator("navigator:browser");
while (windows.hasMoreElements()) {
var win = windows.getNext();
handleWindowLoad(win, reason);
}
} catch (e2) {
zoclauLog("startup existing-window pass failed: " + formatError(e2));
}
} catch (e) {
zoclauLog("startup error: " + formatError(e));
throw e;
}
}
// Called automatically by Zotero 7 when the main window is loaded
async function onMainWindowLoad({ window }, reason) {
zoclauLog("onMainWindowLoad reason=" + reason);
try {
handleWindowLoad(window, reason);
} catch (e) {
zoclauLog("onMainWindowLoad error: " + formatError(e));
throw e;
}
}
// Called automatically by Zotero 7 when the main window is unloaded
async function onMainWindowUnload({ window }, reason) {
zoclauLog("onMainWindowUnload reason=" + reason);
try {
if (window && loadedWindows.has(window)) {
loadedWindows.delete(window);
}
var plugin = getPluginModule();
if (plugin && plugin.onMainWindowUnload) {
plugin.onMainWindowUnload(window);
zoclauLog("onMainWindowUnload handler executed");
} else {
zoclauLog("onMainWindowUnload skipped (missing handler)");
}
} catch (e) {
zoclauLog("onMainWindowUnload error: " + formatError(e));
throw e;
}
}
async function shutdown({ id, version, resourceURI, rootURI }, reason) {
zoclauLog("shutdown begin reason=" + reason);
if (reason === APP_SHUTDOWN) {
return;
}
try {
var plugin = getPluginModule();
if (plugin && plugin.shutdown) {
plugin.shutdown();
zoclauLog("shutdown handler executed");
}
Zotero.Zoclau = undefined;
Zotero.ZeClau = undefined;
if (chromeHandle) {
chromeHandle.destruct();
chromeHandle = null;
zoclauLog("shutdown chrome handle destructed");
}
} catch (e) {
zoclauLog("shutdown error: " + formatError(e));
throw e;
}
}
function uninstall(data, reason) { }