• Skip to main content
  • Select language
  • Skip to search
MDN Web Docs
  • Technologies
    • HTML
    • CSS
    • JavaScript
    • Graphics
    • HTTP
    • APIs / DOM
    • WebExtensions
    • MathML
  • References & Guides
    • Learn web development
    • Tutorials
    • References
    • Developer Guides
    • Accessibility
    • Game development
    • ...more docs
Add-ons
  1. MDN
  2. Mozilla
  3. Add-ons
  4. Thunderbird extensions
  5. Thunderbird HowTos
  6. Activity Manager examples

Activity Manager examples

In This Article
  1. Showing a user-defined activity in the Activity Manager window
  2. Showing a user-defined activity with cancel capability (JavaScript)
  3. Showing a user-defined activity with undo capability (C++)
  4. Adding an activity with a custom context type
  5. Adding a fully customized activity

This content covers features introduced in Thunderbird 3

The Activity Manager is a simple component that understands how to display a combination of user activity and history. See the Activity Manager page for a general description of the component. See the Activity Manager interfaces page for an overview of the related interfaces.

If the default implementation of nsIActivityProcess, nsIActivityWarning and nsIActivityEvent are not sufficient for the activity initiator, activity developers can provide their own components to extend the capabilities. Default implementations can be found in nsActivity.js file.

If activity developers would like to extend the default UI representation of the activity types, they can provide their own XBL elements for their own activity types. All custom activity XBL elements should inherit from "activity-base" binding. For XBL samples please see activity.xml and activityBinding.css files.

Showing a user-defined activity in the Activity Manager window

The following sample will show a process and an event for junk processing in the Activity Manager window.

// Step 1: Adding a Process into the activity manager
const nsIAP = Components.interfaces.nsIActivityProcess;
const nsIAE = Components.interfaces.nsIActivityEvent;
const nsIAM = Components.interfaces.nsIActivityManager;
let gActivityManager = Components.classes["@mozilla.org/activity-manager;1"].getService(nsIAM);
let process = Components.classes["@mozilla.org/activity-process;1"].createInstance(nsIAP);
// Assuming folder is an instance of nsIMsgFolder interface
// Localization is omitted, initiator is not provided
process.init("Processing folder: " + folder.prettiestName, 
             null);
// Note that we don't define a custom icon, default process icon
// will be used
process.contextType = "account";     // group this activity by account 
process.contextObj = folder.server;  // account in question
gActivityManager.addActivity(process);
// Step 2: Showing some progress
let percent = 50;
process.setProgress(percent, "Junk processing 25 of 50 messages", 25, 50);
// Step 3: Removing the process and adding an Event using Process' attributes
process.state = Components.interfaces.nsIActivityProcess.STATE_COMPLETED;
gActivityManager.removeActivity(process.id);
let event = Components.classes["@mozilla.org/activity-event;1"].createInstance(nsIAE);
// Localization is omitted, initiator is omitted
event.init(folder.prettiestName + " is processed",
           null, 
           "No junk found", 
           process.startTime,  // start time 
           Date.now());        // completion time
event.contextType = process.contextType; // optional
event.contextObj = process.contextObj;   // optional
gActivityManager.addActivity(event);

Showing a user-defined activity with cancel capability (JavaScript)

This sample improves the previous one by providing an nsIActivityCancelHandler to allow the user to cancel the process.

// Step 1: Create a nsIActivityCancelHandler implementation
function CancelJunkProcess() 
{
 // user stuff here..
}
CancelJunkProcess.prototype = {
 cancel: function(aActivity) {
   let initiator = aActivity.initiator;
   if (initiator) {
     let folder = aActivity.getSubjects({})[0];
     ....
     // assuming that the initiator has some way to cancel 
     // the junk processing for given folder
     if (initiator.cancelFolderOp(folder)) {
       aActivity.state = Components.interfaces.nsIActivityProcess.STATE_CANCELED;
       gActivityManager.removeActivity(aActivity.id);
       return Cr.NS_SUCCESS;
     }
   }
  return Cr.NS_FAILURE;
 }
}
// Step 2: Modify the previous sample to add initiator, subject
// and associate a nsIActivityCancelHandler component
...
// assuming that gJunkProcessor is the entity initiating the junk processing 
// activity, and it has cancelFolderOp method that cancels the operations on folders
process.init("Processing folder: " + folder.prettiestName, 
             gJunkProcessor);
// folder is being filtered/processed 
process.addSubject(folder);
process.cancelHandler = new CancelJunkProcess();
...

Since nsIActivityCancelHandler is provided with the activity, the UI will show a cancel button beside the activity. You can extrapolate this sample to nsIActivityRetryHandler and nsIActivityPauseHandler as well.

Showing a user-defined activity with undo capability (C++)

.....
#include "nsIActivity.h"
#include "nsIActivityManager.h"
.....
//////////////////////////////////////////////////////////////////////////////
//// Undo handler implementation
class myCopyEventUndo : public nsIActivityUndoHandler
{  
 public:
  NS_DECL_ISUPPORTS
  NS_DECL_NSIACTIVITYUNDOHANDLER
  myCopyEventUndo() {}
 private:
  ~myCopyEventUndo() {}
};
NS_IMPL_ISUPPORTS1(myCopyEventUndo, nsIActivityUndoHandler)
NS_IMETHODIMP myCopyEventUndo::Undo(nsIActivityEvent *event, nsresult *result)
{
  nsresult rv;
  // get the subjects of this copy event
  PRUint32 length;
  nsIVariant **subjectList;
  rv = event->GetSubjects(&length, &subjectList);
  if(NS_FAILED(rv)) 
    return rv;
  // first subject in the list is the source folder in this particular case
  nsCOMPtr<nsIMsgFolder> folder = do_QueryInterface(subjectList[0]);
  // get the initiator
  nsIVariant *initiator;
  event->GetInitiator(&initiator);
  if (initiator)
  {
    nsISupports* ptr;
    rv = object->GetAsISupports(&ptr);
    if(NS_FAILED(rv)) 
      return rv;
    nsCOMPtr<nsIMsgCopyService> copyService = do_QueryInterface(ptr);
    if (copyService)
      copyService->Undo(folder); 
  }
  return (*result = NS_OK);
 }
/////////////////////////////////////////////////////////////////////////////
//// Creating an undoable copy event
nsCOMPtr<nsIActivityUndoHandler> undoHandler = new myCopyEventUndo();
nsCOMPtr<nsIActivityEvent> copyEvent(do_CreateInstance("@mozilla.org/activity-event;1"));
// The initiator of this particular event is CopyService. We want to
// associate it with the event since we are going to use it in the
// undo handler.
// Same for the source folder, it is required for undo operation, but
// since it is the subject of this activity (event), it goes into the
// subject list.
// wrap copyservice in a nsvariant component
nsCOMPtr<nsIWritableVariant> initiator = do_CreateInstance(NS_VARIANT_CONTRACTID);
initiator->SetAsISupports(reinterpret_cast<nsISupports*>(copyService));
// subject of the delete operation is the imap folder
// wrap it in a nsvariant component
nsCOMPtr<nsIWritableVariant> srcFolder = do_CreateInstance(NS_VARIANT_CONTRACTID);
srcFolder->SetAsISupports(reinterpret_cast<nsISupports*>(imapFolder));
copyEvent->AddSubject(srcFolder);
copyEvent->Init(NS_LITERAL_STRING("Message copy event"),
                initiator,
                NS_LITERAL_STRING("Completed successfully"), 
                PR_Now() / PR_USEC_PER_MSEC,   // start time
                PR_Now() / PR_USEC_PER_MSEC);  // completion time
// Do not forget to increase the ref counter if needed
copyEvent->SetUndoHandler(undoHandler);  
////////////////////////////////////////////////////////////////
//// Adding the event into Activity Manager
nsCOMPtr<nsIActivityManager> activityMgr(do_GetService("@mozilla.org/activity-manager;1"));
PRUint32 id;
activityMgr->AddActivity(copyEvent, &id);

Adding an activity with a custom context type

This sample shows how to provide a custom context type for junk processing. As a result, all junk processing activities (assuming that we process accounts in parallel) dealing with messages coming from the same sender will be grouped together. (This example seems to be outdated and not working, see bug 557467 comment 1.)

//optional: define some convenience constants
const nsActProcess = Components.Constructor("@mozilla.org/activity-process;1",
                                           "nsIActivityProcess", "init");
const nsActEvent = Components.Constructor("@mozilla.org/activity-event;1",
                                         "nsIActivityEvent", "init");
 // Step 1: Implement nsIActivityContextDisplayHelper to show a 
 //         customized   display text for our context type
function SenderContextDisplayHelper() 
{
 // user stuff here..
}
SenderContextDisplayHelper.prototype = {
 getContextDisplayText: function(contextType, contextObj) {
   // in this particular example we know that contextType is "Sender"
   // since we also pass the contextType along with the contextObject 
   //  in some cases, one helper can be registered for a group of context types
   // we know that the context object is the author of the message
   // Localization is omitted
   return "Messages coming from " + contextObj.surname + ", " + contextObj.firstname;
 }
}
// Step 2: Register the helper for this context type
gActivityManager.registerContextDisplayHelper("Sender", 
                                             new SenderContextDisplayHelper());
// Step 3: Create the process
...
let process = new nsActProcess("Processing folder: " + folder.prettiestName,
                               gJunkProcessor);
process.cancelHandler = new CancelJunkProcess();
// folder is being filtered/processed 
process.addSubject(folder);
process.contextType = "Sender";
// assuming msg is an instance of nsIMsgHdr
process.contextObj = msg.author;
...

Adding a fully customized activity

In complex scenarios, extensions might implement their own version of the nsIActivityProcess, nsIActivityWarning and nsIActivityEvent interfaces. In such cases, nsActivity.js can be used as a model.

Document Tags and Contributors

 Contributors to this page: wbamberg, aceman-bugzilla, farqad, jenzed, Standard8
 Last updated by: wbamberg, Jan 15, 2016, 11:07:26 AM
See also
  1. WebExtensions
  2. Getting started
    1. Prerequisites
    2. Anatomy of a WebExtension
    3. Packaging and Installation
    4. Walkthrough
    5. Examples
  3. Guides
    1. Content scripts
    2. Porting from Google Chrome
    3. Match patterns
    4. Debugging
    5. Chrome incompatibilities
  4. JavaScript APIs
    1. alarms
    2. bookmarks
    3. browserAction
    4. contextMenus
    5. cookies
    6. events
    7. extension
    8. extensionTypes
    9. i18n
    10. idle
    11. notifications
    12. pageAction
    13. runtime
    14. storage
    15. tabs
    16. webNavigation
    17. webRequest
    18. windows
  5. Manifest keys
    1. applications
    2. background
    3. browser_action
    4. content_scripts
    5. default_locale
    6. description
    7. icons
    8. manifest_version
    9. name
    10. page action
    11. permissions
    12. version
    13. web_accessible_resources
  6. Add-on SDK
  7. Getting started
    1. Installation
    2. Getting started
    3. Troubleshooting
  8. High-Level APIs
    1. addon-page
    2. base64
    3. clipboard
    4. context-menu
    5. hotkeys
    6. indexed-db
    7. l10n
    8. notifications
    9. page-mod
    10. page-worker
    11. panel
    12. passwords
    13. private-browsing
    14. querystring
    15. request
    16. selection
    17. self
    18. simple-prefs
    19. simple-storage
    20. system
    21. tabs
    22. timers
    23. ui
    24. url
    25. widget
    26. windows
  9. Low-Level APIs
    1. /loader
    2. chrome
    3. console/plain-text
    4. console/traceback
    5. content/content
    6. content/loader
    7. content/mod
    8. content/symbiont
    9. content/worker
    10. core/heritage
    11. core/namespace
    12. core/promise
    13. dev/panel
    14. event/core
    15. event/target
    16. frame/hidden-frame
    17. frame/utils
    18. fs/path
    19. io/byte-streams
    20. io/file
    21. io/text-streams
    22. lang/functional
    23. lang/type
    24. loader/cuddlefish
    25. loader/sandbox
    26. net/url
    27. net/xhr
    28. places/bookmarks
    29. places/favicon
    30. places/history
    31. platform/xpcom
    32. preferences/event-target
    33. preferences/service
    34. remote/child
    35. remote/parent
    36. stylesheet/style
    37. stylesheet/utils
    38. system/child_process
    39. system/environment
    40. system/events
    41. system/runtime
    42. system/unload
    43. system/xul-app
    44. tabs/utils
    45. test/assert
    46. test/harness
    47. test/httpd
    48. test/runner
    49. test/utils
    50. ui/button/action
    51. ui/button/toggle
    52. ui/frame
    53. ui/id
    54. ui/sidebar
    55. ui/toolbar
    56. util/array
    57. util/collection
    58. util/deprecate
    59. util/list
    60. util/match-pattern
    61. util/object
    62. util/uuid
    63. window/utils
  10. Firefox for Android
  11. Getting started
    1. Walkthrough
    2. Debugging
    3. Code snippets
  12. APIs
    1. Accounts.jsm
    2. BrowserApp
    3. HelperApps.jsm
    4. Home.jsm
    5. HomeProvider.jsm
    6. JavaAddonManager.jsm
    7. NativeWindow
    8. Notifications.jsm
    9. PageActions.jsm
    10. Prompt.jsm
    11. Snackbars.jsm
    12. Sound.jsm
    13. Tab
  13. Legacy
  14. Restartless extensions
    1. Overview
  15. Overlay extensions
    1. Overview
  16. Themes
  17. Lightweight themes
    1. Overview
  18. Complete themes
    1. Overview
  19. Publishing add-ons
  20. Guides
    1. Signing and distribution overview
    2. Submit an add-on
    3. Review policies
    4. Developer agreement
    5. Featured add-ons
    6. Contact addons.mozilla.org
  21. Community and support
  22. Channels
    1. Add-ons blog
    2. Add-on forums
    3. Stack Overflow
    4. Development newsgroup
    5. IRC Channel