Files
tubestation/modules/plugin/nglsrc/nsPluginViewer.cpp
dougt@netscape.com a70fce6f87 Revising nsIChannel to allow for overlapped i/o. This consists of three parts:
1. Factoring nsIChannel into a protocol specific part, the nsIChannel, and a socket specific, the nsITransport.
2. Derive the nsIChannel from a nsIRequest.
2. Changes the notification system from necko and the URILoader to pass the nsIRequest interface instead of nsIChannel interface.

This goal stems from wanting to be able to have active AsyncRead and AsyncWrite operations on nsSocketTransport.
This is desired because it would greatly simplify the task of maintaining persistent/reusable socket connections
for FTP, HTTP, and Imap (and potentially other protocols).  The problem with the existing nsIChannel interface is
that it does not allow one to selectively suspend just one of the read or write operations while keeping the other active.

The full details of the change on written up in the netlib newsgroup.

r=darin@netscape.com
sr=rpotts@netscape.com
2001-02-10 00:16:26 +00:00

929 lines
22 KiB
C++

/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape 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/NPL/
*
* 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 Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include "nsCOMPtr.h"
#include "nscore.h"
#include "nsCRT.h"
#include "nsIContentViewer.h"
#include "nsIPluginHost.h"
#include "nsIPluginInstance.h"
#include "nsIStreamListener.h"
#include "nsIURL.h"
#include "nsIChannel.h"
#include "nsNetUtil.h"
#include "nsIComponentManager.h"
#include "nsWidgetsCID.h"
#include "nsILinkHandler.h"
#include "nsIWebShell.h"
#include "nsIContentViewerEdit.h"
#include "nsIContentViewerFile.h"
#include "nsIContent.h"
#include "nsIDocument.h"
#include "nsIInterfaceRequestor.h"
#include "nsIDocShellTreeItem.h"
#include "nsIDocShellTreeOwner.h"
#include "nsIWebBrowserChrome.h"
#include "nsIDOMDocument.h"
#include "nsPluginViewer.h"
// Class IDs
static NS_DEFINE_IID(kChildWindowCID, NS_CHILD_CID);
static NS_DEFINE_IID(kIWidgetIID, NS_IWIDGET_IID);
// Interface IDs
static NS_DEFINE_IID(kIContentViewerIID, NS_ICONTENTVIEWER_IID);
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
static NS_DEFINE_IID(kIPluginInstanceOwnerIID, NS_IPLUGININSTANCEOWNER_IID);
static NS_DEFINE_IID(kCPluginManagerCID, NS_PLUGINMANAGER_CID);
static NS_DEFINE_IID(kIStreamListenerIID, NS_ISTREAMLISTENER_IID);
static NS_DEFINE_IID(kIDocumentIID, NS_IDOCUMENT_IID);
class PluginViewerImpl;
class PluginListener : public nsIStreamListener {
public:
PluginListener(PluginViewerImpl* aViewer);
virtual ~PluginListener();
// nsISupports
NS_DECL_ISUPPORTS
// nsIStreamObserver methods:
NS_DECL_NSISTREAMOBSERVER
// nsIStreamListener methods:
NS_DECL_NSISTREAMLISTENER
PluginViewerImpl* mViewer;
nsIStreamListener* mNextStream;
};
class pluginInstanceOwner : public nsIPluginInstanceOwner
{
public:
pluginInstanceOwner();
virtual ~pluginInstanceOwner();
NS_DECL_ISUPPORTS
//nsIPluginInstanceOwner interface
NS_IMETHOD SetInstance(nsIPluginInstance *aInstance);
NS_IMETHOD GetInstance(nsIPluginInstance *&aInstance);
NS_IMETHOD GetWindow(nsPluginWindow *&aWindow);
NS_IMETHOD GetMode(nsPluginMode *aMode);
NS_IMETHOD CreateWidget(void);
NS_IMETHOD GetURL(const char *aURL, const char *aTarget,
void *aPostData, PRUint32 aPostDataLen,
void *aHeadersData, PRUint32 aHeadersDataLen);
NS_IMETHOD ShowStatus(const char *aStatusMsg);
NS_IMETHOD GetDocument(nsIDocument* *aDocument);
//locals
NS_IMETHOD Init(PluginViewerImpl *aViewer, nsIWidget *aWindow);
private:
nsPluginWindow mPluginWindow;
nsIPluginInstance *mInstance;
nsIWidget *mWindow; //we do not addref this...
PluginViewerImpl *mViewer; //we do not addref this...
};
class PluginViewerImpl : public nsIContentViewer,
public nsIContentViewerEdit,
public nsIContentViewerFile
{
public:
PluginViewerImpl(const char* aCommand);
nsresult Init(nsIStreamListener** aDocListener);
NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW
// nsISupports
NS_DECL_ISUPPORTS
// nsIContentViewer
NS_IMETHOD Init(nsIWidget* aParentWidget,
nsIDeviceContext* aDeviceContext,
const nsRect& aBounds);
NS_IMETHOD BindToDocument(nsISupports* aDoc, const char* aCommand);
NS_IMETHOD SetContainer(nsISupports* aContainer);
NS_IMETHOD GetContainer(nsISupports** aContainerResult);
NS_IMETHOD LoadComplete(nsresult aStatus);
NS_IMETHOD Destroy(void);
NS_IMETHOD Stop(void);
NS_IMETHOD GetDOMDocument(nsIDOMDocument **aResult);
NS_IMETHOD SetDOMDocument(nsIDOMDocument *aDocument);
NS_IMETHOD GetBounds(nsRect& aResult);
NS_IMETHOD SetBounds(const nsRect& aBounds);
NS_IMETHOD Move(PRInt32 aX, PRInt32 aY);
NS_IMETHOD Show();
NS_IMETHOD Hide();
NS_IMETHOD SetEnableRendering(PRBool aOn);
NS_IMETHOD GetEnableRendering(PRBool* aResult);
// nsIContentViewerEdit
NS_DECL_NSICONTENTVIEWEREDIT
// nsIContentViewerFile
NS_DECL_NSICONTENTVIEWERFILE
virtual ~PluginViewerImpl();
nsresult CreatePlugin(nsIRequest* request, nsIPluginHost* aHost, const nsRect& aBounds,
nsIStreamListener*& aResult);
nsresult MakeWindow(nsNativeWidget aParent,
nsIDeviceContext* aDeviceContext,
const nsRect& aBounds);
nsresult StartLoad(nsIRequest* request, nsIStreamListener*& aResult);
void ForceRefresh(void);
nsresult GetURI(nsIURI* *aURI);
nsresult GetDocument(nsIDocument* *aDocument);
nsIWidget* mWindow;
nsIDocument* mDocument;
nsCOMPtr<nsISupports> mContainer;
nsIChannel* mChannel;
pluginInstanceOwner *mOwner;
PRBool mEnableRendering;
};
//----------------------------------------------------------------------
nsresult
NS_NewPluginContentViewer(const char* aCommand,
nsIStreamListener** aDocListener,
nsIContentViewer** aDocViewer)
{
PluginViewerImpl* it = new PluginViewerImpl(aCommand);
if (nsnull == it) {
return NS_ERROR_OUT_OF_MEMORY;
}
nsresult rv = it->Init(aDocListener);
if (NS_FAILED(rv)) {
delete it;
return rv;
}
return it->QueryInterface(kIContentViewerIID, (void**) aDocViewer);
}
// Note: operator new zeros our memory
PluginViewerImpl::PluginViewerImpl(const char* aCommand)
{
NS_INIT_REFCNT();
mEnableRendering = PR_TRUE;
}
nsresult
PluginViewerImpl::Init(nsIStreamListener** aDocListener)
{
nsIStreamListener* it = new PluginListener(this);
if (it == nsnull)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(it);
*aDocListener = it;
return NS_OK;
}
// ISupports implementation...
NS_IMPL_ADDREF(PluginViewerImpl)
NS_IMPL_RELEASE(PluginViewerImpl)
nsresult
PluginViewerImpl::QueryInterface(REFNSIID aIID, void** aInstancePtr)
{
if (NULL == aInstancePtr) {
return NS_ERROR_NULL_POINTER;
}
if (aIID.Equals(kIContentViewerIID)) {
nsIContentViewer* tmp = this;
*aInstancePtr = (void*)tmp;
NS_ADDREF_THIS();
return NS_OK;
}
if (aIID.Equals(kISupportsIID)) {
nsIContentViewer* tmp1 = this;
nsISupports* tmp2 = tmp1;
*aInstancePtr = (void*) tmp2;
NS_ADDREF_THIS();
return NS_OK;
}
return NS_NOINTERFACE;
}
PluginViewerImpl::~PluginViewerImpl()
{
NS_IF_RELEASE(mOwner);
if (nsnull != mWindow) {
mWindow->Destroy();
NS_RELEASE(mWindow);
}
NS_IF_RELEASE(mDocument);
NS_IF_RELEASE(mChannel);
}
/*
* This method is called by the Document Loader once a document has
* been created for a particular data stream... The content viewer
* must cache this document for later use when Init(...) is called.
*/
NS_IMETHODIMP
PluginViewerImpl::BindToDocument(nsISupports *aDoc, const char *aCommand)
{
#ifdef NS_DEBUG
printf("PluginViewerImpl::BindToDocument\n");
#endif
return aDoc->QueryInterface(kIDocumentIID, (void**)&mDocument);
return NS_OK;
}
NS_IMETHODIMP
PluginViewerImpl::SetContainer(nsISupports* aContainer)
{
mContainer = aContainer;
return NS_OK;
}
NS_IMETHODIMP
PluginViewerImpl::GetContainer(nsISupports** aResult)
{
NS_ENSURE_ARG_POINTER(aResult);
*aResult = mContainer;
NS_IF_ADDREF(*aResult);
return NS_OK;
}
NS_IMETHODIMP
PluginViewerImpl::Init(nsIWidget* aParentWidget,
nsIDeviceContext* aDeviceContext,
const nsRect& aBounds)
{
nsresult rv = MakeWindow(aParentWidget->GetNativeData(NS_NATIVE_WIDGET),
aDeviceContext, aBounds);
if (NS_OK == rv) {
mOwner = new pluginInstanceOwner();
if (nsnull != mOwner) {
NS_ADDREF(mOwner);
rv = mOwner->Init(this, mWindow);
}
}
return rv;
}
nsresult
PluginViewerImpl::StartLoad(nsIRequest* request, nsIStreamListener*& aResult)
{
nsCOMPtr<nsIChannel> channel = do_QueryInterface(request);
if (!channel) return NS_ERROR_FAILURE;
NS_IF_RELEASE(mChannel);
mChannel = channel;
NS_ADDREF(mChannel);
#ifdef DEBUG
char* contentType;
channel->GetContentType(&contentType);
printf("PluginViewerImpl::StartLoad: content-type=%s\n", contentType);
nsCRT::free(contentType);
#endif
aResult = nsnull;
// Only instantiate the plugin if our container can host it
nsCOMPtr<nsIPluginHost> host;
host = do_GetService(kCPluginManagerCID);
nsresult rv = NS_ERROR_FAILURE;
if(host)
{
nsRect r;
mWindow->GetClientBounds(r);
rv = CreatePlugin(request, host, nsRect(0, 0, r.width, r.height), aResult);
}
return rv;
}
nsresult
PluginViewerImpl::CreatePlugin(nsIRequest* request, nsIPluginHost* aHost, const nsRect& aBounds,
nsIStreamListener*& aResult)
{
nsresult rv = NS_OK;
if (nsnull != mOwner) {
nsPluginWindow *win;
mOwner->GetWindow(win);
win->x = aBounds.x;
win->y = aBounds.y;
win->width = aBounds.width;
win->height = aBounds.height;
win->clipRect.top = aBounds.y;
win->clipRect.left = aBounds.x;
win->clipRect.bottom = aBounds.YMost();
win->clipRect.right = aBounds.XMost();
#ifdef XP_UNIX
win->ws_info = nsnull; //XXX need to figure out what this is. MMP
#endif
nsIURI* uri;
rv = mChannel->GetURI(&uri);
if (NS_FAILED(rv)) return rv;
char* spec;
rv = uri->GetSpec(&spec);
NS_RELEASE(uri);
if (NS_FAILED(rv)) return rv;
nsAutoString str; str.AssignWithConversion(spec);
nsCRT::free(spec);
char* ct;
nsCOMPtr<nsIChannel> channel = do_QueryInterface(request);
channel->GetContentType(&ct);
if (NS_FAILED(rv)) return rv;
rv = aHost->InstantiateFullPagePlugin(ct, str, aResult, mOwner);
delete[] ct;
}
return rv;
}
NS_IMETHODIMP
PluginViewerImpl::Stop(void)
{
// XXX write this
return NS_OK;
}
NS_IMETHODIMP
PluginViewerImpl::LoadComplete(nsresult aStatus)
{
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
PluginViewerImpl::Destroy(void)
{
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
PluginViewerImpl::GetDOMDocument(nsIDOMDocument **aResult)
{
return (mDocument) ? CallQueryInterface(mDocument, aResult) : NS_ERROR_FAILURE;
}
NS_IMETHODIMP
PluginViewerImpl::SetDOMDocument(nsIDOMDocument *aDocument)
{
return NS_ERROR_FAILURE;
}
static nsEventStatus PR_CALLBACK
HandlePluginEvent(nsGUIEvent *aEvent)
{
if( (*aEvent).message == NS_PLUGIN_ACTIVATE) {
(nsIWidget*)((*aEvent).widget)->SetFocus();
}
return nsEventStatus_eIgnore;
}
nsresult
PluginViewerImpl::MakeWindow(nsNativeWidget aParent,
nsIDeviceContext* aDeviceContext,
const nsRect& aBounds)
{
nsresult rv =
nsComponentManager::CreateInstance(kChildWindowCID, nsnull, kIWidgetIID,
(void**)&mWindow);
if (NS_OK != rv) {
return rv;
}
mWindow->Create(aParent, aBounds, HandlePluginEvent, aDeviceContext);
return rv;
}
NS_IMETHODIMP
PluginViewerImpl::GetBounds(nsRect& aResult)
{
NS_PRECONDITION(nsnull != mWindow, "null window");
if (nsnull != mWindow) {
mWindow->GetBounds(aResult);
}
else {
aResult.SetRect(0, 0, 0, 0);
}
return NS_OK;
}
NS_IMETHODIMP
PluginViewerImpl::SetBounds(const nsRect& aBounds)
{
NS_PRECONDITION(nsnull != mWindow, "null window");
if (nsnull != mWindow) {
// Don't have the widget repaint. Layout will generate repaint requests
// during reflow
nsIPluginInstance *inst;
mWindow->Resize(aBounds.x, aBounds.y, aBounds.width, aBounds.height, PR_FALSE);
if ((nsnull != mOwner) && (NS_OK == mOwner->GetInstance(inst)) && (nsnull != inst)) {
nsPluginWindow *win;
if (NS_OK == mOwner->GetWindow(win)) {
win->x = aBounds.x;
win->y = aBounds.y;
win->width = aBounds.width;
win->height = aBounds.height;
win->clipRect.top = aBounds.y;
win->clipRect.left = aBounds.x;
win->clipRect.bottom = aBounds.YMost();
win->clipRect.right = aBounds.XMost();
inst->SetWindow(win);
}
NS_RELEASE(inst);
}
}
return NS_OK;
}
NS_IMETHODIMP
PluginViewerImpl::Move(PRInt32 aX, PRInt32 aY)
{
NS_PRECONDITION(nsnull != mWindow, "null window");
if (nsnull != mWindow) {
nsIPluginInstance *inst;
mWindow->Move(aX, aY);
if ((nsnull != mOwner) && (NS_OK == mOwner->GetInstance(inst)) && (nsnull != inst)) {
nsPluginWindow *win;
if (NS_OK == mOwner->GetWindow(win)) {
win->x = aX;
win->y = aY;
win->clipRect.bottom = (win->clipRect.bottom - win->clipRect.top) + aY;
win->clipRect.right = (win->clipRect.right - win->clipRect.left) + aX;
win->clipRect.top = aY;
win->clipRect.left = aX;
inst->SetWindow(win);
}
NS_RELEASE(inst);
}
}
return NS_OK;
}
NS_IMETHODIMP
PluginViewerImpl::Show()
{
NS_PRECONDITION(nsnull != mWindow, "null window");
if (nsnull != mWindow) {
mWindow->Show(PR_TRUE);
}
// XXX should we call SetWindow here?
return NS_OK;
}
NS_IMETHODIMP
PluginViewerImpl::Hide()
{
NS_PRECONDITION(nsnull != mWindow, "null window");
if (nsnull != mWindow) {
mWindow->Show(PR_FALSE);
}
// should we call SetWindow(nsnull) here?
return NS_OK;
}
NS_IMETHODIMP
PluginViewerImpl::SetEnableRendering(PRBool aOn)
{
mEnableRendering = aOn;
return NS_OK;
}
NS_IMETHODIMP
PluginViewerImpl::GetEnableRendering(PRBool* aResult)
{
NS_PRECONDITION(nsnull != aResult, "null OUT ptr");
if (aResult) {
*aResult = mEnableRendering;
}
return NS_OK;
}
void
PluginViewerImpl::ForceRefresh()
{
mWindow->Invalidate(PR_TRUE);
}
nsresult PluginViewerImpl::GetURI(nsIURI* *aURI)
{
return mChannel->GetURI(aURI);
}
nsresult PluginViewerImpl::GetDocument(nsIDocument* *aDocument)
{
NS_IF_ADDREF(mDocument);
*aDocument = mDocument;
return NS_OK;
}
/* ========================================================================================
* nsIContentViewerFile
* ======================================================================================== */
NS_IMETHODIMP PluginViewerImpl::Search()
{
NS_ASSERTION(0, "NOT IMPLEMENTED");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP PluginViewerImpl::GetSearchable(PRBool *aSearchable)
{
NS_ASSERTION(0, "NOT IMPLEMENTED");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP PluginViewerImpl::ClearSelection()
{
NS_ASSERTION(0, "NOT IMPLEMENTED");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP PluginViewerImpl::SelectAll()
{
NS_ASSERTION(0, "NOT IMPLEMENTED");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP PluginViewerImpl::CopySelection()
{
NS_ASSERTION(0, "NOT IMPLEMENTED");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP PluginViewerImpl::GetCopyable(PRBool *aCopyable)
{
NS_ASSERTION(0, "NOT IMPLEMENTED");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP PluginViewerImpl::CutSelection()
{
NS_ASSERTION(0, "NOT IMPLEMENTED");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP PluginViewerImpl::GetCutable(PRBool *aCutable)
{
NS_ASSERTION(0, "NOT IMPLEMENTED");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP PluginViewerImpl::Paste()
{
NS_ASSERTION(0, "NOT IMPLEMENTED");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP PluginViewerImpl::GetPasteable(PRBool *aPasteable)
{
NS_ASSERTION(0, "NOT IMPLEMENTED");
return NS_ERROR_NOT_IMPLEMENTED;
}
/* ========================================================================================
* nsIContentViewerEdit
* ======================================================================================== */
NS_IMETHODIMP
PluginViewerImpl::Save()
{
NS_ASSERTION(0, "NOT IMPLEMENTED");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
PluginViewerImpl::GetSaveable(PRBool *aSaveable)
{
NS_ASSERTION(0, "NOT IMPLEMENTED");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
PluginViewerImpl::Print(PRBool aSilent,FILE *aFile, nsIPrintListener *aPrintListener)
{
return NS_OK; // XXX: hey, plug in guys! implement me!
}
NS_IMETHODIMP
PluginViewerImpl::GetPrintable(PRBool *aPrintable)
{
NS_ENSURE_ARG_POINTER(aPrintable);
*aPrintable = PR_FALSE; // XXX: hey, plug in guys! implement me!
return NS_OK;
}
NS_IMETHODIMP
PluginViewerImpl::PrintContent(nsIWebShell * aParent,
nsIDeviceContext * aDContext,
nsIDOMWindow * aDOMWin,
PRBool aIsSubDoc)
{
NS_ENSURE_ARG_POINTER(aParent);
NS_ENSURE_ARG_POINTER(aDContext);
return NS_OK;
}
//----------------------------------------------------------------------
PluginListener::PluginListener(PluginViewerImpl* aViewer)
{
NS_INIT_REFCNT();
mViewer = aViewer;
NS_ADDREF(aViewer);
}
PluginListener::~PluginListener()
{
NS_RELEASE(mViewer);
NS_IF_RELEASE(mNextStream);
}
NS_IMPL_ISUPPORTS(PluginListener, kIStreamListenerIID)
NS_IMETHODIMP
PluginListener::OnStartRequest(nsIRequest *request, nsISupports *ctxt)
{
nsresult rv;
char* contentType = nsnull;
nsCOMPtr<nsIChannel> channel = do_QueryInterface(request);
rv = channel->GetContentType(&contentType);
if (NS_FAILED(rv)) {
return rv;
}
rv = mViewer->StartLoad(request, mNextStream);
if (NS_FAILED(rv)) {
return rv;
}
if (nsnull == mNextStream)
return NS_ERROR_FAILURE;
return mNextStream->OnStartRequest(request, ctxt);
}
NS_IMETHODIMP
PluginListener::OnStopRequest(nsIRequest *request, nsISupports *ctxt,
nsresult status, const PRUnichar *errorMsg)
{
if (nsnull == mNextStream) {
return NS_ERROR_FAILURE;
}
return mNextStream->OnStopRequest(request, ctxt, status, errorMsg);
}
NS_IMETHODIMP
PluginListener::OnDataAvailable(nsIRequest *request, nsISupports *ctxt,
nsIInputStream *inStr, PRUint32 sourceOffset, PRUint32 count)
{
if (nsnull == mNextStream) {
return NS_ERROR_FAILURE;
}
return mNextStream->OnDataAvailable(request, ctxt, inStr, sourceOffset, count);
}
//----------------------------------------------------------------------
pluginInstanceOwner :: pluginInstanceOwner()
{
NS_INIT_REFCNT();
memset(&mPluginWindow, 0, sizeof(mPluginWindow));
mInstance = nsnull;
mWindow = nsnull;
mViewer = nsnull;
}
pluginInstanceOwner :: ~pluginInstanceOwner()
{
if (nsnull != mInstance)
{
PRBool doCache = PR_TRUE;
// determine if the plugin wants to be cached
mInstance->GetValue(nsPluginInstanceVariable_DoCacheBool,
(void *) &doCache);
mInstance->Stop();
if (!doCache) {
// if not, destroy the instance
mInstance->Destroy();
}
else {
nsCOMPtr<nsIPluginHost> host;
host = do_GetService(kCPluginManagerCID);
if(host)
host->StopPluginInstance(mInstance);
}
NS_RELEASE(mInstance);
}
mWindow = nsnull;
mViewer = nsnull;
}
NS_IMPL_ISUPPORTS(pluginInstanceOwner, kIPluginInstanceOwnerIID);
NS_IMETHODIMP pluginInstanceOwner :: SetInstance(nsIPluginInstance *aInstance)
{
NS_IF_RELEASE(mInstance);
mInstance = aInstance;
NS_IF_ADDREF(mInstance);
return NS_OK;
}
NS_IMETHODIMP pluginInstanceOwner :: GetInstance(nsIPluginInstance *&aInstance)
{
NS_IF_ADDREF(mInstance);
aInstance = mInstance;
return NS_OK;
}
NS_IMETHODIMP pluginInstanceOwner :: GetWindow(nsPluginWindow *&aWindow)
{
aWindow = &mPluginWindow;
return NS_OK;
}
NS_IMETHODIMP pluginInstanceOwner :: GetMode(nsPluginMode *aMode)
{
*aMode = nsPluginMode_Full;
return NS_OK;
}
NS_IMETHODIMP pluginInstanceOwner :: CreateWidget(void)
{
PRBool windowless;
if (nsnull != mInstance)
{
mInstance->GetValue(nsPluginInstanceVariable_WindowlessBool, (void *)&windowless);
if (PR_TRUE == windowless)
{
mPluginWindow.window = nsnull; //XXX this needs to be a HDC
mPluginWindow.type = nsPluginWindowType_Drawable;
}
else if (nsnull != mWindow)
{
mPluginWindow.window = (nsPluginPort *)mWindow->GetNativeData(NS_NATIVE_PLUGIN_PORT);
mPluginWindow.type = nsPluginWindowType_Window;
}
else
return NS_ERROR_FAILURE;
}
else
return NS_ERROR_FAILURE;
return NS_OK;
}
NS_IMETHODIMP pluginInstanceOwner :: GetURL(const char *aURL, const char *aTarget, void *aPostData, PRUint32 aPostDataLen, void *aHeadersData,
PRUint32 aHeadersDataLen)
{
nsresult rv;
if (nsnull != mViewer)
{
nsCOMPtr<nsISupports> cont;
rv = mViewer->GetContainer(getter_AddRefs(cont));
if (NS_OK == rv)
{
nsCOMPtr<nsILinkHandler> lh(do_QueryInterface(cont));
if (lh)
{
nsCOMPtr<nsIURI> uri;
rv = mViewer->GetURI(getter_AddRefs(uri));
if (NS_OK == rv)
{
// Create an absolute URL
char* absURIStr;
rv = NS_MakeAbsoluteURI(&absURIStr, aURL, uri);
nsAutoString fullurl; fullurl.AssignWithConversion(absURIStr);
nsCRT::free(absURIStr);
if (NS_OK == rv) {
nsAutoString unitarget; unitarget.AssignWithConversion(aTarget);
rv = lh->OnLinkClick(nsnull, eLinkVerb_Replace, fullurl.GetUnicode(), unitarget.GetUnicode(), nsnull);
}
}
}
}
}
else
rv = NS_ERROR_FAILURE;
return rv;
}
NS_IMETHODIMP pluginInstanceOwner :: ShowStatus(const char *aStatusMsg)
{
nsresult rv = NS_ERROR_FAILURE;
if (nsnull != mViewer)
{
nsCOMPtr<nsISupports> cont;
rv = mViewer->GetContainer(getter_AddRefs(cont));
if ((NS_OK == rv) && (nsnull != cont))
{
nsCOMPtr<nsIDocShellTreeItem> docShellItem(do_QueryInterface(cont));
if (docShellItem)
{
nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
docShellItem->GetTreeOwner(getter_AddRefs(treeOwner));
if(treeOwner)
{
nsCOMPtr<nsIWebBrowserChrome> browserChrome(do_GetInterface(treeOwner));
if(browserChrome)
{
nsAutoString msg; msg.AssignWithConversion(aStatusMsg);
browserChrome->SetStatus(nsIWebBrowserChrome::STATUS_SCRIPT, msg.GetUnicode());
}
}
}
}
}
return rv;
}
NS_IMETHODIMP pluginInstanceOwner :: GetDocument(nsIDocument* *aDocument)
{
return mViewer->GetDocument(aDocument);
}
NS_IMETHODIMP pluginInstanceOwner :: Init(PluginViewerImpl *aViewer, nsIWidget *aWindow)
{
//do not addref
mWindow = aWindow;
mViewer = aViewer;
return NS_OK;
}