Changeset View
Changeset View
Standalone View
Standalone View
extension/extension.js
Show First 20 Lines • Show All 81 Lines • ▼ Show 20 Line(s) | |||||
82 | // System | 82 | // System | ||
83 | // ------------------------------------------------------------------------ | 83 | // ------------------------------------------------------------------------ | ||
84 | // | 84 | // | ||
85 | 85 | | |||
86 | // When connecting to native host fails (e.g. not installed), we immediately get a disconnect | 86 | // When connecting to native host fails (e.g. not installed), we immediately get a disconnect | ||
87 | // event immediately afterwards. Also avoid infinite restart loop then. | 87 | // event immediately afterwards. Also avoid infinite restart loop then. | ||
88 | var receivedMessageOnce = false; | 88 | var receivedMessageOnce = false; | ||
89 | 89 | | |||
90 | var portStatus = ""; | ||||
91 | var portLastErrorMessage = undefined; | ||||
92 | | ||||
93 | function updateBrowserAction() { | ||||
94 | let enableAction = false; | ||||
95 | if (portStatus === "UNSUPPORTED_OS" || portStatus === "STARTUP_FAILED") { | ||||
96 | chrome.browserAction.setIcon({ | ||||
97 | path: { | ||||
98 | // FIXME needs proper icon, cf. Bug 410821 | ||||
99 | "128": "icons/plasma-disabled-128.png" | ||||
100 | } | ||||
101 | }); | ||||
102 | enableAction = true; | ||||
103 | } | ||||
104 | | ||||
105 | if (portLastErrorMessage) { | ||||
106 | chrome.browserAction.setBadgeText({ text: "!" }); | ||||
107 | chrome.browserAction.setBadgeBackgroundColor({ color: "#da4453" }); // breeze "negative" color | ||||
108 | enableAction = true; | ||||
109 | } else { | ||||
110 | chrome.browserAction.setBadgeText({ text: "" }); | ||||
111 | } | ||||
112 | | ||||
113 | if (enableAction) { | ||||
114 | chrome.browserAction.enable(); | ||||
115 | } else { | ||||
116 | chrome.browserAction.disable(); | ||||
117 | } | ||||
118 | } | ||||
119 | updateBrowserAction(); | ||||
120 | | ||||
90 | // Check for supported platform to avoid loading it on e.g. Windows and then failing | 121 | // Check for supported platform to avoid loading it on e.g. Windows and then failing | ||
91 | // when the extension got synced to another device and then failing | 122 | // when the extension got synced to another device and then failing | ||
92 | chrome.runtime.getPlatformInfo(function (info) { | 123 | chrome.runtime.getPlatformInfo(function (info) { | ||
93 | if (!SUPPORTED_PLATFORMS.includes(info.os)) { | 124 | if (!SUPPORTED_PLATFORMS.includes(info.os)) { | ||
94 | console.log("This extension is not supported on", info.os); | 125 | console.log("This extension is not supported on", info.os); | ||
126 | portStatus = "UNSUPPORTED_OS"; | ||||
127 | updateBrowserAction(); | ||||
95 | return; | 128 | return; | ||
96 | } | 129 | } | ||
97 | 130 | | |||
98 | connectHost(); | 131 | connectHost(); | ||
99 | }); | 132 | }); | ||
100 | 133 | | |||
101 | function connectHost() { | 134 | function connectHost() { | ||
102 | port = chrome.runtime.connectNative("org.kde.plasma.browser_integration"); | 135 | port = chrome.runtime.connectNative("org.kde.plasma.browser_integration"); | ||
103 | 136 | | |||
104 | port.onMessage.addListener(function (message) { | 137 | port.onMessage.addListener(function (message) { | ||
105 | var subsystem = message.subsystem; | 138 | var subsystem = message.subsystem; | ||
106 | var action = message.action; | 139 | var action = message.action; | ||
107 | 140 | | |||
108 | let isReply = message.hasOwnProperty("replyToSerial"); | 141 | let isReply = message.hasOwnProperty("replyToSerial"); | ||
109 | let replyToSerial = message.replyToSerial; | 142 | let replyToSerial = message.replyToSerial; | ||
110 | 143 | | |||
111 | if (!isReply && (!subsystem || !action)) { | 144 | if (!isReply && (!subsystem || !action)) { | ||
112 | return; | 145 | return; | ||
113 | } | 146 | } | ||
114 | 147 | | |||
148 | if (portStatus) { | ||||
149 | portStatus = ""; | ||||
150 | updateBrowserAction(); | ||||
151 | } | ||||
152 | | ||||
115 | receivedMessageOnce = true; | 153 | receivedMessageOnce = true; | ||
116 | 154 | | |||
117 | if (isReply) { | 155 | if (isReply) { | ||
118 | let replyResolver = pendingMessageReplyResolvers[replyToSerial]; | 156 | let replyResolver = pendingMessageReplyResolvers[replyToSerial]; | ||
119 | if (replyResolver) { | 157 | if (replyResolver) { | ||
120 | replyResolver(message.payload); | 158 | replyResolver(message.payload); | ||
121 | delete pendingMessageReplyResolvers[replyToSerial]; | 159 | delete pendingMessageReplyResolvers[replyToSerial]; | ||
122 | } else { | 160 | } else { | ||
Show All 10 Lines | |||||
133 | }); | 171 | }); | ||
134 | 172 | | |||
135 | port.onDisconnect.addListener(function() { | 173 | port.onDisconnect.addListener(function() { | ||
136 | var error = chrome.runtime.lastError; | 174 | var error = chrome.runtime.lastError; | ||
137 | 175 | | |||
138 | console.warn("Host disconnected", error); | 176 | console.warn("Host disconnected", error); | ||
139 | 177 | | |||
140 | // Remove all kde connect menu entries since they won't work without a host | 178 | // Remove all kde connect menu entries since they won't work without a host | ||
179 | try { | ||||
141 | for (let device of kdeConnectDevices) { | 180 | for (let device of kdeConnectDevices) { | ||
142 | chrome.contextMenus.remove(kdeConnectMenuIdPrefix + device); | 181 | chrome.contextMenus.remove(kdeConnectMenuIdPrefix + device); | ||
143 | } | 182 | } | ||
144 | kdeConnectDevices = []; | 183 | } catch (e) { | ||
145 | 184 | console.warn("Failed to cleanup after port disconnect", e); | |||
146 | var reason = chrome.i18n.getMessage("general_error_unknown"); | | |||
147 | if (error && error.message) { | | |||
148 | reason = error.message; | | |||
149 | } | 185 | } | ||
150 | 186 | kdeConnectDevices = []; | |||
151 | var message = receivedMessageOnce ? chrome.i18n.getMessage("general_error_port_disconnect", reason) | | |||
152 | : chrome.i18n.getMessage("general_error_port_startupfail"); | | |||
153 | | ||||
154 | chrome.notifications.create(null, { | | |||
155 | type: "basic", | | |||
156 | title: chrome.i18n.getMessage("general_error_title"), | | |||
157 | message: message, | | |||
158 | iconUrl: "icons/sad-face-128.png" | | |||
159 | }); | | |||
160 | 187 | | |||
161 | if (receivedMessageOnce) { | 188 | if (receivedMessageOnce) { | ||
189 | portLastErrorMessage = error && error.message || "UNKNOWN"; | ||||
190 | portStatus = "DISCONNECTED"; | ||||
191 | | ||||
162 | console.log("Auto-restarting it"); | 192 | console.log("Auto-restarting it"); | ||
163 | connectHost(); | 193 | connectHost(); | ||
164 | } else { | 194 | } else { | ||
195 | portLastErrorMessage = ""; | ||||
196 | portStatus = "STARTUP_FAILED"; | ||||
197 | | ||||
165 | console.warn("Not auto-restarting host as we haven't received any message from it before. Check that it's working/installed correctly"); | 198 | console.warn("Not auto-restarting host as we haven't received any message from it before. Check that it's working/installed correctly"); | ||
166 | } | 199 | } | ||
200 | updateBrowserAction(); | ||||
167 | }); | 201 | }); | ||
168 | 202 | | |||
169 | sendEnvironment(); | 203 | sendEnvironment(); | ||
170 | sendSettings(); | 204 | sendSettings(); | ||
171 | sendDownloads(); | 205 | sendDownloads(); | ||
172 | } | 206 | } | ||
173 | 207 | | |||
174 | addRuntimeCallback("settings", "changed", function () { | 208 | addRuntimeCallback("settings", "changed", function () { | ||
175 | // we could also just reload our extension :) | 209 | // we could also just reload our extension :) | ||
176 | // but this also causes the settings dialog to quit | 210 | // but this also causes the settings dialog to quit | ||
177 | //chrome.runtime.reload(); | 211 | //chrome.runtime.reload(); | ||
178 | sendSettings(); | 212 | sendSettings(); | ||
179 | }); | 213 | }); | ||
180 | 214 | | |||
181 | addRuntimeCallback("settings", "openKRunnerSettings", function () { | 215 | addRuntimeCallback("settings", "openKRunnerSettings", function () { | ||
182 | sendPortMessage("settings", "openKRunnerSettings"); | 216 | sendPortMessage("settings", "openKRunnerSettings"); | ||
183 | }); | 217 | }); | ||
218 | | ||||
219 | addRuntimeCallback("browserAction", "getStatus", (message) => { | ||||
220 | let info = { | ||||
221 | portStatus, | ||||
222 | portLastErrorMessage | ||||
223 | }; | ||||
224 | | ||||
225 | return Promise.resolve(info); | ||||
226 | }); | ||||
227 | | ||||
228 | addRuntimeCallback("browserAction", "ready", () => { | ||||
229 | | ||||
230 | // HACK there's no way to tell whether the browser action popup got closed | ||||
231 | // None of onunload, onbeforeunload, onvisibilitychanged are fired. | ||||
232 | // Instead, we create a port once the browser action is ready and then | ||||
233 | // listen for the port being disconnected. | ||||
234 | | ||||
235 | let browserActionPort = chrome.runtime.connect({ | ||||
236 | name: "browserActionPort" | ||||
237 | }); | ||||
238 | browserActionPort.onDisconnect.addListener((port) => { | ||||
239 | if (port.name !== "browserActionPort") { | ||||
240 | return; | ||||
241 | } | ||||
242 | | ||||
243 | // disabling the browser action immediately when opening it | ||||
244 | // causes opening to fail on Firefox, so clear the error only when it's being closed. | ||||
245 | portLastErrorMessage = ""; | ||||
246 | updateBrowserAction(); | ||||
247 | }); | ||||
248 | }); |