1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5
6#include "nsISupports.idl"
7
8interface nsIMsgFolder;
9interface nsIMsgCopyServiceListener;
10interface nsIMsgDBHdr;
11interface nsIMsgWindow;
12interface nsIOutputStream;
13interface nsIInputStream;
14interface nsIUrlListener;
15interface nsIMsgDatabase;
16interface nsITransaction;
17
18[scriptable, uuid(F732CE58-E540-4dc4-B803-9456056EBEFC)]
19
20/**
21 * Pluggable message store interface. Each incoming server can have a different
22 * message store.
23 * All methods are synchronous unless otherwise specified.
24 */
25interface nsIMsgPluggableStore : nsISupports {
26  /**
27   * Examines the store and adds subfolders for the existing folders in the
28   * profile directory. aParentFolder->AddSubfolder is the normal way
29   * to register the subfolders. This method is expected to be synchronous.
30   * This shouldn't be confused with server folder discovery, which is allowed
31   * to be asynchronous.
32   *
33   * @param aParentFolder folder whose existing children we want to discover.
34   *                      This will be the root folder for the server object.
35   * @param aDeep true if we should discover all descendents. Would we ever
36   *              not want to do this?
37   */
38
39  void discoverSubFolders(in nsIMsgFolder aParentFolder, in boolean aDeep);
40  /**
41   * Creates storage for a new, empty folder.
42   *
43   * @param aParent parent folder
44   * @param aFolderName leaf name of folder.
45   * @return newly created folder.
46   * @exception NS_MSG_FOLDER_EXISTS If the child exists.
47   * @exception NS_MSG_CANT_CREATE_FOLDER for other errors.
48   */
49  nsIMsgFolder createFolder(in nsIMsgFolder aParent, in AString aFolderName);
50
51  /**
52   * Delete storage for a folder and its subfolders, if any.
53   * This is a real delete, not a move to the trash folder.
54   *
55   * @param aFolder folder to delete
56   */
57  void deleteFolder(in nsIMsgFolder aFolder);
58
59  /**
60   * Rename storage for an existing folder.
61   *
62   * @param aFolder folder to rename
63   * @param aNewName name to give new folder
64   * @return the renamed folder object
65   */
66  nsIMsgFolder renameFolder(in nsIMsgFolder aFolder, in AString aNewName);
67
68  /**
69   * Tells if the store has the requested amount of space available in the
70   * specified folder.
71   *
72   * @param aFolder folder we want to add messages to.
73   * @param aSpaceRequested How many bytes we're trying to add to the store.
74   *
75   * The function returns an exception if there is not enough space to
76   * indicate the reason of the shortage:
77   * NS_ERROR_FILE_TOO_BIG   = the store cannot grow further due to internal limits
78   * NS_ERROR_FILE_NO_DEVICE_SPACE = there is not enough space on the disk
79   */
80  boolean hasSpaceAvailable(in nsIMsgFolder aFolder,
81                            in long long aSpaceRequested);
82
83  /**
84   * Move/Copy a folder to a new parent folder. This method is asynchronous.
85   * The store needs to use the aListener to notify the core code of the
86   * completion of the operation. And it must send the appropriate
87   * nsIMsgFolderNotificationService notifications.
88   *
89   * @param aSrcFolder folder to move/copy
90   * @param aDstFolder parent dest folder
91   * @param aIsMoveFolder true if move, false if copy. If move, source folder
92   *                      is deleted when copy completes.
93   * @param aMsgWindow used to display progress, may be null
94   * @param aListener - used to get notification when copy is done.
95   * @param aNewName  Optional new name for the target folder.
96   *                  If rename is not needed, set this to empty string.
97   */
98  void copyFolder(in nsIMsgFolder aSrcFolder, in nsIMsgFolder aDstFolder,
99                  in boolean aIsMoveFolder, in nsIMsgWindow aMsgWindow,
100                  in nsIMsgCopyServiceListener aListener,
101                  in AString aNewName);
102
103  /**
104   * Get an output stream for a message in a folder.
105   *
106   * @param aFolder folder to create a message output stream for.
107   * @param aNewHdr If aNewHdr is set on input, then this is probably for
108   *                offline storage of an existing message. If null, the
109   *                this is a newly downloaded message and the store needs
110   *                to create a new header for the new message. If the db
111   *                is invalid, this can be null. But if the db is valid,
112   *                the store should create a message header with the right
113   *                message key, or whatever other property it needs to set to
114   *                be able to retrieve the message contents later. If the store
115   *                needs to base any of this on the contents of the message,
116   *                it will need remember the message header and hook into
117   *                the output stream somehow to alter the message header.
118   * @param aReusable set to true on output if the caller can reuse the
119   *                  stream for multiple messages, e.g., mbox format.
120   *                  This means the caller will likely get the same stream
121   *                  back on multiple calls to this method, and shouldn't
122   *                  close the stream in between calls if they want reuse.
123   *
124   * @return The output stream to write to. The output stream will be positioned
125   *         for writing (e.g., for berkeley mailbox, it will be at the end).
126   */
127  nsIOutputStream getNewMsgOutputStream(in nsIMsgFolder aFolder,
128                                        inout nsIMsgDBHdr aNewHdr,
129                                        out boolean aReusable);
130
131  /**
132   * Called when the current message is discarded, e.g., it is moved
133   * to an other folder as a filter action, or is deleted because it's
134   * a duplicate. This gives the berkeley mailbox store a chance to simply
135   * truncate the Inbox w/o leaving a deleted message in the store.
136   *
137   * @param aOutputStream stream we were writing the message to be discarded to
138   * @param aNewHdr header of message to discard
139   */
140  void discardNewMessage(in nsIOutputStream aOutputStream,
141                         in nsIMsgDBHdr aNewHdr);
142
143  /**
144   * Must be called by code that calls getNewMsgOutputStream to finish
145   * the process of storing a new message, if the new msg has not been
146   * discarded. Could/should this be combined with discardNewMessage?
147   *
148   * @param aOutputStream stream we were writing the message to.
149   * @param aNewHdr header of message finished.
150   */
151  void finishNewMessage(in nsIOutputStream aOutputStream,
152                         in nsIMsgDBHdr aNewHdr);
153
154  /**
155   * Called by pop3 message filters when a newly downloaded message is being
156   * moved by an incoming filter. This is called before finishNewMessage, and
157   * it allows the store to optimize that case.
158   *
159   * @param aNewHdr msg hdr of message being moved.
160   * @param aDestFolder folder to move message to, in the same store.
161   *
162   * @return true if successful, false if the store doesn't want to optimize
163   *         this.
164   * @exception If the moved failed. values TBD
165   */
166  boolean moveNewlyDownloadedMessage(in nsIMsgDBHdr aNewHdr,
167                                     in nsIMsgFolder aDestFolder);
168
169  /**
170   * Get an input stream that we can read the contents of a message from.
171   * If the input stream is reusable, and the caller is going to ask
172   * for input streams for other messages in the folder, then the caller
173   * should not close the stream until it is done with its messages.
174   *
175   * @param aMsgFolder Folder containing the message
176   * @param aMsgToken token that identifies message. This is store-dependent,
177   *                  and must be set as a string property "storeToken" on the
178   *                  message hdr by the store when the message is added
179   *                  to the store.
180   * @param aOffset offset in the returned stream of the message.
181   * @param[optional] aHdr msgHdr to use in case storeToken is not set. This is
182   *                  for upgrade from existing profiles.
183   * @param[optional] aReusable Is the returned stream re-usable for other
184   *                            messages' input streams?
185   */
186  nsIInputStream getMsgInputStream(in nsIMsgFolder aFolder,
187                                   in ACString aMsgToken,
188                                   out long long aOffset,
189                                   [optional] in nsIMsgDBHdr aHdr,
190                                   [optional] out boolean aReusable);
191
192  /**
193   * Delete the passed in messages. These message should all be in the
194   * same folder.
195   * @param aHdrArray array of nsIMsgDBHdr's.
196   */
197  void deleteMessages(in Array<nsIMsgDBHdr> aHdrArray);
198
199  /**
200   * This allows the store to handle a msg move/copy if it wants. This lets
201   * it optimize move/copies within the same store. E.g., for maildir, a
202   * msg move mostly entails moving the file containing the message, and
203   * updating the db. If the store does not want to implement this, the core
204   * code will use getMsgInputStream on the source message,
205   * getNewMsgOutputStream for the dest message, and stream the input to
206   * the output. This operation can be asynchronous.
207   * If the store does the copy, it must return the appropriate undo action,
208   * which can be store dependent. And it must send the appropriate
209   * nsIMsgFolderNotificationService notifications.
210   *
211   * @param isMove true if this is a move, false if it is a copy.
212   * @param aHdrArray array of nsIMsgDBHdr's, all in the same folder
213   * @param aDstFolder folder to move/copy the messages to.
214   * @param aListener listener to notify of copy status.
215   * @param aDstHdrs array of nsIMsgDBHdr's in the destination folder.
216   * @param[out,optional] aUndoAction transaction to provide undo, if
217   * the store does the copy itself.
218   * @return true if messages were copied, false if the core code should
219   *         do the copy.
220   */
221  boolean copyMessages(in boolean isMove,
222                       in Array<nsIMsgDBHdr> aHdrArray,
223                       in nsIMsgFolder aDstFolder,
224                       in nsIMsgCopyServiceListener aListener,
225                       out Array<nsIMsgDBHdr> aDstHdrs,
226                       out nsITransaction aUndoAction);
227
228  /**
229   * Does this store require compaction? For example, maildir doesn't require
230   * compaction at all. Berkeley mailbox does. A sqlite store probably doesn't.
231   * This is a static property of the store. It doesn't mean that any particular
232   * folder has space that can be reclaimed via compaction. Right now, the core
233   * code keeps track of the size of messages deleted, which it can use in
234   * conjunction with this store attribute.
235   */
236  readonly attribute boolean supportsCompaction;
237
238  /**
239   * Remove deleted messages from the store, reclaiming space. Some stores
240   * won't need to do anything here (e.g., maildir), and those stores
241   * should return false for needsCompaction. This operation is asynchronous,
242   * and the passed url listener should be called when the operation is done.
243   *
244   * @param aFolder folder whose storage is to be compacted
245   * @param aListener listener notified when compaction is done.
246   * @param aMsgWindow window to display progress/status in.
247   */
248  void compactFolder(in nsIMsgFolder aFolder, in nsIUrlListener aListener,
249                     in nsIMsgWindow aMsgWindow);
250
251  /**
252   * Is the summary file for the passed folder valid? For Berkeley Mailboxes,
253   * for local mail folders, this checks the timestamp and size of the local
254   * mail folder against values stored in the db. For other stores, this may
255   * be a noop, though other stores could certainly become invalid. For
256   * Berkeley Mailboxes, this is to deal with the case of other apps altering
257   * mailboxes from outside mailnews code, and this is certainly possible
258   * with other stores.
259   *
260   * @param aFolder Folder to check if summary is valid for.
261   * @param aDB DB to check validity of.
262   *
263   * @return return true if the summary file is valid, false otherwise.
264   */
265  boolean isSummaryFileValid(in nsIMsgFolder aFolder, in nsIMsgDatabase aDB);
266
267  /**
268   * Marks the summary file for aFolder as valid or invalid. This method
269   * may not be required, since it's really used by Berkeley Mailbox code
270   * to fix the timestamp and size for a folder.
271   *
272   * @param aFolder folder whose summary file should be marked (in)valid.
273   * @param aDB db to mark valid (may not be the folder's db in odd cases
274   *            like folder compaction.
275   * @param aValid whether to mark it valid or invalid.
276   */
277  void setSummaryFileValid(in nsIMsgFolder aFolder, in nsIMsgDatabase aDB,
278                           in boolean aValid);
279
280  /**
281   * Rebuild the index from information in the store. This involves creating
282   * a new nsIMsgDatabase for the folder, adding the information for all the
283   * messages in the store, and then copying the new msg database over the
284   * existing database. For Berkeley mailbox, we try to maintain meta data
285   * stored in the existing database when possible, and other stores should do
286   * the same. Ideally, I would figure out a way of making that easy. That
287   * might entail reworking the rebuild index process into one where the store
288   * would iterate over the messages, and stream each message through the
289   * message parser, and the common code would handle maintaining the
290   * meta data. But the berkeley mailbox code needs to do some parsing because
291   * it doesn't know how big the message is (i.e., the stream can't simply be
292   * a file stream).
293   * This operation is asynchronous,
294   * and the passed url listener should be called when the operation is done.
295   *
296   * @param aFolder folder whose storage is to be compacted
297   * @param aMsgDB db to put parsed headers in.
298   * @param aMsgWindow msgWindow to use for progress updates.
299   * @param aListener listener notified when the index is rebuilt.
300   */
301  void rebuildIndex(in nsIMsgFolder aFolder, in nsIMsgDatabase aMsgDB,
302                    in nsIMsgWindow aMsgWindow, in nsIUrlListener aListener);
303
304  /**
305   * Sets/Clears the passed flags on the passed messages.
306   * @param aHdrArray array of nsIMsgDBHdr's
307   * @param aFlags flags to set/clear
308   * @param aSet true to set the flag(s), false to clear.
309   */
310  void changeFlags(in Array<nsIMsgDBHdr> aHdrArray, in unsigned long aFlags,
311                   in boolean aSet);
312  /**
313   *Sets/Clears the passed keywords on the passed messages.
314   * @param aHdrArray array of nsIMsgDBHdr's
315   * @param aKeywords keywords to set/clear
316   * @param aAdd true to add the keyword(s), false to remove.
317   */
318  void changeKeywords(in Array<nsIMsgDBHdr> aHdrArray, in ACString aKeywords,
319                      in boolean aAdd);
320
321  /**
322   * Identifies a specific type of store. Please use this only for legacy
323   * bug fixes, and not as a method to change behavior!
324   *
325   * Typical values: "mbox", "maildir"
326   */
327  readonly attribute ACString storeType;
328};
329