Back to index

lightning-sunbird  0.9+nobinonly
nsDocLoadObserver.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is Mozilla Communicator client code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *   Simon Fraser <sfraser@netscape.com>
00024  *
00025  * Alternatively, the contents of this file may be used under the terms of
00026  * either of the GNU General Public License Version 2 or later (the "GPL"),
00027  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00028  * in which case the provisions of the GPL or the LGPL are applicable instead
00029  * of those above. If you wish to allow use of your version of this file only
00030  * under the terms of either the GPL or the LGPL, and not to allow others to
00031  * use your version of this file under the terms of the MPL, indicate your
00032  * decision by deleting the provisions above and replace them with the notice
00033  * and other provisions required by the GPL or the LGPL. If you do not delete
00034  * the provisions above, a recipient may use your version of this file under
00035  * the terms of any one of the MPL, the GPL or the LGPL.
00036  *
00037  * ***** END LICENSE BLOCK ***** */
00038 
00039 #include "nsCOMPtr.h"
00040 #include "nsError.h"
00041 #include "nsIObserverService.h"
00042 #include "nsIServiceManager.h"
00043 #include "nsString.h"
00044 #include "nsReadableUtils.h"
00045 #include "nsAEUtils.h"
00046 #include "nsAESpyglassSuiteHandler.h"
00047 
00048 #include "nsDocLoadObserver.h"
00049 
00050 nsDocLoadObserver::nsDocLoadObserver()
00051 :      mRegistered(PR_FALSE)
00052 {
00053 }
00054 
00055 nsDocLoadObserver::~nsDocLoadObserver()
00056 {
00057 }
00058 
00059 
00060 NS_IMPL_ISUPPORTS1(nsDocLoadObserver, nsIObserver)
00061 
00062 void nsDocLoadObserver::Register()
00063 {
00064        if (!mRegistered)
00065        {
00066               nsresult rv;
00067               nsCOMPtr<nsIObserverService> anObserverService = do_GetService("@mozilla.org/observer-service;1", &rv);
00068               if (NS_SUCCEEDED(rv))
00069               {
00070                      if (NS_SUCCEEDED(anObserverService->AddObserver(this, "EndDocumentLoad", PR_FALSE)))
00071                      {
00072                             mRegistered = PR_TRUE;
00073                      }
00074               }
00075        }
00076 }
00077 
00078 void nsDocLoadObserver::Unregister()
00079 {
00080        if (mRegistered)
00081        {
00082               nsresult rv;
00083               nsCOMPtr<nsIObserverService> anObserverService = do_GetService("@mozilla.org/observer-service;1", &rv);
00084               if (NS_SUCCEEDED(rv))
00085               {
00086                      if (NS_SUCCEEDED(anObserverService->RemoveObserver(this, 
00087                             "EndDocumentLoad")))
00088                      {
00089                             mRegistered = PR_FALSE;
00090                      }
00091               }
00092        }
00093 }
00094 
00095 void nsDocLoadObserver::AddEchoRequester(OSType appSignature)
00096 {
00097   // make sure an application is only in the list once
00098   mEchoRequesters.RemoveElement((void*)appSignature);
00099   
00100        mEchoRequesters.AppendElement((void*)appSignature);
00101        Register();     // ensure we are registered
00102 }
00103 
00104 void nsDocLoadObserver::RemoveEchoRequester(OSType appSignature)
00105 {
00106        mEchoRequesters.RemoveElement((void*)appSignature);
00107        if (mEchoRequesters.Count() == 0)
00108          Unregister();
00109 }
00110 
00111 NS_IMETHODIMP nsDocLoadObserver::Observe(nsISupports* /*aSubject*/,
00112               const char* /*aTopic*/, const PRUnichar* someData)
00113 {
00114        // we need a URL to forward
00115        if (!someData)
00116               return NS_ERROR_NULL_POINTER;
00117 
00118        // are there any echo requesters to notify?
00119        if (mEchoRequesters.Count() == 0)
00120               return NS_OK;
00121 
00122        // create the descriptor for identifying this application
00123        StAEDesc from;
00124        const OSType mozz = 'MOZZ';
00125        if (noErr != ::AECreateDesc(typeType, &mozz, sizeof(mozz), &from))
00126               return NS_ERROR_UNEXPECTED;
00127 
00128        // create the descriptor for the URL
00129        nsString urlText(someData);
00130        char* urlString = ToNewCString(urlText);
00131 
00132        StAEDesc url;
00133        OSErr err = ::AECreateDesc(typeChar, urlString, urlText.Length(), &url);
00134        nsMemory::Free(urlString);
00135        if (err != noErr)
00136               return NS_ERROR_UNEXPECTED;
00137 
00138        // keep track of any invalid requesters and remove them when we're done
00139        nsVoidArray requestersToRemove;
00140        
00141        PRInt32              numRequesters = mEchoRequesters.Count();
00142        
00143        // now notify all the echo requesters
00144        for (PRInt32 i = 0; i < numRequesters; i ++)
00145        {
00146               // specify the address of the requester
00147               StAEDesc targetAddress;
00148               const OSType target = (OSType)mEchoRequesters.ElementAt(i);
00149               if (noErr != ::AECreateDesc(typeApplSignature, &target, sizeof(target), &targetAddress))
00150                      return NS_ERROR_UNEXPECTED;
00151 
00152               // create the event
00153               AppleEvent sendEvent;
00154               err = ::AECreateAppleEvent(AESpyglassSuiteHandler::kSpyglassSendSignature,
00155                             AESpyglassSuiteHandler::kSendURLEchoEvent, 
00156                             &targetAddress, kAutoGenerateReturnID, kAnyTransactionID, &sendEvent);
00157               if (noErr != err)
00158               {      // this target is no longer available
00159                      requestersToRemove.AppendElement((void *)target);
00160                      continue;
00161               }
00162 
00163               // attach our signature - to let the requester know who we are
00164               err = ::AEPutParamDesc(&sendEvent, keyOriginalAddressAttr, &from);
00165               NS_ASSERTION(noErr == err, "AEPutParamDesc");
00166 
00167               // attach the new URL
00168               err = ::AEPutParamDesc(&sendEvent, keyDirectObject, &url);
00169               NS_ASSERTION(noErr == err, "AEPutParamDesc");
00170               
00171               // send it
00172               AppleEvent reply;
00173               err = ::AESend(&sendEvent, &reply, kAENoReply, kAENormalPriority, 180, NULL, NULL);
00174               NS_ASSERTION(noErr == err, "AESend");
00175               ::AEDisposeDesc(&sendEvent);
00176        }
00177 
00178        // now remove unresponsive requestors
00179        for (PRInt32 i = 0; i < requestersToRemove.Count(); i ++)
00180        {
00181               OSType thisRequester = (OSType)requestersToRemove.ElementAt(i);
00182               mEchoRequesters.RemoveElement((void *)thisRequester);
00183        }
00184        
00185        return NS_OK;
00186 }