Merge lp:~chrisccoulson/messagingmenu-extension/me-fixes into lp:messagingmenu-extension
- me-fixes
- Merge into trunk
Status: | Merged |
---|---|
Merged at revision: | 44 |
Proposed branch: | lp:~chrisccoulson/messagingmenu-extension/me-fixes |
Merge into: | lp:messagingmenu-extension |
Diff against target: |
1021 lines (+650/-140) 7 files modified
config_build.sh (+2/-2) defaults/preferences/defaults.js (+0/-4) install.rdf (+0/-1) locale/en-US/messagingmenu.properties (+1/-1) modules/LibDbusmenu.jsm (+15/-0) modules/LibIndicate.jsm (+14/-1) modules/MessagingMenu.jsm (+618/-131) |
To merge this branch: | bzr merge lp:~chrisccoulson/messagingmenu-extension/me-fixes |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Mike Conley | Approve | ||
Review via email: mp+65678@code.launchpad.net |
Commit message
Description of the change
Here are some changes I've been working on :-)
Mike Conley (mconley) wrote : | # |
- 58. By Chris Coulson
-
Rename mmie => indicatorEntry
Fix a typo
Delete some dead code
Chris Coulson (chrisccoulson) wrote : | # |
Thanks for reviewing. I've pushed an update with most of those comments addressed, and I removed 2 dead functions that I'd added as well.
>
> + cleanup: function MM_cleanup() {
> + // We're being uninstalled or disabled. If we created a launcher
> + // entry in the messaging menu, make sure we clean it up
> + let userLauncherEnt
> Ci.nsILocalFile);
> + userLauncherEnt
> + new LauncherEntryFi
> + "removeLauncher
> + },
>
> What if a launcher entry exists, but we didn't put it there?
>
Yeah, I guess this is a problem, but I think it is an edge case. In general, we don't offer any particular guarantees about application data stored in the profile (eg, we could save a pref so we know we created the file, but there's no guarantees the user hasn't modified it since we created it)
- 59. By Chris Coulson
-
Only clean up the local launcher entry if we created it (just based on a simple mtime check)
Chris Coulson (chrisccoulson) wrote : | # |
I've fixed the remaining issue as well now
Mike Conley (mconley) wrote : | # |
Hey Chris - looks good to me, thanks!
Preview Diff
1 | === modified file 'config_build.sh' |
2 | --- config_build.sh 2011-06-07 15:01:14 +0000 |
3 | +++ config_build.sh 2011-06-24 11:05:55 +0000 |
4 | @@ -3,10 +3,10 @@ |
5 | # Build config for the build script, build.sh. Look there for more info. |
6 | |
7 | APP_NAME=messagingmenu |
8 | -CHROME_PROVIDERS="content" |
9 | +CHROME_PROVIDERS="content locale" |
10 | CLEAN_UP=1 |
11 | ROOT_FILES= |
12 | -ROOT_DIRS="modules locale defaults" |
13 | +ROOT_DIRS="modules" |
14 | BEFORE_BUILD= |
15 | BEFORE_PACK= |
16 | AFTER_BUILD= |
17 | |
18 | === removed directory 'defaults' |
19 | === removed directory 'defaults/preferences' |
20 | === removed file 'defaults/preferences/defaults.js' |
21 | --- defaults/preferences/defaults.js 2011-03-29 17:55:47 +0000 |
22 | +++ defaults/preferences/defaults.js 1970-01-01 00:00:00 +0000 |
23 | @@ -1,4 +0,0 @@ |
24 | -pref("extensions.messagingmenu.showIndication", true); |
25 | -pref("extensions.messagingmenu.includeMail", true); |
26 | -pref("extensions.messagingmenu.includeNewsgroups", true); |
27 | -pref("extensions.messagingmenu.includeRSS", true); |
28 | |
29 | === modified file 'install.rdf' |
30 | --- install.rdf 2011-06-06 19:04:21 +0000 |
31 | +++ install.rdf 2011-06-24 11:05:55 +0000 |
32 | @@ -5,7 +5,6 @@ |
33 | <Description about="urn:mozilla:install-manifest"> |
34 | <em:id>messagingmenu@mozilla.com</em:id> |
35 | <em:version>0.6</em:version> |
36 | - <em:unpack>true</em:unpack> |
37 | <em:optionsURL>chrome://messagingmenu/content/options.xul</em:optionsURL> |
38 | |
39 | <em:targetApplication> |
40 | |
41 | === modified file 'locale/en-US/messagingmenu.properties' |
42 | --- locale/en-US/messagingmenu.properties 2011-02-26 19:33:18 +0000 |
43 | +++ locale/en-US/messagingmenu.properties 2011-06-24 11:05:55 +0000 |
44 | @@ -1,2 +1,2 @@ |
45 | -compose_new_message=Compose New Message |
46 | +composeNewMessage=Compose New Message |
47 | contacts=Contacts |
48 | |
49 | === modified file 'modules/LibDbusmenu.jsm' |
50 | --- modules/LibDbusmenu.jsm 2011-06-06 14:58:22 +0000 |
51 | +++ modules/LibDbusmenu.jsm 2011-06-24 11:05:55 +0000 |
52 | @@ -101,6 +101,20 @@ |
53 | return dbusmenu_menuitem_property_set; |
54 | }); |
55 | |
56 | +XPCOMUtils.defineLazyGetter(this, "dbusmenu_menuitem_property_set_bool", function() { |
57 | + var dbusmenu_menuitem_property_set_bool = |
58 | + libdbusmenu.declare("dbusmenu_menuitem_property_set_bool", |
59 | + ctypes.default_abi, |
60 | + LibGObject.gboolean, |
61 | + DbusmenuMenuitem.ptr, |
62 | + LibGObject.gchar.ptr, |
63 | + LibGObject.gboolean); |
64 | + if (!dbusmenu_menuitem_property_set_bool) |
65 | + throw "dbusmenu_menuitem_property_set is unavailable"; |
66 | + |
67 | + return dbusmenu_menuitem_property_set_bool; |
68 | +}); |
69 | + |
70 | XPCOMUtils.defineLazyGetter(this, "dbusmenu_menuitem_child_append", function() { |
71 | var dbusmenu_menuitem_child_append = |
72 | libdbusmenu.declare("dbusmenu_menuitem_child_append", |
73 | @@ -134,6 +148,7 @@ |
74 | ServerNew: dbusmenu_server_new, |
75 | MenuitemNew: dbusmenu_menuitem_new, |
76 | MenuitemPropertySet: dbusmenu_menuitem_property_set, |
77 | + MenuitemPropertySetBool: dbusmenu_menuitem_property_set_bool, |
78 | MenuitemChildAppend: dbusmenu_menuitem_child_append, |
79 | ServerSetRoot: dbusmenu_server_set_root |
80 | }; |
81 | |
82 | === modified file 'modules/LibIndicate.jsm' |
83 | --- modules/LibIndicate.jsm 2011-06-06 19:04:21 +0000 |
84 | +++ modules/LibIndicate.jsm 2011-06-24 11:05:55 +0000 |
85 | @@ -190,6 +190,18 @@ |
86 | return indicate_indicator_hide; |
87 | }); |
88 | |
89 | +XPCOMUtils.defineLazyGetter(this, "indicate_indicator_is_visible", function() { |
90 | + var indicate_indicator_is_visible = |
91 | + libindicate.declare("indicate_indicator_is_visible", |
92 | + ctypes.default_abi, |
93 | + LibGObject.gboolean, |
94 | + Indicator.ptr) |
95 | + if (!indicate_indicator_is_visible) |
96 | + throw "indicate_indicator_is_visible is unavailable"; |
97 | + |
98 | + return indicate_indicator_is_visible; |
99 | +}); |
100 | + |
101 | var LibIndicate = { |
102 | Indicator: Indicator, |
103 | IndicateServer: IndicateServer, |
104 | @@ -213,5 +225,6 @@ |
105 | IndicatorSetProperty: indicate_indicator_set_property, |
106 | IndicatorGetProperty: indicate_indicator_get_property, |
107 | IndicatorShow: indicate_indicator_show, |
108 | - IndicatorHide: indicate_indicator_hide |
109 | + IndicatorHide: indicate_indicator_hide, |
110 | + IndicatorIsVisible: indicate_indicator_is_visible |
111 | }; |
112 | |
113 | === modified file 'modules/MessagingMenu.jsm' |
114 | --- modules/MessagingMenu.jsm 2011-06-07 15:02:53 +0000 |
115 | +++ modules/MessagingMenu.jsm 2011-06-24 11:05:55 +0000 |
116 | @@ -21,6 +21,7 @@ |
117 | * |
118 | * Contributor(s): |
119 | * Mike Conley <mconley@mozillamessaging.com> |
120 | + * Chris Coulson <chris.coulson@canonical.com> |
121 | * |
122 | * Alternatively, the contents of this file may be used under the terms of |
123 | * either the GNU General Public License Version 2 or later (the "GPL"), or |
124 | @@ -45,7 +46,11 @@ |
125 | |
126 | Cu.import("resource://gre/modules/ctypes.jsm"); |
127 | Cu.import("resource://gre/modules/Services.jsm"); |
128 | +Cu.import("resource://gre/modules/NetUtil.jsm"); |
129 | +Cu.import("resource://gre/modules/FileUtils.jsm"); |
130 | +Cu.import("resource://gre/modules/AddonManager.jsm"); |
131 | Cu.import("resource:///modules/mailServices.js"); |
132 | +Cu.import("resource:///modules/iteratorUtils.jsm"); |
133 | Cu.import("resource://messagingmenu/LibGObject.jsm"); |
134 | Cu.import("resource://messagingmenu/LibDbusmenu.jsm"); |
135 | Cu.import("resource://messagingmenu/LibIndicate.jsm"); |
136 | @@ -53,17 +58,37 @@ |
137 | // I need the GdkWindow lib to do focus hacking |
138 | Cu.import("resource://messagingmenu/LibGdkWindow.jsm"); |
139 | |
140 | +["LOG", "WARN", "ERROR"].forEach(function(aName) { |
141 | + this.__defineGetter__(aName, function() { |
142 | + Components.utils.import("resource://gre/modules/AddonLogging.jsm"); |
143 | + |
144 | + LogManager.getLogger("messagingmenu", this); |
145 | + return this[aName]; |
146 | + }); |
147 | +}, this); |
148 | + |
149 | const FLDR_UNINTERESTING = Ci.nsMsgFolderFlags.Trash |
150 | - & Ci.nsMsgFolderFlags.Junk |
151 | - & Ci.nsMsgFolderFlags.SentMail |
152 | - & Ci.nsMsgFolderFlags.Drafts |
153 | - & Ci.nsMsgFolderFlags.Templates |
154 | - & Ci.nsMsgFolderFlags.Queue; |
155 | + | Ci.nsMsgFolderFlags.Junk |
156 | + | Ci.nsMsgFolderFlags.SentMail |
157 | + | Ci.nsMsgFolderFlags.Drafts |
158 | + | Ci.nsMsgFolderFlags.Templates |
159 | + | Ci.nsMsgFolderFlags.Queue; |
160 | |
161 | -const DATE_IN_SECONDS_KEY = "date-in-seconds"; |
162 | -const MESSAGE_URL_KEY = "message-url"; |
163 | -const SHELL_EXECUTABLES = ["thunderbird.sh", "thunderbird"]; |
164 | -const USER_SHARE_APPLICATIONS = "/usr/share/applications/" |
165 | +const FOLDER_URL_KEY = "url"; |
166 | +const SHELL_EXECUTABLES = ["thunderbird", "thunderbird-bin"]; |
167 | +const USER_SHARE_APPLICATIONS = "/usr/share/applications/"; |
168 | +const SYSTEM_LAUNCHER_ENTRIES = "/usr/share/indicators/messages/applications/"; |
169 | +const USER_LAUNCHER_ENTRIES = ".config/indicators/messages/applications/"; |
170 | +const USER_BLACKLIST_ENTRIES = ".config/indicators/messages/applications-blacklist/"; |
171 | +const MAX_INDICATORS = 6; |
172 | +const ADDON_ID = "messagingmenu@mozilla.com"; |
173 | +const PREF_ROOT = "extensions.messagingmenu."; |
174 | +const PREF_INCLUDE_NEWSGROUPS = "includeNewsgroups"; |
175 | +const PREF_INCLUDE_RSS = "includeRSS"; |
176 | +const PREF_ENABLED = "enabled"; |
177 | +const PREF_USER_LAUNCHER_PATH = "userLauncherPath"; |
178 | +const PREF_USER_LAUNCHER_MTIME = "userLauncherMTime"; |
179 | +const NS_PREFBRANCH_PREFCHANGE_TOPIC_ID = "nsPref:changed"; |
180 | |
181 | var open3PaneCallback; |
182 | var contactsCallback; |
183 | @@ -90,23 +115,37 @@ |
184 | } |
185 | |
186 | var openAndFocusAddressBook = function MM_openAndFocusAddressBook(aInstance, aTimestamp, aUserData) { |
187 | + LOG("Opening addressbook"); |
188 | injectTimestamp(aTimestamp); |
189 | MessagingMenu.tbProc.run(false, ['-addressbook'], 1); |
190 | } |
191 | |
192 | var openAndFocusComposer = function MM_openAndFocusComposer(aInstance, aTimestamp, aUserData) { |
193 | + LOG("Opening composer"); |
194 | injectTimestamp(aTimestamp); |
195 | MessagingMenu.tbProc.run(false, ['-compose'], 1); |
196 | } |
197 | |
198 | var onClickIndicator = function MM_onClickIndicator(aInstance, aTimestamp, aUserData) { |
199 | let indicator = LibIndicate.IndicatorPtrCast(aInstance); |
200 | + let folderURL = LibIndicate.IndicatorGetProperty(indicator, FOLDER_URL_KEY).readString(); |
201 | + LOG("Received click event on indicator for folder " + folderURL); |
202 | + |
203 | + let indicatorEntry = MessagingMenu.mIndicators[folderURL]; |
204 | + if (!indicatorEntry) { |
205 | + WARN("No indicator for folder " + folderURL); |
206 | + return; |
207 | + } |
208 | + |
209 | // Hide the indicator |
210 | - MessagingMenu.hideIndicator(indicator); |
211 | - let url = LibIndicate.IndicatorGetProperty(indicator, MESSAGE_URL_KEY); |
212 | - var msg = MessagingMenu.messenger.msgHdrFromURI(url.readString()); |
213 | - if(!msg) |
214 | + MessagingMenu.hideIndicator(indicatorEntry); |
215 | + |
216 | + var msg = MessagingMenu.messenger.msgHdrFromURI(indicatorEntry.messageURL); |
217 | + if(!msg) { |
218 | + WARN("Invalid message URI " + indicatorEntry.messageURL); |
219 | return; |
220 | + } |
221 | + |
222 | // Focus 3pane |
223 | openAndFocus3Pane(aInstance, aTimestamp, aUserData); |
224 | gWindow.document.getElementById("tabmail").switchToTab(0); |
225 | @@ -114,9 +153,237 @@ |
226 | gWindow.gFolderDisplay.selectMessage(msg); |
227 | } |
228 | |
229 | +function hasMultipleAccounts() { |
230 | + let count = 0; |
231 | + // We don't want to just call Count() on the account nsISupportsArray, as we |
232 | + // want to filter out accounts with "none" as the incoming server type |
233 | + // (eg, for Local Folders) |
234 | + for (let account in fixIterator(MailServices.accounts.accounts, Ci.nsIMsgAccount)) { |
235 | + if (account.incomingServer.type != "none") { |
236 | + count++ |
237 | + } |
238 | + } |
239 | + |
240 | + return count > 1; |
241 | +} |
242 | + |
243 | +// Helper class to wrap a nsIPrefBranch and allow the caller |
244 | +// to specify default values to be used where the pref doesn't exist |
245 | +function Prefs(aBranch) { |
246 | + this.branch = aBranch; |
247 | +} |
248 | + |
249 | +Prefs.prototype = { |
250 | + getBoolPref: function P_getBoolPref(aName, aDefaultValue) { |
251 | + try { |
252 | + return this.branch.getBoolPref(aName); |
253 | + } catch(e) { |
254 | + return aDefaultValue; |
255 | + } |
256 | + }, |
257 | + |
258 | + setCharPref: function P_setCharPref(aName, aValue) { |
259 | + this.branch.setCharPref(aName, aValue); |
260 | + }, |
261 | + |
262 | + getCharPref: function P_getCharPref(aName, aDefaultValue) { |
263 | + try { |
264 | + return this.branch.getCharPref(aName); |
265 | + } catch(e) { |
266 | + return aDefaultValue; |
267 | + } |
268 | + }, |
269 | + |
270 | + setIntPrefAsChar: function P_setIntPrefAsChar(aName, aValue) { |
271 | + this.setCharPref(aName, aValue.toString()); |
272 | + }, |
273 | + |
274 | + getIntPrefFromChar: function P_getIntPrefFromChar(aName, aDefaultValue) { |
275 | + return parseInt(this.getCharPref(aName, aDefaultValue.toString())); |
276 | + }, |
277 | + |
278 | + clearUserPref: function P_clearUserPref(aName) { |
279 | + this.branch.clearUserPref(aName); |
280 | + }, |
281 | + |
282 | + addObserver: function P_addObserver(aDomain, aObserver, aHoldWeak) { |
283 | + this.branch.QueryInterface(Ci.nsIPrefBranch2) |
284 | + .addObserver(aDomain, aObserver, aHoldWeak); |
285 | + }, |
286 | + |
287 | + removeObserver: function P_removeObserver(aDomain, aObserver) { |
288 | + this.branch.QueryInterface(Ci.nsIPrefBranch2) |
289 | + .removeObserver(aDomain, aObserver); |
290 | + } |
291 | +}; |
292 | + |
293 | +// Small helper class which takes a directory containing messaging menu |
294 | +// launcher entries and tells the listener whether one of them is ours |
295 | +function LauncherEntryFinder(aDir, aDesktopFile, aListener, aMethod) { |
296 | + LOG("Searching for launcher entry for " + aDesktopFile + " in " + aDir.path); |
297 | + if (!aDir.exists() || !aDir.isDirectory()) { |
298 | + WARN(aDir.path + " does not exist or is not a directory"); |
299 | + aListener[method](aDir, null); |
300 | + } |
301 | + |
302 | + this.listener = aListener; |
303 | + this.desktopFile = aDesktopFile; |
304 | + this.entries = aDir.directoryEntries; |
305 | + this.method = aMethod; |
306 | + this.dir = aDir; |
307 | + |
308 | + this.processNextEntry(); |
309 | +} |
310 | + |
311 | +LauncherEntryFinder.prototype = { |
312 | + processNextEntry: function MMEF_processNextEntry() { |
313 | + if (this.entries.hasMoreElements()) { |
314 | + var entry = this.entries.getNext().QueryInterface(Ci.nsIFile); |
315 | + if (!entry.isFile()) { |
316 | + this.processNextEntry(); |
317 | + } |
318 | + var self = this; |
319 | + NetUtil.asyncFetch(entry, function(inputStream, status) { |
320 | + let data = NetUtil.readInputStreamToString(inputStream, inputStream.available()); |
321 | + if (data.replace(/\n$/,"") == self.desktopFile) { |
322 | + LOG("Found launcher entry " + entry.path); |
323 | + self.listener[self.method](self.dir, entry); |
324 | + } else { |
325 | + self.processNextEntry(); |
326 | + } |
327 | + }); |
328 | + } else { |
329 | + LOG("No launcher entry found"); |
330 | + this.listener[this.method](this.dir, null); |
331 | + } |
332 | + } |
333 | +}; |
334 | + |
335 | +function MMIndicatorEntry (aFolder) { |
336 | + LOG("Creating indicator for folder " + aFolder.folderURL); |
337 | + this.folder = aFolder; |
338 | + this.indicator = LibIndicate.IndicatorNew(); |
339 | + if (hasMultipleAccounts()) { |
340 | + this.label = aFolder.prettiestName + |
341 | + " (" + aFolder.server.prettyName + ")"; |
342 | + } else { |
343 | + this.label = aFolder.prettiestName; |
344 | + } |
345 | + this.unreadCount = 0; |
346 | + this.dateInSeconds = 0; |
347 | + this.cancelAttention(); |
348 | + this.hide(); |
349 | + |
350 | + LibGObject.g_signal_connect(this.indicator, "user-display", |
351 | + clickIndicatorCallback, null); |
352 | + |
353 | + LibIndicate.IndicatorSetProperty(this.indicator, |
354 | + FOLDER_URL_KEY, |
355 | + aFolder.folderURL); |
356 | + |
357 | + Services.prefs.addObserver("mail.accountmanager.accounts", |
358 | + this, false); |
359 | +} |
360 | + |
361 | +MMIndicatorEntry.prototype = { |
362 | + get indicator() { |
363 | + if (this._indicator) { |
364 | + return this._indicator; |
365 | + } |
366 | + |
367 | + throw "No IndicateIndicator. Have we been destroyed?"; |
368 | + }, |
369 | + |
370 | + set indicator(aIndicator) { |
371 | + this._indicator = aIndicator; |
372 | + }, |
373 | + |
374 | + getAttention: function MMIE_getAttention() { |
375 | + LOG("Requesting attention for folder " + this.folder.folderURL); |
376 | + LibIndicate.IndicatorSetProperty(this.indicator, |
377 | + LibIndicate.INDICATOR_MESSAGES_PROP_ATTENTION, |
378 | + "true"); |
379 | + this._attention = true; |
380 | + }, |
381 | + |
382 | + cancelAttention: function MMIE_cancelAttention() { |
383 | + LOG("Cancelling attention for folder " + this.folder.folderURL); |
384 | + LibIndicate.IndicatorSetProperty(this.indicator, |
385 | + LibIndicate.INDICATOR_MESSAGES_PROP_ATTENTION, |
386 | + "false"); |
387 | + this._attention = false; |
388 | + }, |
389 | + |
390 | + hasAttention: function MMIE_hasAttention() { |
391 | + return this._attention; |
392 | + }, |
393 | + |
394 | + set label(aName) { |
395 | + LOG("Setting label for folder " + this.folder.folderURL + " to " + aName); |
396 | + LibIndicate.IndicatorSetProperty(this.indicator, |
397 | + LibIndicate.INDICATOR_MESSAGES_PROP_NAME, |
398 | + aName); |
399 | + }, |
400 | + |
401 | + set unreadCount(aCount) { |
402 | + LOG("Setting unread count for folder " + this.folder.folderURL + |
403 | + " to " + aCount.toString()); |
404 | + LibIndicate.IndicatorSetProperty(this.indicator, |
405 | + LibIndicate.INDICATOR_MESSAGES_PROP_COUNT, |
406 | + aCount.toString()); |
407 | + this._unreadCount = aCount; |
408 | + }, |
409 | + |
410 | + get unreadCount() { |
411 | + return this._unreadCount; |
412 | + }, |
413 | + |
414 | + show: function MMIE_show() { |
415 | + LOG("Showing indicator for folder " + this.folder.folderURL); |
416 | + LibIndicate.IndicatorShow(this.indicator); |
417 | + }, |
418 | + |
419 | + hide: function MMIE_hide() { |
420 | + LOG("Hiding indicator for folder " + this.folder.folderURL); |
421 | + LibIndicate.IndicatorHide(this.indicator); |
422 | + }, |
423 | + |
424 | + get visible() { |
425 | + return LibIndicate.IndicatorIsVisible(this.indicator) != 0; |
426 | + }, |
427 | + |
428 | + destroy: function MMIE_destroy() { |
429 | + LOG("Destroying indicator for folder " + this.folder.folderURL); |
430 | + LibGObject.g_object_unref(this.indicator); |
431 | + this.indicator = null; |
432 | + |
433 | + Services.prefs.removeObserver("mail.accountmanager.accounts", |
434 | + this); |
435 | + }, |
436 | + |
437 | + observe: function MMIE_observe(subject, topic, data) { |
438 | + // An account was added or removed. Note that this observer fires |
439 | + // before nsIMsgAccountManager is up-to-date, so we add the next |
440 | + // bit to the event loop |
441 | + LOG("Account settings updated. Updating label for folder " + |
442 | + this.folder.folderURL); |
443 | + var self = this; |
444 | + gWindow.setTimeout(function() { |
445 | + if (hasMultipleAccounts()) { |
446 | + self.label = self.folder.prettiestName + |
447 | + " (" + self.folder.server.prettyName + ")"; |
448 | + } else { |
449 | + self.label = self.folder.prettiestName; |
450 | + } |
451 | + }, 0); |
452 | + } |
453 | +}; |
454 | + |
455 | var MessagingMenu = { |
456 | initialized: false, |
457 | + enabled: false, |
458 | mIndicators: {}, |
459 | + visibleIndicators: 0, |
460 | |
461 | get messenger() { |
462 | if (this._messenger) |
463 | @@ -163,10 +430,32 @@ |
464 | get prefs() { |
465 | if (this._prefs) |
466 | return this._prefs; |
467 | - this._prefs = Services.prefs.getBranch("extensions.messagingmenu."); |
468 | + this._prefs = new Prefs(Services.prefs.getBranch(PREF_ROOT)); |
469 | return this._prefs; |
470 | }, |
471 | |
472 | + get shortcutVisibility() { |
473 | + if (this._shortcutVisibility == null) { |
474 | + this._shortcutVisibility = false; |
475 | + } |
476 | + |
477 | + return this._shortcutVisibility ? 1 : 0; |
478 | + }, |
479 | + |
480 | + set shortcutVisibility(aVis) { |
481 | + this._shortcutVisibility = aVis; |
482 | + |
483 | + if (this.contactsMi) { |
484 | + LibDbusmenu.MenuitemPropertySetBool(this.contactsMi, "visible", |
485 | + this.shortcutVisibility); |
486 | + } |
487 | + |
488 | + if (this.composeMi) { |
489 | + LibDbusmenu.MenuitemPropertySetBool(this.composeMi, "visible", |
490 | + this.shortcutVisibility); |
491 | + } |
492 | + }, |
493 | + |
494 | get indicateServer() { |
495 | if (this._indicateServer) |
496 | return this._indicateServer; |
497 | @@ -181,24 +470,35 @@ |
498 | LibGObject.g_signal_connect(indicateServer, "server-display", |
499 | open3PaneCallback, null); |
500 | |
501 | + let bundle = Services.strings.createBundle( |
502 | + "chrome://messagingmenu/locale/messagingmenu.properties"); |
503 | + |
504 | let server = LibDbusmenu.ServerNew("/messaging/commands"); |
505 | let root = LibDbusmenu.MenuitemNew(); |
506 | - let mi = LibDbusmenu.MenuitemNew(); |
507 | - LibDbusmenu.MenuitemPropertySet(mi, "label", "Contacts"); |
508 | + this.contactsMi = LibDbusmenu.MenuitemNew(); |
509 | + LibDbusmenu.MenuitemPropertySet(this.contactsMi, "label", |
510 | + bundle.GetStringFromName("contacts")); |
511 | + LibDbusmenu.MenuitemPropertySetBool(this.contactsMi, "visible", |
512 | + this.shortcutVisibility); |
513 | contactsCallback = LibGObject.GCallbackFunction(openAndFocusAddressBook); |
514 | |
515 | - LibGObject.g_signal_connect(mi, LibDbusmenu.MENUITEM_SIGNAL_ITEM_ACTIVATED, |
516 | + LibGObject.g_signal_connect(this.contactsMi, |
517 | + LibDbusmenu.MENUITEM_SIGNAL_ITEM_ACTIVATED, |
518 | contactsCallback, null); |
519 | - LibDbusmenu.MenuitemChildAppend(root, mi); |
520 | + LibDbusmenu.MenuitemChildAppend(root, this.contactsMi); |
521 | |
522 | - mi = LibDbusmenu.MenuitemNew(); |
523 | - LibDbusmenu.MenuitemPropertySet(mi, "label", "Compose a New Message"); |
524 | + this.composeMi = LibDbusmenu.MenuitemNew(); |
525 | + LibDbusmenu.MenuitemPropertySet(this.composeMi, "label", |
526 | + bundle.GetStringFromName("composeNewMessage")); |
527 | + LibDbusmenu.MenuitemPropertySetBool(this.composeMi, "visible", |
528 | + this.shortcutVisibility); |
529 | composerCallback = LibGObject.GCallbackFunction(openAndFocusComposer); |
530 | |
531 | - LibGObject.g_signal_connect(mi, LibDbusmenu.MENUITEM_SIGNAL_ITEM_ACTIVATED, |
532 | + LibGObject.g_signal_connect(this.composeMi, |
533 | + LibDbusmenu.MENUITEM_SIGNAL_ITEM_ACTIVATED, |
534 | composerCallback, null); |
535 | |
536 | - LibDbusmenu.MenuitemChildAppend(root, mi); |
537 | + LibDbusmenu.MenuitemChildAppend(root, this.composeMi); |
538 | LibDbusmenu.ServerSetRoot(server, root); |
539 | LibIndicate.ServerSetMenu(indicateServer, server); |
540 | LibIndicate.ServerShow(indicateServer); |
541 | @@ -209,36 +509,173 @@ |
542 | return this._indicateServer; |
543 | }, |
544 | |
545 | + sysLauncherFindResult: function MM_sysLauncherFindResult(aDir, aFound) { |
546 | + if (!aFound) { |
547 | + // There is no system-provided static launcher entry for us in the |
548 | + // messaging menu. Show the "Compose" and "Contacts" items, and then |
549 | + // add a static launcher entry if there isn't one already |
550 | + this.shortcutVisibility = true; |
551 | + |
552 | + let userLauncherEntriesDir = Services.dirsvc.get("Home", Ci.nsILocalFile); |
553 | + userLauncherEntriesDir.appendRelativePath(USER_LAUNCHER_ENTRIES); |
554 | + new LauncherEntryFinder(userLauncherEntriesDir, this.desktopFile, this, |
555 | + "createLauncherEntryIfNoneExists"); |
556 | + } |
557 | + }, |
558 | + |
559 | + createLauncherEntryIfNoneExists: function MM_createLauncherEntryIfNoneExists( |
560 | + aDir, aFound) { |
561 | + if (!aFound) { |
562 | + let entry = aDir; |
563 | + entry.append(Services.appinfo.name.toLowerCase()); |
564 | + let ostream = FileUtils.openSafeFileOutputStream(entry, |
565 | + FileUtils.MODE_WRONLY | |
566 | + FileUtils.MODE_CREATE | |
567 | + FileUtils.MODE_TRUNCATE); |
568 | + let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"] |
569 | + .createInstance(Ci.nsIScriptableUnicodeConverter); |
570 | + converter.charset = "UTF-8"; |
571 | + let istream = converter.convertToInputStream(this.desktopFile); |
572 | + var self = this; |
573 | + NetUtil.asyncCopy(istream, ostream, function() { |
574 | + self.prefs.setCharPref(PREF_USER_LAUNCHER_PATH, entry.path); |
575 | + self.prefs.setIntPrefAsChar(PREF_USER_LAUNCHER_MTIME, |
576 | + entry.lastModifiedTime); |
577 | + }); |
578 | + } |
579 | + }, |
580 | + |
581 | init: function MM_init(aWindow) { |
582 | if (this.initialized) |
583 | return; |
584 | |
585 | + LOG("Initializing MessagingMenu"); |
586 | + |
587 | gWindow = aWindow; |
588 | |
589 | + // Check if we have a static launcher entry in the messaging menu. If we |
590 | + // don't, then we should add one and also display "Contacts" and "Compose" |
591 | + // menu items. If there is one, then it was probably added by the Thunderbird |
592 | + // package. We don't need to create one or show the extra menu items in that case |
593 | + let sysLauncherEntriesDir = Cc["@mozilla.org/file/local;1"] |
594 | + .createInstance(Ci.nsILocalFile); |
595 | + sysLauncherEntriesDir.initWithPath(SYSTEM_LAUNCHER_ENTRIES); |
596 | + new LauncherEntryFinder(sysLauncherEntriesDir, this.desktopFile, this, |
597 | + "sysLauncherFindResult"); |
598 | + |
599 | + AddonManager.addAddonListener(this); |
600 | + this.prefs.addObserver("", this, false); |
601 | + Services.obs.addObserver(this, "xpcom-will-shutdown", false); |
602 | + |
603 | + if (this.prefs.getBoolPref(PREF_ENABLED, true)) { |
604 | + this.enable(); |
605 | + } else { |
606 | + this.disableAndHide(); |
607 | + } |
608 | + |
609 | + this.initialized = true; |
610 | + }, |
611 | + |
612 | + removeLauncherEntry: function MM_removeLauncherEntry(aDir, aFound) { |
613 | + if (aFound) { |
614 | + LOG("Removing launcher entry " + aFound.path); |
615 | + aFound.remove(false); |
616 | + } |
617 | + }, |
618 | + |
619 | + enable: function MM_enable() { |
620 | + if (this.enabled) { |
621 | + WARN("Trying to enable more than once"); |
622 | + return; |
623 | + } |
624 | + |
625 | + LOG("Enabling messaging indicator"); |
626 | + |
627 | if (!this.indicateServer) { |
628 | Cu.reportError("Could not construct the Messaging Menu server."); |
629 | return; |
630 | } |
631 | |
632 | + let userBlacklistDir = Services.dirsvc.get("Home", Ci.nsILocalFile); |
633 | + userBlacklistDir.appendRelativePath(USER_BLACKLIST_ENTRIES); |
634 | + new LauncherEntryFinder(userBlacklistDir, this.desktopFile, this, |
635 | + "removeLauncherEntry"); |
636 | + |
637 | let notificationFlags = Ci.nsIFolderListener.added |
638 | | Ci.nsIFolderListener.propertyFlagChanged; |
639 | MailServices.mailSession.AddFolderListener(this, notificationFlags); |
640 | |
641 | - Services.obs.addObserver(this, "xpcom-will-shutdown", false); |
642 | - this.initialized = true; |
643 | - }, |
644 | - |
645 | - shutdown: function MM_shutdown() { |
646 | + this.enabled = true; |
647 | + }, |
648 | + |
649 | + disableAndHide: function MM_disableAndHide() { |
650 | + LOG("Hiding messaging indicator"); |
651 | + let userBlacklistDir = Services.dirsvc.get("Home", Ci.nsILocalFile); |
652 | + userBlacklistDir.appendRelativePath(USER_BLACKLIST_ENTRIES); |
653 | + new LauncherEntryFinder(userBlacklistDir, this.desktopFile, this, |
654 | + "createLauncherEntryIfNoneExists"); |
655 | + |
656 | + this.disable(); |
657 | + }, |
658 | + |
659 | + cleanup: function MM_cleanup() { |
660 | + // We're being uninstalled or disabled. If we created a launcher |
661 | + // entry in the messaging menu, make sure we clean it up |
662 | + let userLauncherEntry = this.prefs.getCharPref(PREF_USER_LAUNCHER_PATH, |
663 | + null); |
664 | + let userLauncherEntryMTime = |
665 | + this.prefs.getIntPrefFromChar(PREF_USER_LAUNCHER_MTIME, 0); |
666 | + this.prefs.clearUserPref(PREF_USER_LAUNCHER_PATH); |
667 | + this.prefs.clearUserPref(PREF_USER_LAUNCHER_MTIME); |
668 | + if (userLauncherEntry) { |
669 | + let userLauncherEntryFile = Cc["@mozilla.org/file/local;1"] |
670 | + .createInstance(Ci.nsILocalFile); |
671 | + userLauncherEntryFile.initWithPath(userLauncherEntry); |
672 | + if (userLauncherEntryFile.exists() && |
673 | + userLauncherEntryFile.isFile() && |
674 | + userLauncherEntryFile.lastModifiedTime == userLauncherEntryMTime) { |
675 | + LOG("Removing launcher entry at " + userLauncherEntry); |
676 | + userLauncherEntryFile.remove(false); |
677 | + } |
678 | + } |
679 | + }, |
680 | + |
681 | + disable: function MM_disable() { |
682 | + if (!this.enabled) |
683 | + return; |
684 | + |
685 | + LOG("Disabling messaging indicator"); |
686 | + |
687 | + MailServices.mailSession.RemoveFolderListener(this); |
688 | + |
689 | // Remove references for any leftover indicators |
690 | - for each (key in this.mIndicators) |
691 | - LibGObject.g_object_unref(this.mIndicators[key]); |
692 | - |
693 | + for (let key in this.mIndicators) |
694 | + this.mIndicators[key].destroy(); |
695 | this.mIndicators = {}; |
696 | + this.visibleIndicators = 0; |
697 | |
698 | if (this._indicateServer) |
699 | LibGObject.g_object_unref(this._indicateServer); |
700 | - |
701 | this._indicateServer = null; |
702 | + |
703 | + this.enabled = false; |
704 | + }, |
705 | + |
706 | + shutdown: function MM_shutdown() { |
707 | + if (!this.initialized) { |
708 | + WARN("Calling shutdown before we are initialized"); |
709 | + return; |
710 | + } |
711 | + |
712 | + LOG("Shutting down"); |
713 | + |
714 | + this.disable(); |
715 | + |
716 | + AddonManager.removeAddonListener(this); |
717 | + Services.prefs.removeObserver(this, "xpcom-will-shutdown"); |
718 | + this.prefs.removeObserver("", this); |
719 | + |
720 | + this.initialized = false; |
721 | }, |
722 | |
723 | /* Given a particular message header, determines whether or not |
724 | @@ -247,111 +684,95 @@ |
725 | * @param header An nsIMsgDBHdr for a message. |
726 | */ |
727 | worthIndication: function MM_worthIndication(header) { |
728 | + var folder = header.folder; |
729 | + LOG("Checking if message " + header.folder.getUriForMsg(header) + |
730 | + " in " + folder.folderURL + " is worth indicating"); |
731 | + |
732 | // Filter out the new messages that don't count...like junk. |
733 | var junkScore = header.getStringProperty("junkscore"); |
734 | - |
735 | if ((junkScore != "") && (junkScore != "0")) { |
736 | // We're junk. Not worth indicating. |
737 | + LOG("Rejecting message with junkscore = " + junkScore); |
738 | return false; |
739 | } |
740 | |
741 | - var folder = header.folder; |
742 | - |
743 | - if (this.prefs.getBoolPref("includeMail")) { |
744 | - if (folder.flags & Ci.nsMsgFolderFlags.Inbox) { |
745 | - return true; |
746 | - } |
747 | - } |
748 | - |
749 | if (folder.flags & FLDR_UNINTERESTING) { |
750 | - return false; |
751 | - } |
752 | - |
753 | + LOG("Rejecting message with flags = " + folder.flags.toString()); |
754 | + return false; |
755 | + } |
756 | + |
757 | + if (header.isRead) { |
758 | + // The item has already been read |
759 | + LOG("Rejecting message which has already been read"); |
760 | + return false; |
761 | + } |
762 | + |
763 | + if (folder.flags & Ci.nsMsgFolderFlags.Mail) { |
764 | + LOG("Accepting mail message"); |
765 | + return true; |
766 | + } |
767 | |
768 | // Are we checking news groups? |
769 | - if (this.prefs.getBoolPref("includeNewsgroups")) { |
770 | + if (this.prefs.getBoolPref(PREF_INCLUDE_NEWSGROUPS, true)) { |
771 | if (folder.flags & Ci.nsMsgFolderFlags.Newsgroup) { |
772 | + LOG("Accepting newsgroup message"); |
773 | return true; |
774 | } |
775 | } |
776 | |
777 | - if (this.prefs.getBoolPref("includeRSS")) { |
778 | + if (this.prefs.getBoolPref(PREF_INCLUDE_RSS, true)) { |
779 | if (folder.server.type == "rss") { |
780 | + LOG("Accepting message from RSS feed"); |
781 | return true; |
782 | } |
783 | } |
784 | |
785 | + LOG("Rejecting message with flags = " + folder.flags.toString()); |
786 | return false; |
787 | }, |
788 | |
789 | - /* Sends a request to Indicate to uMessagingMenuService. |
790 | + /* Given a message header, displays an indicator for it's folder |
791 | + * and requests attention |
792 | * |
793 | * @param aItemHeader A nsIMsgDBHdr for the message that we're |
794 | * trying to show in the Messaging Menu. |
795 | */ |
796 | - sendIndication: function MM_sendIndication(aItemHeader) { |
797 | - var itemFolder = aItemHeader.folder; |
798 | - // TODO: We want to only display the root folder's name if it disambiguates common |
799 | - // subfolder names. |
800 | - itemFolder.updateSummaryTotals(true); |
801 | - let label = itemFolder.prettiestName + " (" |
802 | - + itemFolder.rootFolder.prettiestName + ")"; |
803 | - let count = itemFolder.getNumUnread(true); |
804 | - let folderUrl = itemFolder.folderURL; |
805 | - let messageUrl = itemFolder.getUriForMsg(aItemHeader); |
806 | - |
807 | - this.doIndication(folderUrl, label, messageUrl, count, |
808 | - aItemHeader.dateInSeconds); |
809 | - }, |
810 | - |
811 | - doIndication: function MM_doIndication(aFolderURL, aFolderName, |
812 | - aMessageURL, count, |
813 | - aDateInSeconds) { |
814 | - |
815 | - var indicator; |
816 | - if (!this.mIndicators[aFolderURL]) { |
817 | - indicator = LibIndicate.IndicatorNew(); |
818 | - LibIndicate.IndicatorSetProperty(indicator, |
819 | - LibIndicate.INDICATOR_MESSAGES_PROP_NAME, aFolderName); |
820 | - LibIndicate.IndicatorSetProperty(indicator, DATE_IN_SECONDS_KEY, "0") |
821 | - LibIndicate.IndicatorSetProperty(indicator, |
822 | - LibIndicate.INDICATOR_MESSAGES_PROP_ATTENTION, "false"); |
823 | - |
824 | - LibGObject.g_signal_connect(indicator, "user-display", |
825 | - clickIndicatorCallback, null); |
826 | - this.mIndicators[aFolderURL] = indicator; |
827 | - } else { |
828 | - indicator = this.mIndicators[aFolderURL]; |
829 | - } |
830 | - |
831 | - let curDateInSeconds = LibIndicate.IndicatorGetProperty(indicator, DATE_IN_SECONDS_KEY); |
832 | - curDateInSeconds = curDateInSeconds.readString(); |
833 | - let gettingAttention = LibIndicate |
834 | - .IndicatorGetProperty(indicator, |
835 | - LibIndicate.INDICATOR_MESSAGES_PROP_ATTENTION); |
836 | - gettingAttention = gettingAttention.readString(); |
837 | - |
838 | - if (gettingAttention != "true" || (curDateInSeconds > aDateInSeconds)) { |
839 | - LibIndicate.IndicatorSetProperty(indicator, |
840 | - MESSAGE_URL_KEY, |
841 | - aMessageURL); |
842 | - LibIndicate.IndicatorSetProperty(indicator, |
843 | - DATE_IN_SECONDS_KEY, |
844 | - aDateInSeconds.toString()); |
845 | - } |
846 | - |
847 | - LibIndicate.IndicatorSetProperty(indicator, |
848 | - LibIndicate.INDICATOR_MESSAGES_PROP_COUNT, count.toString()); |
849 | - |
850 | - LibIndicate.IndicatorSetProperty(indicator, |
851 | - LibIndicate.INDICATOR_MESSAGES_PROP_ATTENTION, "true"); |
852 | - |
853 | - LibIndicate.IndicatorShow(indicator); |
854 | - }, |
855 | - |
856 | - stopIndication: function MM_stopIndication(aItemHeader) { |
857 | + doIndication: function MM_doIndication(aItemHeader) { |
858 | let itemFolder = aItemHeader.folder; |
859 | let folderURL = itemFolder.folderURL; |
860 | + LOG("Doing indication for folder " + folderURL); |
861 | + if (!this.mIndicators[folderURL]) { |
862 | + // Create an indicator for this folder if one doesn't already exist |
863 | + this.mIndicators[folderURL] = new MMIndicatorEntry(itemFolder); |
864 | + } |
865 | + |
866 | + let indicator = this.mIndicators[folderURL]; |
867 | + indicator.unreadCount += 1; |
868 | + |
869 | + LOG("Current indicator dateInSeconds = " + indicator.dateInSeconds.toString()); |
870 | + LOG("Message item dateInSeconds = " + aItemHeader.dateInSeconds.toString()); |
871 | + if (indicator.hasAttention()) { |
872 | + LOG("Indicator for folder already has attention"); |
873 | + } |
874 | + |
875 | + if (!indicator.hasAttention() || (indicator.dateInSeconds > aItemHeader.dateInSeconds)) { |
876 | + indicator.messageURL = itemFolder.getUriForMsg(aItemHeader); |
877 | + indicator.dateInSeconds = aItemHeader.dateInSeconds; |
878 | + } |
879 | + |
880 | + indicator.getAttention(); |
881 | + |
882 | + // Don't show more than MAX_INDICATORS indicators |
883 | + if (!indicator.visible && (this.visibleIndicators < MAX_INDICATORS)) { |
884 | + this.visibleIndicators++; |
885 | + indicator.show(); |
886 | + LOG("There are now " + this.visibleIndicators.toString() + " visible indicators"); |
887 | + } |
888 | + }, |
889 | + |
890 | + stopIndication: function MM_stopIndication(aItemHeader) { |
891 | + let folderURL = aItemHeader.folder.folderURL; |
892 | + LOG("Stopping indication for folder " + folderURL); |
893 | |
894 | if (!this.mIndicators[folderURL]) |
895 | return; |
896 | @@ -359,10 +780,41 @@ |
897 | this.hideIndicator(this.mIndicators[folderURL]); |
898 | }, |
899 | |
900 | - hideIndicator: function MM_hideIndicator(indicator) { |
901 | - LibIndicate.IndicatorHide(indicator); |
902 | - LibIndicate.IndicatorSetProperty(indicator, |
903 | - LibIndicate.INDICATOR_MESSAGES_PROP_ATTENTION, "false"); |
904 | + hideIndicator: function MM_hideIndicator(aIndicator) { |
905 | + if (aIndicator.visible) { |
906 | + aIndicator.hide(); |
907 | + if (this.visibleIndicators > 0) { |
908 | + this.visibleIndicators--; |
909 | + LOG("There are now " + this.visibleIndicators.toString() + " visible indicators"); |
910 | + } else { |
911 | + ERROR("Invalid MessagingMenu.visibleIndicators count: " |
912 | + + this.visibleIndicators.toString()); |
913 | + } |
914 | + } |
915 | + aIndicator.cancelAttention(); |
916 | + aIndicator.unreadCount = 0; |
917 | + |
918 | + if (this.visibleIndicators >= MAX_INDICATORS) { |
919 | + return; |
920 | + } |
921 | + |
922 | + // Now see if there are any pending indicators to be shown |
923 | + // Show the one which has been waiting the longest |
924 | + let pendingIndicator = null; |
925 | + for (let url in this.mIndicators) { |
926 | + let indicator = this.mIndicators[url]; |
927 | + if (indicator.hasAttention() && !indicator.visible && |
928 | + (!pendingIndicator || |
929 | + (indicator.dateInSeconds < pendingIndicator.dateInSeconds))) { |
930 | + pendingIndicator = indicator; |
931 | + } |
932 | + } |
933 | + |
934 | + if (pendingIndicator) { |
935 | + pendingIndicator.show(); |
936 | + this.visibleIndicators++; |
937 | + LOG("There are now " + this.visibleIndicators.toString() + " visible indicators"); |
938 | + } |
939 | }, |
940 | |
941 | /* Observes when items are added to folders, and when |
942 | @@ -370,25 +822,60 @@ |
943 | * sent by uMessagingMenuService for opening messages based |
944 | * on an Indicator that was clicked. |
945 | */ |
946 | - OnItemAdded: function MM_OnItemAdded(parentItem, item) { |
947 | - let header = item.QueryInterface(Ci.nsIMsgDBHdr); |
948 | - if(this.worthIndication(header)) { |
949 | - this.sendIndication(header); |
950 | - } |
951 | - }, |
952 | - |
953 | - OnItemPropertyFlagChanged: function MM_OnItemPropertyFlagChanged(item, property, oldFlag, newFlag) { |
954 | - if((oldFlag & Ci.nsMsgMessageFlags.New) |
955 | - && !(newFlag & Ci.nsMsgMessageFlags.New)) { |
956 | - let header = item.QueryInterface(Ci.nsIMsgDBHdr); |
957 | - this.stopIndication(header); |
958 | - } |
959 | - }, |
960 | - |
961 | - observe: function(aSubject, aTopic, aData) { |
962 | - if (aTopic == "xpcom-will-shutdown") { |
963 | - this.shutdown(); |
964 | - } |
965 | - } |
966 | + OnItemAdded: function MM_OnItemAdded(parentItem, item) { |
967 | + let header = item.QueryInterface(Ci.nsIMsgDBHdr); |
968 | + if(this.worthIndication(header)) { |
969 | + this.doIndication(header); |
970 | + } |
971 | + }, |
972 | + |
973 | + OnItemPropertyFlagChanged: function MM_OnItemPropertyFlagChanged(item, property, oldFlag, newFlag) { |
974 | + if((oldFlag & Ci.nsMsgMessageFlags.New) |
975 | + && !(newFlag & Ci.nsMsgMessageFlags.New)) { |
976 | + let header = item.QueryInterface(Ci.nsIMsgDBHdr); |
977 | + this.stopIndication(header); |
978 | + } |
979 | + }, |
980 | + |
981 | + observe: function(aSubject, aTopic, aData) { |
982 | + if (aTopic == "xpcom-will-shutdown") { |
983 | + LOG("Got shutdown notification"); |
984 | + this.shutdown(); |
985 | + } else if (aTopic == NS_PREFBRANCH_PREFCHANGE_TOPIC_ID) { |
986 | + LOG("Got prefchange notification for " + aData); |
987 | + if (aData == PREF_ENABLED) { |
988 | + let prefs = new Prefs(aSubject.QueryInterface(Ci.nsIPrefBranch)); |
989 | + let enabled = prefs.getBoolPref(aData, true); |
990 | + if (enabled) { |
991 | + this.enable(); |
992 | + } else { |
993 | + this.disableAndHide(); |
994 | + } |
995 | + } |
996 | + } else { |
997 | + WARN("Observer notification not intended for us: " + aTopic); |
998 | + } |
999 | + }, |
1000 | + |
1001 | + onUninstalling: function(aAddon, aNeedsRestart) { |
1002 | + if (aAddon.id == ADDON_ID) { |
1003 | + LOG("Addon is being uninstalled"); |
1004 | + this.cleanup(); |
1005 | + } |
1006 | + }, |
1007 | + |
1008 | + onDisabling: function(aAddon, aNeedsRestart) { |
1009 | + if (aAddon.id == ADDON_ID) { |
1010 | + LOG("Addon is being disabled"); |
1011 | + this.disableAndHide(); |
1012 | + } |
1013 | + }, |
1014 | + |
1015 | + onEnabling: function(aAddon, aNeedsRestart) { |
1016 | + if (aAddon.id == ADDON_ID) { |
1017 | + LOG("Addon is being enabled"); |
1018 | + this.enable(); |
1019 | + } |
1020 | + } |
1021 | } |
1022 |
+ let folderURL = LibIndicate. IndicatorGetPro perty(indicator , URL_KEY) .readString( ); mIndicators[ folderURL] ;
FOLDER_
+ LOG("Received click event on indicator for folder " + folderURL);
+
+ let mmie = MessagingMenu.
+ if (!mmie) {
+ WARN("No indicator for folder " + folderURL);
+ return;
I assume that "mmie" stands for something like "Messaging Menu Indicator
Entry". Still, I think "indicatorEntry" would suffice, and is clearer.
+// Small helper class which takes a directory containting messaging menu nder(aDir, aDesktopFile, aListener, aMethod) {
+// launcher entries and tells the listener whether one of them is ours
+function LauncherEntryFi
+ LOG("Searching for launcher entry for " + aDesktopFile + " in " +
aDir.path);
Typo: "containting" -> "containing"
+ cleanup: function MM_cleanup() { ryDir = Services. dirsvc. get("Home" , ryDir.appendRel ativePath( USER_LAUNCHER_ ENTRIES) ; nder(userLaunch erEntryDir, this.desktopFile, this, Entry") ;
+ // We're being uninstalled or disabled. If we created a launcher
+ // entry in the messaging menu, make sure we clean it up
+ let userLauncherEnt
Ci.nsILocalFile);
+ userLauncherEnt
+ new LauncherEntryFi
+ "removeLauncher
+ },
What if a launcher entry exists, but we didn't put it there?
+ buildIndicators ();
+ //this.
+
Please remove.
+ // Now see if there are any pending indicators to be shown
+ // Show the one which has been waiting the longest
+ let pendingIndicator = null;
+ for (let url in this.mIndicators) {
Oh, I quite like this idea. Good work. :)
I like it! Once the above is addressed, I think this is fine to merge.