gecko/xpfe/bootstrap/nsDocLoadObserver.cpp

187 lines
5.7 KiB
C++

/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla Communicator client code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Simon Fraser <sfraser@netscape.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsCOMPtr.h"
#include "nsError.h"
#include "nsIObserverService.h"
#include "nsIServiceManager.h"
#include "nsString.h"
#include "nsReadableUtils.h"
#include "nsAEUtils.h"
#include "nsAESpyglassSuiteHandler.h"
#include "nsDocLoadObserver.h"
nsDocLoadObserver::nsDocLoadObserver()
: mRegistered(PR_FALSE)
{
}
nsDocLoadObserver::~nsDocLoadObserver()
{
}
NS_IMPL_ISUPPORTS1(nsDocLoadObserver, nsIObserver)
void nsDocLoadObserver::Register()
{
if (!mRegistered)
{
nsresult rv;
nsCOMPtr<nsIObserverService> anObserverService = do_GetService("@mozilla.org/observer-service;1", &rv);
if (NS_SUCCEEDED(rv))
{
if (NS_SUCCEEDED(anObserverService->AddObserver(this, "EndDocumentLoad", PR_FALSE)))
{
mRegistered = PR_TRUE;
}
}
}
}
void nsDocLoadObserver::Unregister()
{
if (mRegistered)
{
nsresult rv;
nsCOMPtr<nsIObserverService> anObserverService = do_GetService("@mozilla.org/observer-service;1", &rv);
if (NS_SUCCEEDED(rv))
{
if (NS_SUCCEEDED(anObserverService->RemoveObserver(this,
"EndDocumentLoad")))
{
mRegistered = PR_FALSE;
}
}
}
}
void nsDocLoadObserver::AddEchoRequester(OSType appSignature)
{
// make sure an application is only in the list once
mEchoRequesters.RemoveElement((void*)appSignature);
mEchoRequesters.AppendElement((void*)appSignature);
Register(); // ensure we are registered
}
void nsDocLoadObserver::RemoveEchoRequester(OSType appSignature)
{
mEchoRequesters.RemoveElement((void*)appSignature);
if (mEchoRequesters.Count() == 0)
Unregister();
}
NS_IMETHODIMP nsDocLoadObserver::Observe(nsISupports* /*aSubject*/,
const char* /*aTopic*/, const PRUnichar* someData)
{
// we need a URL to forward
if (!someData)
return NS_ERROR_NULL_POINTER;
// are there any echo requesters to notify?
if (mEchoRequesters.Count() == 0)
return NS_OK;
// create the descriptor for identifying this application
StAEDesc from;
const OSType mozz = 'MOZZ';
if (noErr != ::AECreateDesc(typeType, &mozz, sizeof(mozz), &from))
return NS_ERROR_UNEXPECTED;
// create the descriptor for the URL
nsString urlText(someData);
char* urlString = ToNewCString(urlText);
StAEDesc url;
OSErr err = ::AECreateDesc(typeChar, urlString, urlText.Length(), &url);
nsMemory::Free(urlString);
if (err != noErr)
return NS_ERROR_UNEXPECTED;
// keep track of any invalid requesters and remove them when we're done
nsVoidArray requestersToRemove;
PRInt32 numRequesters = mEchoRequesters.Count();
// now notify all the echo requesters
for (PRInt32 i = 0; i < numRequesters; i ++)
{
// specify the address of the requester
StAEDesc targetAddress;
const OSType target = (OSType)mEchoRequesters.ElementAt(i);
if (noErr != ::AECreateDesc(typeApplSignature, &target, sizeof(target), &targetAddress))
return NS_ERROR_UNEXPECTED;
// create the event
AppleEvent sendEvent;
err = ::AECreateAppleEvent(AESpyglassSuiteHandler::kSpyglassSendSignature,
AESpyglassSuiteHandler::kSendURLEchoEvent,
&targetAddress, kAutoGenerateReturnID, kAnyTransactionID, &sendEvent);
if (noErr != err)
{ // this target is no longer available
requestersToRemove.AppendElement((void *)target);
continue;
}
// attach our signature - to let the requester know who we are
err = ::AEPutParamDesc(&sendEvent, keyOriginalAddressAttr, &from);
NS_ASSERTION(noErr == err, "AEPutParamDesc");
// attach the new URL
err = ::AEPutParamDesc(&sendEvent, keyDirectObject, &url);
NS_ASSERTION(noErr == err, "AEPutParamDesc");
// send it
AppleEvent reply;
err = ::AESend(&sendEvent, &reply, kAENoReply, kAENormalPriority, 180, NULL, NULL);
NS_ASSERTION(noErr == err, "AESend");
::AEDisposeDesc(&sendEvent);
}
// now remove unresponsive requestors
for (PRInt32 i = 0; i < requestersToRemove.Count(); i ++)
{
OSType thisRequester = (OSType)requestersToRemove.ElementAt(i);
mEchoRequesters.RemoveElement((void *)thisRequester);
}
return NS_OK;
}