PatchingThunderbirdCore

Setting up a build environment under Windows 2k

I've used the instructions on this site: http://whereswalden.com/mozilla/msvcfree/ to set up the build environment for Thunderbird under Windows 2k. But using the Microsoft Visual Studio .NET 2003 compiler instead of the free download from MS. This caused the file XPIDL.EXE to be corrupt, which caused a memory problem. There is a bug report about this with a sollution here: https://bugzilla.mozilla.org/show_bug.cgi?id=208345 . Although this fixed the problem with XPIDL.EXE, I got a link error not much further in the compiling process. I think it has to do with the VC71 libraries. But I don't know how to resolve it yet.

-- BastiaanGrutters - 28 Oct 2005

Well, didn't manage to fix the link error, so tried compiling with the MS free download toolkit. Which went alot better, as it completed and I got a working Thunderbird, it has some problems with the extension updater, but I think that is because it uses ActiveX. (compiling entire Thunderbird takes about 1 and a half to 2 hours)

Thunderbird source

I have used all the compiling time by taking a look at the Thunderbird compose source to familiarize myself with it. As always with source code that isn't your own, it takes some time to understand. First thing to do was add some more debug information. This helped in both understanding the source and understanding the process of sending mail with Thunderbird.

Editing Thunderbird

Some fixes and tweaks are needed to the Thunderbird core in order to be able to write the Ops Thunderbird extension properly.

nsIMsgSendListener::OnStopSending bug

See: https://bugzilla.mozilla.org/show_bug.cgi?id=312275

I have added these 2 lines to the thunderbird core (nsMsgSend.cpp):

  // Get the message id and add it as a parameter to the OnStopSending notifier
  const char *msgId = nsnull;
  msgId = mCompFields->GetMessageId();
And to changed the first parameter in the NotifyListenerOnStopSending call to "msgId":
  //
  // Tell the listeners that we are done with the sending operation...
  //
  NotifyListenerOnStopSending( msgId, aExitCode, nsnull, nsnull );
Now the nsIMsgSendListener OnStopSending method correctly returns a message id, sending the e-mail message succeeded.

nsIMsgSendListener add and remove

See: https://bugzilla.mozilla.org/show_bug.cgi?id=308798

In addition to the bug fix there was need for a way to actually add the listener. The only way to do this was by adding a recyclinglistener and after the compose window had been opened and closed to set a propery in the compose parameters. Which would ofcourse cause trouble if multiple extensions wanted to add one, therefore I added AddMsgSendListener and RemoveMsgSendListener to nsMsgCompose.cpp.

nsresult nsMsgCompose::AddMsgSendListener( nsIMsgSendListener *msgSendListener ) {
  nsresult rv = NS_OK;
  
  if ( !msgSendListener ) {
    return NS_ERROR_NULL_POINTER;
  }
  
  if ( !mMsgSendListeners ) {
    rv = NS_NewISupportsArray( getter_AddRefs( mMsgSendListeners ) );
    if ( NS_FAILED( rv ) ) return rv;
  }

  nsCOMPtr<nsISupports> iSupports = do_QueryInterface( msgSendListener, &rv );
  if ( NS_FAILED( rv ) ) {
     return rv;
  }

  // note that this return value is really a PRBool, so be sure to use
  // NS_SUCCEEDED or NS_FAILED to check it.
  return mMsgSendListeners->AppendElement( iSupports );
}

nsresult nsMsgCompose::RemoveMsgSendListener( nsIMsgSendListener *msgSendListener ) {
  if ( !msgSendListener ) {
    return NS_ERROR_NULL_POINTER;
  }

  nsresult rv = NS_OK;
  
  // otherwise, see if it exists in our list
  if ( !mMsgSendListeners ) {
   return ( nsresult ) PR_FALSE;      // yeah, this sucks, but I'm emulating the behaviour of
  }                                 // nsISupportsArray::RemoveElement()

  nsCOMPtr<nsISupports> iSupports = do_QueryInterface( msgSendListener, &rv );
  if ( NS_FAILED( rv ) ) { 
   return rv;
  }

  // note that this return value is really a PRBool, so be sure to use
  // NS_SUCCEEDED or NS_FAILED to check it.
  return mMsgSendListeners->RemoveElement( iSupports );
}
I've also added mMsgSendListeners to the nsMsgCompose.h and added the method interface to nsIMsgCompose.idl, so these methods can be accessed through javascript.

Last step was actually notifying the listeners:

   // call OnStartSending for all added sendlisteners
    nsCOMPtr<nsISupportsArray> mMsgSendListeners;
    compose->GetMsgSendListeners( getter_AddRefs( mMsgSendListeners ) );
    if (!mMsgSendListeners) {
      return NS_OK;    // maybe there just aren't any.
    }
 
    PRUint32 numListeners;
    nsresult rv = mMsgSendListeners->Count( &numListeners );
    if ( NS_FAILED( rv ) ) return rv;

    PRUint32 i;
    for ( i = 0; i < numListeners; i ++ ) {
      nsCOMPtr<nsIMsgSendListener> thisListener =
      do_QueryElementAt( mMsgSendListeners, i );
      if ( thisListener ) {
        thisListener->OnStartSending( aMsgID, aMsgSize );
      }
    }
This piece of code was added for every notify method of nsIMsgSendListener. In order to get mMsgSendListeners I had to add another method in nsMsgCompose.cpp, GetMsgSendListeners, which just retrieves this parameter.

Creating a patch

By typing the following command from the development environment root (eg: c:\moz\mozilla):
cvs diff -u8pN
Differences will be shown with the current CVS version. Now the output can be put in a .diff file. (or directly by adding ">patch.diff" to the command.

-- BastiaanGrutters - 04 Nov 2005

Update

nsISupportsArray seems to be deprecated, so I switched to nsCOMArray(see: http://www.mozilla.org/projects/xpcom/array-guide.html#nsCOMArray) as that is the prefered array type. Following some more comments I had to change a lot of code to simplfy the whole listener notification process. The new approach seems to work and even to simplify some code, I had some issues with implementing the right interface to allow the sendlistener methods to be called from another object to nsMsgCompose. Everything seems to work now, I'll just submit the patch and await further comments.

Applying the patches to the source

Applying the diff patches to the source is done by moving to the mozilla source directory and then typing:
patch -p0 <"location of patches/msg_id.diff"
patch -p0 <"location of patches/sendlistener.diff"
Or as it will now be only 1 patch:
patch -p0 <"location of patches/sendlistener.diff"
Topic revision: r8 - 17 Jan 2006 - 15:22:29 - BastiaanGrutters

tip TWiki Tip of the Day
Disabling individual WikiWords
Prevent a WikiWord from being linked by prefixing it with an exclamation point. Example: To escape SunOs ... Read on Read more

 
This site is powered by the TWiki collaboration platformCopyright © by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding TWiki? Send feedback