Moved from webshell/src
git-svn-id: svn://10.0.0.236/trunk@30557 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
parent
cec1954858
commit
969dad1d78
692
mozilla/content/base/src/nsDocumentViewer.cpp
Normal file
692
mozilla/content/base/src/nsDocumentViewer.cpp
Normal file
@ -0,0 +1,692 @@
|
||||
/* -*- 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.0 (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.
|
||||
*/
|
||||
#include "nslayout.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsCRT.h"
|
||||
#include "nsString.h"
|
||||
#include "nsISupports.h"
|
||||
#include "nsIContentViewerContainer.h"
|
||||
#include "nsIDocumentViewer.h"
|
||||
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIPresContext.h"
|
||||
#include "nsIPresShell.h"
|
||||
#include "nsIStyleSet.h"
|
||||
#include "nsIStyleSheet.h"
|
||||
#include "nsIFrame.h"
|
||||
|
||||
#include "nsIScriptContextOwner.h"
|
||||
#include "nsIScriptGlobalObject.h"
|
||||
#include "nsILinkHandler.h"
|
||||
#include "nsIDOMDocument.h"
|
||||
|
||||
#include "nsViewsCID.h"
|
||||
#include "nsWidgetsCID.h"
|
||||
#include "nsGfxCIID.h"
|
||||
#include "nsIDeviceContext.h"
|
||||
#include "nsIDeviceContextSpec.h"
|
||||
#include "nsIDeviceContextSpecFactory.h"
|
||||
#include "nsIViewManager.h"
|
||||
#include "nsIView.h"
|
||||
|
||||
#include "nsIPref.h"
|
||||
#include "nsIPageSequenceFrame.h"
|
||||
#include "nsIURL.h"
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
#undef NOISY_VIEWER
|
||||
#else
|
||||
#undef NOISY_VIEWER
|
||||
#endif
|
||||
|
||||
class DocumentViewerImpl : public nsIDocumentViewer
|
||||
{
|
||||
public:
|
||||
DocumentViewerImpl();
|
||||
DocumentViewerImpl(nsIPresContext* aPresContext);
|
||||
|
||||
NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW
|
||||
|
||||
// nsISupports interface...
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsIContentViewer interface...
|
||||
NS_IMETHOD Init(nsNativeWidget aParent,
|
||||
nsIDeviceContext* aDeviceContext,
|
||||
nsIPref* aPrefs,
|
||||
const nsRect& aBounds,
|
||||
nsScrollPreference aScrolling = nsScrollPreference_kAuto);
|
||||
NS_IMETHOD BindToDocument(nsISupports* aDoc, const char* aCommand);
|
||||
NS_IMETHOD SetContainer(nsIContentViewerContainer* aContainer);
|
||||
NS_IMETHOD GetContainer(nsIContentViewerContainer*& aContainerResult);
|
||||
NS_IMETHOD Stop(void);
|
||||
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 Print(void);
|
||||
|
||||
// nsIDocumentViewer interface...
|
||||
NS_IMETHOD SetUAStyleSheet(nsIStyleSheet* aUAStyleSheet);
|
||||
NS_IMETHOD GetDocument(nsIDocument*& aResult);
|
||||
NS_IMETHOD GetPresShell(nsIPresShell*& aResult);
|
||||
NS_IMETHOD GetPresContext(nsIPresContext*& aResult);
|
||||
NS_IMETHOD CreateDocumentViewerUsing(nsIPresContext* aPresContext,
|
||||
nsIDocumentViewer*& aResult);
|
||||
|
||||
protected:
|
||||
virtual ~DocumentViewerImpl();
|
||||
|
||||
private:
|
||||
void ForceRefresh(void);
|
||||
nsresult CreateStyleSet(nsIDocument* aDocument, nsIStyleSet** aStyleSet);
|
||||
nsresult MakeWindow(nsNativeWidget aNativeParent,
|
||||
const nsRect& aBounds,
|
||||
nsScrollPreference aScrolling);
|
||||
|
||||
protected:
|
||||
// IMPORTANT: The ownership implicit in the following member
|
||||
// variables has been explicitly checked and set using nsCOMPtr
|
||||
// for owning pointers and raw COM interface pointers for weak
|
||||
// (ie, non owning) references. If you add any members to this
|
||||
// class, please make the ownership explicit (pinkerton, scc).
|
||||
|
||||
nsIContentViewerContainer* mContainer; // [WEAK] it owns me!
|
||||
nsCOMPtr<nsIDeviceContext> mDeviceContext; // ??? can't hurt, but...
|
||||
nsIView* mView; // [WEAK] cleaned up by view mgr
|
||||
|
||||
// the following six items are explicitly in this order
|
||||
// so they will be destroyed in the reverse order (pinkerton, scc)
|
||||
nsCOMPtr<nsIDocument> mDocument;
|
||||
nsCOMPtr<nsIWidget> mWindow; // ??? should we really own it?
|
||||
nsCOMPtr<nsIViewManager> mViewManager;
|
||||
nsCOMPtr<nsIPresContext> mPresContext;
|
||||
nsCOMPtr<nsIPresShell> mPresShell;
|
||||
|
||||
nsCOMPtr<nsIStyleSheet> mUAStyleSheet;
|
||||
};
|
||||
|
||||
//Class IDs
|
||||
static NS_DEFINE_IID(kViewManagerCID, NS_VIEW_MANAGER_CID);
|
||||
static NS_DEFINE_IID(kScrollingViewCID, NS_SCROLLING_VIEW_CID);
|
||||
static NS_DEFINE_IID(kWidgetCID, NS_CHILD_CID);
|
||||
static NS_DEFINE_IID(kViewCID, NS_VIEW_CID);
|
||||
|
||||
|
||||
// Interface IDs
|
||||
static NS_DEFINE_IID(kIScriptContextOwnerIID, NS_ISCRIPTCONTEXTOWNER_IID);
|
||||
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
|
||||
static NS_DEFINE_IID(kIDocumentIID, NS_IDOCUMENT_IID);
|
||||
static NS_DEFINE_IID(kIDOMDocumentIID, NS_IDOMDOCUMENT_IID);
|
||||
static NS_DEFINE_IID(kIViewManagerIID, NS_IVIEWMANAGER_IID);
|
||||
static NS_DEFINE_IID(kIViewIID, NS_IVIEW_IID);
|
||||
static NS_DEFINE_IID(kScrollViewIID, NS_ISCROLLABLEVIEW_IID);
|
||||
static NS_DEFINE_IID(kIContentViewerIID, NS_ICONTENT_VIEWER_IID);
|
||||
static NS_DEFINE_IID(kIDocumentViewerIID, NS_IDOCUMENT_VIEWER_IID);
|
||||
static NS_DEFINE_IID(kILinkHandlerIID, NS_ILINKHANDLER_IID);
|
||||
|
||||
nsresult
|
||||
NS_NewDocumentViewer(nsIDocumentViewer** aResult)
|
||||
{
|
||||
NS_PRECONDITION(aResult, "null OUT ptr");
|
||||
if (!aResult) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
DocumentViewerImpl* it = new DocumentViewerImpl();
|
||||
if (nsnull == it) {
|
||||
*aResult = nsnull;
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
return it->QueryInterface(kIDocumentViewerIID, (void**) aResult);
|
||||
}
|
||||
|
||||
// Note: operator new zeros our memory
|
||||
DocumentViewerImpl::DocumentViewerImpl()
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
}
|
||||
|
||||
DocumentViewerImpl::DocumentViewerImpl(nsIPresContext* aPresContext)
|
||||
: mPresContext(dont_QueryInterface(aPresContext))
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
}
|
||||
|
||||
// ISupports implementation...
|
||||
NS_IMPL_ADDREF(DocumentViewerImpl)
|
||||
NS_IMPL_RELEASE(DocumentViewerImpl)
|
||||
|
||||
nsresult DocumentViewerImpl::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(kIDocumentViewerIID)) {
|
||||
nsIDocumentViewer* 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;
|
||||
}
|
||||
|
||||
|
||||
DocumentViewerImpl::~DocumentViewerImpl()
|
||||
{
|
||||
if (mDocument) {
|
||||
// Break global object circular reference on the document created
|
||||
// in the DocViewer Init
|
||||
nsIScriptContextOwner *mOwner = mDocument->GetScriptContextOwner();
|
||||
if (nsnull != mOwner) {
|
||||
nsIScriptGlobalObject *mGlobal;
|
||||
mOwner->GetScriptGlobalObject(&mGlobal);
|
||||
if (nsnull != mGlobal) {
|
||||
mGlobal->SetNewDocument(nsnull);
|
||||
NS_RELEASE(mGlobal);
|
||||
}
|
||||
NS_RELEASE(mOwner);
|
||||
|
||||
// out of band cleanup of webshell
|
||||
mDocument->SetScriptContextOwner(nsnull);
|
||||
}
|
||||
}
|
||||
|
||||
if (mDeviceContext)
|
||||
mDeviceContext->FlushFontCache();
|
||||
|
||||
if (mPresShell) {
|
||||
// Break circular reference (or something)
|
||||
mPresShell->EndObservingDocument();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 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
|
||||
DocumentViewerImpl::BindToDocument(nsISupports *aDoc, const char *aCommand)
|
||||
{
|
||||
NS_PRECONDITION(!mDocument, "Viewer is already bound to a document!");
|
||||
|
||||
#ifdef NOISY_VIEWER
|
||||
printf("DocumentViewerImpl::BindToDocument\n");
|
||||
#endif
|
||||
|
||||
nsresult rv;
|
||||
mDocument = do_QueryInterface(aDoc,&rv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
DocumentViewerImpl::SetContainer(nsIContentViewerContainer* aContainer)
|
||||
{
|
||||
mContainer = aContainer;
|
||||
if (mPresContext) {
|
||||
mPresContext->SetContainer(aContainer);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
DocumentViewerImpl::GetContainer(nsIContentViewerContainer*& aResult)
|
||||
{
|
||||
aResult = mContainer;
|
||||
NS_IF_ADDREF(aResult);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
DocumentViewerImpl::Init(nsNativeWidget aNativeParent,
|
||||
nsIDeviceContext* aDeviceContext,
|
||||
nsIPref* aPrefs,
|
||||
const nsRect& aBounds,
|
||||
nsScrollPreference aScrolling)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
if (!mDocument) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
mDeviceContext = dont_QueryInterface(aDeviceContext);
|
||||
|
||||
PRBool makeCX = PR_FALSE;
|
||||
if (!mPresContext) {
|
||||
// Create presentation context
|
||||
rv = NS_NewGalleyContext(getter_AddRefs(mPresContext));
|
||||
if (NS_OK != rv) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
mPresContext->Init(aDeviceContext, aPrefs);
|
||||
makeCX = PR_TRUE;
|
||||
}
|
||||
|
||||
if (nsnull != mContainer) {
|
||||
nsILinkHandler* linkHandler = nsnull;
|
||||
mContainer->QueryCapability(kILinkHandlerIID, (void**)&linkHandler);
|
||||
mPresContext->SetContainer(mContainer);
|
||||
mPresContext->SetLinkHandler(linkHandler);
|
||||
NS_IF_RELEASE(linkHandler);
|
||||
|
||||
// Set script-context-owner in the document
|
||||
nsIScriptContextOwner* owner = nsnull;
|
||||
mContainer->QueryCapability(kIScriptContextOwnerIID, (void**)&owner);
|
||||
if (nsnull != owner) {
|
||||
mDocument->SetScriptContextOwner(owner);
|
||||
nsIScriptGlobalObject* global;
|
||||
rv = owner->GetScriptGlobalObject(&global);
|
||||
if (NS_SUCCEEDED(rv) && (nsnull != global)) {
|
||||
nsIDOMDocument *domdoc = nsnull;
|
||||
mDocument->QueryInterface(kIDOMDocumentIID,
|
||||
(void**) &domdoc);
|
||||
if (nsnull != domdoc) {
|
||||
global->SetNewDocument(domdoc);
|
||||
NS_RELEASE(domdoc);
|
||||
}
|
||||
NS_RELEASE(global);
|
||||
}
|
||||
NS_RELEASE(owner);
|
||||
}
|
||||
}
|
||||
|
||||
// Create the ViewManager and Root View...
|
||||
MakeWindow(aNativeParent, aBounds, aScrolling);
|
||||
|
||||
// Create the style set...
|
||||
nsIStyleSet* styleSet;
|
||||
rv = CreateStyleSet(mDocument, &styleSet);
|
||||
if (NS_OK == rv) {
|
||||
// Now make the shell for the document
|
||||
rv = mDocument->CreateShell(mPresContext, mViewManager, styleSet,
|
||||
getter_AddRefs(mPresShell));
|
||||
NS_RELEASE(styleSet);
|
||||
if (NS_OK == rv) {
|
||||
// Initialize our view manager
|
||||
nsRect bounds;
|
||||
mWindow->GetBounds(bounds);
|
||||
nscoord width = bounds.width;
|
||||
nscoord height = bounds.height;
|
||||
float p2t;
|
||||
mPresContext->GetPixelsToTwips(&p2t);
|
||||
width = NSIntPixelsToTwips(width, p2t);
|
||||
height = NSIntPixelsToTwips(height, p2t);
|
||||
mViewManager->DisableRefresh();
|
||||
mViewManager->SetWindowDimensions(width, height);
|
||||
|
||||
if (!makeCX) {
|
||||
// Make shell an observer for next time
|
||||
mPresShell->BeginObservingDocument();
|
||||
|
||||
// Resize-reflow this time
|
||||
mPresShell->InitialReflow(width, height);
|
||||
|
||||
// Now trigger a refresh
|
||||
mViewManager->EnableRefresh();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
DocumentViewerImpl::Stop(void)
|
||||
{
|
||||
if (mPresContext) {
|
||||
mPresContext->Stop();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
DocumentViewerImpl::SetUAStyleSheet(nsIStyleSheet* aUAStyleSheet)
|
||||
{
|
||||
mUAStyleSheet = dont_QueryInterface(aUAStyleSheet);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
DocumentViewerImpl::GetDocument(nsIDocument*& aResult)
|
||||
{
|
||||
aResult = mDocument;
|
||||
NS_IF_ADDREF(aResult);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
DocumentViewerImpl::GetPresShell(nsIPresShell*& aResult)
|
||||
{
|
||||
aResult = mPresShell;
|
||||
NS_IF_ADDREF(aResult);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
DocumentViewerImpl::GetPresContext(nsIPresContext*& aResult)
|
||||
{
|
||||
aResult = mPresContext;
|
||||
NS_IF_ADDREF(aResult);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
DocumentViewerImpl::GetBounds(nsRect& aResult)
|
||||
{
|
||||
NS_PRECONDITION(mWindow, "null window");
|
||||
if (mWindow) {
|
||||
mWindow->GetBounds(aResult);
|
||||
}
|
||||
else {
|
||||
aResult.SetRect(0, 0, 0, 0);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
DocumentViewerImpl::SetBounds(const nsRect& aBounds)
|
||||
{
|
||||
NS_PRECONDITION(mWindow, "null window");
|
||||
if (mWindow) {
|
||||
// Don't have the widget repaint. Layout will generate repaint requests
|
||||
// during reflow
|
||||
mWindow->Resize(aBounds.x, aBounds.y, aBounds.width, aBounds.height,
|
||||
PR_FALSE);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
DocumentViewerImpl::Move(PRInt32 aX, PRInt32 aY)
|
||||
{
|
||||
NS_PRECONDITION(mWindow, "null window");
|
||||
if (mWindow) {
|
||||
mWindow->Move(aX, aY);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
DocumentViewerImpl::Show(void)
|
||||
{
|
||||
NS_PRECONDITION(mWindow, "null window");
|
||||
if (mWindow) {
|
||||
mWindow->Show(PR_TRUE);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
DocumentViewerImpl::Hide(void)
|
||||
{
|
||||
NS_PRECONDITION(mWindow, "null window");
|
||||
if (mWindow) {
|
||||
mWindow->Show(PR_FALSE);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
static NS_DEFINE_IID(kIDeviceContextSpecFactoryIID, NS_IDEVICE_CONTEXT_SPEC_FACTORY_IID);
|
||||
static NS_DEFINE_IID(kDeviceContextSpecFactoryCID, NS_DEVICE_CONTEXT_SPEC_FACTORY_CID);
|
||||
|
||||
NS_IMETHODIMP DocumentViewerImpl::Print(void)
|
||||
{
|
||||
nsIDeviceContextSpecFactory *factory = nsnull;
|
||||
|
||||
nsComponentManager::CreateInstance(kDeviceContextSpecFactoryCID, nsnull,
|
||||
kIDeviceContextSpecFactoryIID,
|
||||
(void **)&factory);
|
||||
|
||||
if (nsnull != factory)
|
||||
{
|
||||
nsIDeviceContextSpec *devspec = nsnull;
|
||||
nsCOMPtr<nsIDeviceContext> dx;
|
||||
nsIDeviceContext *newdx = nsnull;
|
||||
|
||||
factory->CreateDeviceContextSpec(nsnull, devspec, PR_FALSE);
|
||||
|
||||
if (nsnull != devspec) {
|
||||
mPresContext->GetDeviceContext(getter_AddRefs(dx));
|
||||
|
||||
if (NS_OK == dx->GetDeviceContextFor(devspec, newdx))
|
||||
{
|
||||
nsIPresShell *ps;
|
||||
nsIPresContext *cx;
|
||||
nsIStyleSet *ss;
|
||||
nsIPref *prefs;
|
||||
nsIViewManager *vm;
|
||||
PRInt32 width, height;
|
||||
nsIView *view;
|
||||
|
||||
NS_RELEASE(devspec);
|
||||
|
||||
newdx->BeginDocument();
|
||||
newdx->GetDeviceSurfaceDimensions(width, height);
|
||||
|
||||
NS_NewPrintContext(&cx);
|
||||
mPresContext->GetPrefs(&prefs);
|
||||
cx->Init(newdx, prefs);
|
||||
|
||||
CreateStyleSet(mDocument, &ss);
|
||||
|
||||
NS_NewPresShell(&ps);
|
||||
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
rv = nsComponentManager::CreateInstance(kViewManagerCID,
|
||||
nsnull,
|
||||
kIViewManagerIID,
|
||||
(void **)&vm);
|
||||
|
||||
if ((NS_OK != rv) || (NS_OK != vm->Init(newdx))) {
|
||||
NS_ASSERTION(PR_FALSE, "can't get good VM");
|
||||
}
|
||||
|
||||
nsRect tbounds = nsRect(0, 0, width, height);
|
||||
|
||||
// Create a child window of the parent that is our "root view/window"
|
||||
// Create a view
|
||||
rv = nsComponentManager::CreateInstance(kViewCID,
|
||||
nsnull,
|
||||
kIViewIID,
|
||||
(void **)&view);
|
||||
if ((NS_OK != rv) || (NS_OK != view->Init(vm,
|
||||
tbounds,
|
||||
nsnull))) {
|
||||
NS_ASSERTION(PR_FALSE, "can't get good view");
|
||||
}
|
||||
|
||||
// Setup hierarchical relationship in view manager
|
||||
vm->SetRootView(view);
|
||||
}
|
||||
|
||||
ps->Init(mDocument, cx, vm, ss);
|
||||
|
||||
//lay it out...
|
||||
//newdx->BeginDocument();
|
||||
ps->InitialReflow(width, height);
|
||||
|
||||
// Ask the page sequence frame to print all the pages
|
||||
nsIPageSequenceFrame* pageSequence;
|
||||
nsPrintOptions options;
|
||||
|
||||
ps->GetPageSequenceFrame(&pageSequence);
|
||||
NS_ASSERTION(nsnull != pageSequence, "no page sequence frame");
|
||||
pageSequence->Print(*cx, options, nsnull);
|
||||
newdx->EndDocument();
|
||||
|
||||
NS_RELEASE(ps);
|
||||
NS_RELEASE(vm);
|
||||
NS_RELEASE(ss);
|
||||
NS_RELEASE(newdx);
|
||||
NS_IF_RELEASE(prefs); // XXX why is the prefs null??
|
||||
}
|
||||
|
||||
}
|
||||
NS_RELEASE(factory);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void DocumentViewerImpl::ForceRefresh()
|
||||
{
|
||||
mWindow->Invalidate(PR_TRUE);
|
||||
}
|
||||
|
||||
nsresult
|
||||
DocumentViewerImpl::CreateStyleSet(nsIDocument* aDocument,
|
||||
nsIStyleSet** aStyleSet)
|
||||
{
|
||||
// this should eventually get expanded to allow for creating
|
||||
// different sets for different media
|
||||
nsresult rv;
|
||||
|
||||
if (!mUAStyleSheet) {
|
||||
NS_WARNING("unable to load UA style sheet");
|
||||
}
|
||||
|
||||
rv = NS_NewStyleSet(aStyleSet);
|
||||
if (NS_OK == rv) {
|
||||
PRInt32 index = aDocument->GetNumberOfStyleSheets();
|
||||
|
||||
while (0 < index--) {
|
||||
nsIStyleSheet* sheet = aDocument->GetStyleSheetAt(index);
|
||||
(*aStyleSet)->AddDocStyleSheet(sheet, aDocument);
|
||||
NS_RELEASE(sheet);
|
||||
}
|
||||
if (mUAStyleSheet) {
|
||||
(*aStyleSet)->AppendBackstopStyleSheet(mUAStyleSheet);
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
DocumentViewerImpl::MakeWindow(nsNativeWidget aNativeParent,
|
||||
const nsRect& aBounds,
|
||||
nsScrollPreference aScrolling)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
rv = nsComponentManager::CreateInstance(kViewManagerCID,
|
||||
nsnull,
|
||||
kIViewManagerIID,
|
||||
getter_AddRefs(mViewManager));
|
||||
|
||||
nsCOMPtr<nsIDeviceContext> dx;
|
||||
mPresContext->GetDeviceContext(getter_AddRefs(dx));
|
||||
|
||||
if ((NS_OK != rv) || (NS_OK != mViewManager->Init(dx))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsRect tbounds = aBounds;
|
||||
float p2t;
|
||||
mPresContext->GetPixelsToTwips(&p2t);
|
||||
tbounds *= p2t;
|
||||
|
||||
// Create a child window of the parent that is our "root view/window"
|
||||
// Create a view
|
||||
rv = nsComponentManager::CreateInstance(kViewCID,
|
||||
nsnull,
|
||||
kIViewIID,
|
||||
(void**)&mView);
|
||||
static NS_DEFINE_IID(kWidgetCID, NS_CHILD_CID);
|
||||
if ((NS_OK != rv) || (NS_OK != mView->Init(mViewManager,
|
||||
tbounds,
|
||||
nsnull))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = mView->CreateWidget(kWidgetCID, nsnull, aNativeParent);
|
||||
|
||||
if (rv != NS_OK)
|
||||
return rv;
|
||||
|
||||
// Setup hierarchical relationship in view manager
|
||||
mViewManager->SetRootView(mView);
|
||||
|
||||
mView->GetWidget(*getter_AddRefs(mWindow));
|
||||
|
||||
//set frame rate to 25 fps
|
||||
mViewManager->SetFrameRate(25);
|
||||
|
||||
// This SetFocus is necessary so the Arrow Key and Page Key events
|
||||
// go to the scrolled view as soon as the Window is created instead of going to
|
||||
// the browser window (this enables keyboard scrolling of the document)
|
||||
mWindow->SetFocus();
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
DocumentViewerImpl::CreateDocumentViewerUsing(nsIPresContext* aPresContext,
|
||||
nsIDocumentViewer*& aResult)
|
||||
{
|
||||
if (!mDocument) {
|
||||
// XXX better error
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
if (nsnull == aPresContext) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
// Create new viewer
|
||||
DocumentViewerImpl* viewer = new DocumentViewerImpl(aPresContext);
|
||||
if (nsnull == viewer) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
NS_ADDREF(viewer);
|
||||
|
||||
// XXX make sure the ua style sheet is used (for now; need to be
|
||||
// able to specify an alternate)
|
||||
viewer->SetUAStyleSheet(mUAStyleSheet);
|
||||
|
||||
// Bind the new viewer to the old document
|
||||
nsresult rv = viewer->BindToDocument(mDocument, "create");/* XXX verb? */
|
||||
|
||||
aResult = viewer;
|
||||
|
||||
return rv;
|
||||
}
|
||||
692
mozilla/layout/base/nsDocumentViewer.cpp
Normal file
692
mozilla/layout/base/nsDocumentViewer.cpp
Normal file
@ -0,0 +1,692 @@
|
||||
/* -*- 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.0 (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.
|
||||
*/
|
||||
#include "nslayout.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsCRT.h"
|
||||
#include "nsString.h"
|
||||
#include "nsISupports.h"
|
||||
#include "nsIContentViewerContainer.h"
|
||||
#include "nsIDocumentViewer.h"
|
||||
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIPresContext.h"
|
||||
#include "nsIPresShell.h"
|
||||
#include "nsIStyleSet.h"
|
||||
#include "nsIStyleSheet.h"
|
||||
#include "nsIFrame.h"
|
||||
|
||||
#include "nsIScriptContextOwner.h"
|
||||
#include "nsIScriptGlobalObject.h"
|
||||
#include "nsILinkHandler.h"
|
||||
#include "nsIDOMDocument.h"
|
||||
|
||||
#include "nsViewsCID.h"
|
||||
#include "nsWidgetsCID.h"
|
||||
#include "nsGfxCIID.h"
|
||||
#include "nsIDeviceContext.h"
|
||||
#include "nsIDeviceContextSpec.h"
|
||||
#include "nsIDeviceContextSpecFactory.h"
|
||||
#include "nsIViewManager.h"
|
||||
#include "nsIView.h"
|
||||
|
||||
#include "nsIPref.h"
|
||||
#include "nsIPageSequenceFrame.h"
|
||||
#include "nsIURL.h"
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
#undef NOISY_VIEWER
|
||||
#else
|
||||
#undef NOISY_VIEWER
|
||||
#endif
|
||||
|
||||
class DocumentViewerImpl : public nsIDocumentViewer
|
||||
{
|
||||
public:
|
||||
DocumentViewerImpl();
|
||||
DocumentViewerImpl(nsIPresContext* aPresContext);
|
||||
|
||||
NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW
|
||||
|
||||
// nsISupports interface...
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsIContentViewer interface...
|
||||
NS_IMETHOD Init(nsNativeWidget aParent,
|
||||
nsIDeviceContext* aDeviceContext,
|
||||
nsIPref* aPrefs,
|
||||
const nsRect& aBounds,
|
||||
nsScrollPreference aScrolling = nsScrollPreference_kAuto);
|
||||
NS_IMETHOD BindToDocument(nsISupports* aDoc, const char* aCommand);
|
||||
NS_IMETHOD SetContainer(nsIContentViewerContainer* aContainer);
|
||||
NS_IMETHOD GetContainer(nsIContentViewerContainer*& aContainerResult);
|
||||
NS_IMETHOD Stop(void);
|
||||
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 Print(void);
|
||||
|
||||
// nsIDocumentViewer interface...
|
||||
NS_IMETHOD SetUAStyleSheet(nsIStyleSheet* aUAStyleSheet);
|
||||
NS_IMETHOD GetDocument(nsIDocument*& aResult);
|
||||
NS_IMETHOD GetPresShell(nsIPresShell*& aResult);
|
||||
NS_IMETHOD GetPresContext(nsIPresContext*& aResult);
|
||||
NS_IMETHOD CreateDocumentViewerUsing(nsIPresContext* aPresContext,
|
||||
nsIDocumentViewer*& aResult);
|
||||
|
||||
protected:
|
||||
virtual ~DocumentViewerImpl();
|
||||
|
||||
private:
|
||||
void ForceRefresh(void);
|
||||
nsresult CreateStyleSet(nsIDocument* aDocument, nsIStyleSet** aStyleSet);
|
||||
nsresult MakeWindow(nsNativeWidget aNativeParent,
|
||||
const nsRect& aBounds,
|
||||
nsScrollPreference aScrolling);
|
||||
|
||||
protected:
|
||||
// IMPORTANT: The ownership implicit in the following member
|
||||
// variables has been explicitly checked and set using nsCOMPtr
|
||||
// for owning pointers and raw COM interface pointers for weak
|
||||
// (ie, non owning) references. If you add any members to this
|
||||
// class, please make the ownership explicit (pinkerton, scc).
|
||||
|
||||
nsIContentViewerContainer* mContainer; // [WEAK] it owns me!
|
||||
nsCOMPtr<nsIDeviceContext> mDeviceContext; // ??? can't hurt, but...
|
||||
nsIView* mView; // [WEAK] cleaned up by view mgr
|
||||
|
||||
// the following six items are explicitly in this order
|
||||
// so they will be destroyed in the reverse order (pinkerton, scc)
|
||||
nsCOMPtr<nsIDocument> mDocument;
|
||||
nsCOMPtr<nsIWidget> mWindow; // ??? should we really own it?
|
||||
nsCOMPtr<nsIViewManager> mViewManager;
|
||||
nsCOMPtr<nsIPresContext> mPresContext;
|
||||
nsCOMPtr<nsIPresShell> mPresShell;
|
||||
|
||||
nsCOMPtr<nsIStyleSheet> mUAStyleSheet;
|
||||
};
|
||||
|
||||
//Class IDs
|
||||
static NS_DEFINE_IID(kViewManagerCID, NS_VIEW_MANAGER_CID);
|
||||
static NS_DEFINE_IID(kScrollingViewCID, NS_SCROLLING_VIEW_CID);
|
||||
static NS_DEFINE_IID(kWidgetCID, NS_CHILD_CID);
|
||||
static NS_DEFINE_IID(kViewCID, NS_VIEW_CID);
|
||||
|
||||
|
||||
// Interface IDs
|
||||
static NS_DEFINE_IID(kIScriptContextOwnerIID, NS_ISCRIPTCONTEXTOWNER_IID);
|
||||
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
|
||||
static NS_DEFINE_IID(kIDocumentIID, NS_IDOCUMENT_IID);
|
||||
static NS_DEFINE_IID(kIDOMDocumentIID, NS_IDOMDOCUMENT_IID);
|
||||
static NS_DEFINE_IID(kIViewManagerIID, NS_IVIEWMANAGER_IID);
|
||||
static NS_DEFINE_IID(kIViewIID, NS_IVIEW_IID);
|
||||
static NS_DEFINE_IID(kScrollViewIID, NS_ISCROLLABLEVIEW_IID);
|
||||
static NS_DEFINE_IID(kIContentViewerIID, NS_ICONTENT_VIEWER_IID);
|
||||
static NS_DEFINE_IID(kIDocumentViewerIID, NS_IDOCUMENT_VIEWER_IID);
|
||||
static NS_DEFINE_IID(kILinkHandlerIID, NS_ILINKHANDLER_IID);
|
||||
|
||||
nsresult
|
||||
NS_NewDocumentViewer(nsIDocumentViewer** aResult)
|
||||
{
|
||||
NS_PRECONDITION(aResult, "null OUT ptr");
|
||||
if (!aResult) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
DocumentViewerImpl* it = new DocumentViewerImpl();
|
||||
if (nsnull == it) {
|
||||
*aResult = nsnull;
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
return it->QueryInterface(kIDocumentViewerIID, (void**) aResult);
|
||||
}
|
||||
|
||||
// Note: operator new zeros our memory
|
||||
DocumentViewerImpl::DocumentViewerImpl()
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
}
|
||||
|
||||
DocumentViewerImpl::DocumentViewerImpl(nsIPresContext* aPresContext)
|
||||
: mPresContext(dont_QueryInterface(aPresContext))
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
}
|
||||
|
||||
// ISupports implementation...
|
||||
NS_IMPL_ADDREF(DocumentViewerImpl)
|
||||
NS_IMPL_RELEASE(DocumentViewerImpl)
|
||||
|
||||
nsresult DocumentViewerImpl::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(kIDocumentViewerIID)) {
|
||||
nsIDocumentViewer* 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;
|
||||
}
|
||||
|
||||
|
||||
DocumentViewerImpl::~DocumentViewerImpl()
|
||||
{
|
||||
if (mDocument) {
|
||||
// Break global object circular reference on the document created
|
||||
// in the DocViewer Init
|
||||
nsIScriptContextOwner *mOwner = mDocument->GetScriptContextOwner();
|
||||
if (nsnull != mOwner) {
|
||||
nsIScriptGlobalObject *mGlobal;
|
||||
mOwner->GetScriptGlobalObject(&mGlobal);
|
||||
if (nsnull != mGlobal) {
|
||||
mGlobal->SetNewDocument(nsnull);
|
||||
NS_RELEASE(mGlobal);
|
||||
}
|
||||
NS_RELEASE(mOwner);
|
||||
|
||||
// out of band cleanup of webshell
|
||||
mDocument->SetScriptContextOwner(nsnull);
|
||||
}
|
||||
}
|
||||
|
||||
if (mDeviceContext)
|
||||
mDeviceContext->FlushFontCache();
|
||||
|
||||
if (mPresShell) {
|
||||
// Break circular reference (or something)
|
||||
mPresShell->EndObservingDocument();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 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
|
||||
DocumentViewerImpl::BindToDocument(nsISupports *aDoc, const char *aCommand)
|
||||
{
|
||||
NS_PRECONDITION(!mDocument, "Viewer is already bound to a document!");
|
||||
|
||||
#ifdef NOISY_VIEWER
|
||||
printf("DocumentViewerImpl::BindToDocument\n");
|
||||
#endif
|
||||
|
||||
nsresult rv;
|
||||
mDocument = do_QueryInterface(aDoc,&rv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
DocumentViewerImpl::SetContainer(nsIContentViewerContainer* aContainer)
|
||||
{
|
||||
mContainer = aContainer;
|
||||
if (mPresContext) {
|
||||
mPresContext->SetContainer(aContainer);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
DocumentViewerImpl::GetContainer(nsIContentViewerContainer*& aResult)
|
||||
{
|
||||
aResult = mContainer;
|
||||
NS_IF_ADDREF(aResult);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
DocumentViewerImpl::Init(nsNativeWidget aNativeParent,
|
||||
nsIDeviceContext* aDeviceContext,
|
||||
nsIPref* aPrefs,
|
||||
const nsRect& aBounds,
|
||||
nsScrollPreference aScrolling)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
if (!mDocument) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
mDeviceContext = dont_QueryInterface(aDeviceContext);
|
||||
|
||||
PRBool makeCX = PR_FALSE;
|
||||
if (!mPresContext) {
|
||||
// Create presentation context
|
||||
rv = NS_NewGalleyContext(getter_AddRefs(mPresContext));
|
||||
if (NS_OK != rv) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
mPresContext->Init(aDeviceContext, aPrefs);
|
||||
makeCX = PR_TRUE;
|
||||
}
|
||||
|
||||
if (nsnull != mContainer) {
|
||||
nsILinkHandler* linkHandler = nsnull;
|
||||
mContainer->QueryCapability(kILinkHandlerIID, (void**)&linkHandler);
|
||||
mPresContext->SetContainer(mContainer);
|
||||
mPresContext->SetLinkHandler(linkHandler);
|
||||
NS_IF_RELEASE(linkHandler);
|
||||
|
||||
// Set script-context-owner in the document
|
||||
nsIScriptContextOwner* owner = nsnull;
|
||||
mContainer->QueryCapability(kIScriptContextOwnerIID, (void**)&owner);
|
||||
if (nsnull != owner) {
|
||||
mDocument->SetScriptContextOwner(owner);
|
||||
nsIScriptGlobalObject* global;
|
||||
rv = owner->GetScriptGlobalObject(&global);
|
||||
if (NS_SUCCEEDED(rv) && (nsnull != global)) {
|
||||
nsIDOMDocument *domdoc = nsnull;
|
||||
mDocument->QueryInterface(kIDOMDocumentIID,
|
||||
(void**) &domdoc);
|
||||
if (nsnull != domdoc) {
|
||||
global->SetNewDocument(domdoc);
|
||||
NS_RELEASE(domdoc);
|
||||
}
|
||||
NS_RELEASE(global);
|
||||
}
|
||||
NS_RELEASE(owner);
|
||||
}
|
||||
}
|
||||
|
||||
// Create the ViewManager and Root View...
|
||||
MakeWindow(aNativeParent, aBounds, aScrolling);
|
||||
|
||||
// Create the style set...
|
||||
nsIStyleSet* styleSet;
|
||||
rv = CreateStyleSet(mDocument, &styleSet);
|
||||
if (NS_OK == rv) {
|
||||
// Now make the shell for the document
|
||||
rv = mDocument->CreateShell(mPresContext, mViewManager, styleSet,
|
||||
getter_AddRefs(mPresShell));
|
||||
NS_RELEASE(styleSet);
|
||||
if (NS_OK == rv) {
|
||||
// Initialize our view manager
|
||||
nsRect bounds;
|
||||
mWindow->GetBounds(bounds);
|
||||
nscoord width = bounds.width;
|
||||
nscoord height = bounds.height;
|
||||
float p2t;
|
||||
mPresContext->GetPixelsToTwips(&p2t);
|
||||
width = NSIntPixelsToTwips(width, p2t);
|
||||
height = NSIntPixelsToTwips(height, p2t);
|
||||
mViewManager->DisableRefresh();
|
||||
mViewManager->SetWindowDimensions(width, height);
|
||||
|
||||
if (!makeCX) {
|
||||
// Make shell an observer for next time
|
||||
mPresShell->BeginObservingDocument();
|
||||
|
||||
// Resize-reflow this time
|
||||
mPresShell->InitialReflow(width, height);
|
||||
|
||||
// Now trigger a refresh
|
||||
mViewManager->EnableRefresh();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
DocumentViewerImpl::Stop(void)
|
||||
{
|
||||
if (mPresContext) {
|
||||
mPresContext->Stop();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
DocumentViewerImpl::SetUAStyleSheet(nsIStyleSheet* aUAStyleSheet)
|
||||
{
|
||||
mUAStyleSheet = dont_QueryInterface(aUAStyleSheet);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
DocumentViewerImpl::GetDocument(nsIDocument*& aResult)
|
||||
{
|
||||
aResult = mDocument;
|
||||
NS_IF_ADDREF(aResult);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
DocumentViewerImpl::GetPresShell(nsIPresShell*& aResult)
|
||||
{
|
||||
aResult = mPresShell;
|
||||
NS_IF_ADDREF(aResult);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
DocumentViewerImpl::GetPresContext(nsIPresContext*& aResult)
|
||||
{
|
||||
aResult = mPresContext;
|
||||
NS_IF_ADDREF(aResult);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
DocumentViewerImpl::GetBounds(nsRect& aResult)
|
||||
{
|
||||
NS_PRECONDITION(mWindow, "null window");
|
||||
if (mWindow) {
|
||||
mWindow->GetBounds(aResult);
|
||||
}
|
||||
else {
|
||||
aResult.SetRect(0, 0, 0, 0);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
DocumentViewerImpl::SetBounds(const nsRect& aBounds)
|
||||
{
|
||||
NS_PRECONDITION(mWindow, "null window");
|
||||
if (mWindow) {
|
||||
// Don't have the widget repaint. Layout will generate repaint requests
|
||||
// during reflow
|
||||
mWindow->Resize(aBounds.x, aBounds.y, aBounds.width, aBounds.height,
|
||||
PR_FALSE);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
DocumentViewerImpl::Move(PRInt32 aX, PRInt32 aY)
|
||||
{
|
||||
NS_PRECONDITION(mWindow, "null window");
|
||||
if (mWindow) {
|
||||
mWindow->Move(aX, aY);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
DocumentViewerImpl::Show(void)
|
||||
{
|
||||
NS_PRECONDITION(mWindow, "null window");
|
||||
if (mWindow) {
|
||||
mWindow->Show(PR_TRUE);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
DocumentViewerImpl::Hide(void)
|
||||
{
|
||||
NS_PRECONDITION(mWindow, "null window");
|
||||
if (mWindow) {
|
||||
mWindow->Show(PR_FALSE);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
static NS_DEFINE_IID(kIDeviceContextSpecFactoryIID, NS_IDEVICE_CONTEXT_SPEC_FACTORY_IID);
|
||||
static NS_DEFINE_IID(kDeviceContextSpecFactoryCID, NS_DEVICE_CONTEXT_SPEC_FACTORY_CID);
|
||||
|
||||
NS_IMETHODIMP DocumentViewerImpl::Print(void)
|
||||
{
|
||||
nsIDeviceContextSpecFactory *factory = nsnull;
|
||||
|
||||
nsComponentManager::CreateInstance(kDeviceContextSpecFactoryCID, nsnull,
|
||||
kIDeviceContextSpecFactoryIID,
|
||||
(void **)&factory);
|
||||
|
||||
if (nsnull != factory)
|
||||
{
|
||||
nsIDeviceContextSpec *devspec = nsnull;
|
||||
nsCOMPtr<nsIDeviceContext> dx;
|
||||
nsIDeviceContext *newdx = nsnull;
|
||||
|
||||
factory->CreateDeviceContextSpec(nsnull, devspec, PR_FALSE);
|
||||
|
||||
if (nsnull != devspec) {
|
||||
mPresContext->GetDeviceContext(getter_AddRefs(dx));
|
||||
|
||||
if (NS_OK == dx->GetDeviceContextFor(devspec, newdx))
|
||||
{
|
||||
nsIPresShell *ps;
|
||||
nsIPresContext *cx;
|
||||
nsIStyleSet *ss;
|
||||
nsIPref *prefs;
|
||||
nsIViewManager *vm;
|
||||
PRInt32 width, height;
|
||||
nsIView *view;
|
||||
|
||||
NS_RELEASE(devspec);
|
||||
|
||||
newdx->BeginDocument();
|
||||
newdx->GetDeviceSurfaceDimensions(width, height);
|
||||
|
||||
NS_NewPrintContext(&cx);
|
||||
mPresContext->GetPrefs(&prefs);
|
||||
cx->Init(newdx, prefs);
|
||||
|
||||
CreateStyleSet(mDocument, &ss);
|
||||
|
||||
NS_NewPresShell(&ps);
|
||||
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
rv = nsComponentManager::CreateInstance(kViewManagerCID,
|
||||
nsnull,
|
||||
kIViewManagerIID,
|
||||
(void **)&vm);
|
||||
|
||||
if ((NS_OK != rv) || (NS_OK != vm->Init(newdx))) {
|
||||
NS_ASSERTION(PR_FALSE, "can't get good VM");
|
||||
}
|
||||
|
||||
nsRect tbounds = nsRect(0, 0, width, height);
|
||||
|
||||
// Create a child window of the parent that is our "root view/window"
|
||||
// Create a view
|
||||
rv = nsComponentManager::CreateInstance(kViewCID,
|
||||
nsnull,
|
||||
kIViewIID,
|
||||
(void **)&view);
|
||||
if ((NS_OK != rv) || (NS_OK != view->Init(vm,
|
||||
tbounds,
|
||||
nsnull))) {
|
||||
NS_ASSERTION(PR_FALSE, "can't get good view");
|
||||
}
|
||||
|
||||
// Setup hierarchical relationship in view manager
|
||||
vm->SetRootView(view);
|
||||
}
|
||||
|
||||
ps->Init(mDocument, cx, vm, ss);
|
||||
|
||||
//lay it out...
|
||||
//newdx->BeginDocument();
|
||||
ps->InitialReflow(width, height);
|
||||
|
||||
// Ask the page sequence frame to print all the pages
|
||||
nsIPageSequenceFrame* pageSequence;
|
||||
nsPrintOptions options;
|
||||
|
||||
ps->GetPageSequenceFrame(&pageSequence);
|
||||
NS_ASSERTION(nsnull != pageSequence, "no page sequence frame");
|
||||
pageSequence->Print(*cx, options, nsnull);
|
||||
newdx->EndDocument();
|
||||
|
||||
NS_RELEASE(ps);
|
||||
NS_RELEASE(vm);
|
||||
NS_RELEASE(ss);
|
||||
NS_RELEASE(newdx);
|
||||
NS_IF_RELEASE(prefs); // XXX why is the prefs null??
|
||||
}
|
||||
|
||||
}
|
||||
NS_RELEASE(factory);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void DocumentViewerImpl::ForceRefresh()
|
||||
{
|
||||
mWindow->Invalidate(PR_TRUE);
|
||||
}
|
||||
|
||||
nsresult
|
||||
DocumentViewerImpl::CreateStyleSet(nsIDocument* aDocument,
|
||||
nsIStyleSet** aStyleSet)
|
||||
{
|
||||
// this should eventually get expanded to allow for creating
|
||||
// different sets for different media
|
||||
nsresult rv;
|
||||
|
||||
if (!mUAStyleSheet) {
|
||||
NS_WARNING("unable to load UA style sheet");
|
||||
}
|
||||
|
||||
rv = NS_NewStyleSet(aStyleSet);
|
||||
if (NS_OK == rv) {
|
||||
PRInt32 index = aDocument->GetNumberOfStyleSheets();
|
||||
|
||||
while (0 < index--) {
|
||||
nsIStyleSheet* sheet = aDocument->GetStyleSheetAt(index);
|
||||
(*aStyleSet)->AddDocStyleSheet(sheet, aDocument);
|
||||
NS_RELEASE(sheet);
|
||||
}
|
||||
if (mUAStyleSheet) {
|
||||
(*aStyleSet)->AppendBackstopStyleSheet(mUAStyleSheet);
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
DocumentViewerImpl::MakeWindow(nsNativeWidget aNativeParent,
|
||||
const nsRect& aBounds,
|
||||
nsScrollPreference aScrolling)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
rv = nsComponentManager::CreateInstance(kViewManagerCID,
|
||||
nsnull,
|
||||
kIViewManagerIID,
|
||||
getter_AddRefs(mViewManager));
|
||||
|
||||
nsCOMPtr<nsIDeviceContext> dx;
|
||||
mPresContext->GetDeviceContext(getter_AddRefs(dx));
|
||||
|
||||
if ((NS_OK != rv) || (NS_OK != mViewManager->Init(dx))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsRect tbounds = aBounds;
|
||||
float p2t;
|
||||
mPresContext->GetPixelsToTwips(&p2t);
|
||||
tbounds *= p2t;
|
||||
|
||||
// Create a child window of the parent that is our "root view/window"
|
||||
// Create a view
|
||||
rv = nsComponentManager::CreateInstance(kViewCID,
|
||||
nsnull,
|
||||
kIViewIID,
|
||||
(void**)&mView);
|
||||
static NS_DEFINE_IID(kWidgetCID, NS_CHILD_CID);
|
||||
if ((NS_OK != rv) || (NS_OK != mView->Init(mViewManager,
|
||||
tbounds,
|
||||
nsnull))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = mView->CreateWidget(kWidgetCID, nsnull, aNativeParent);
|
||||
|
||||
if (rv != NS_OK)
|
||||
return rv;
|
||||
|
||||
// Setup hierarchical relationship in view manager
|
||||
mViewManager->SetRootView(mView);
|
||||
|
||||
mView->GetWidget(*getter_AddRefs(mWindow));
|
||||
|
||||
//set frame rate to 25 fps
|
||||
mViewManager->SetFrameRate(25);
|
||||
|
||||
// This SetFocus is necessary so the Arrow Key and Page Key events
|
||||
// go to the scrolled view as soon as the Window is created instead of going to
|
||||
// the browser window (this enables keyboard scrolling of the document)
|
||||
mWindow->SetFocus();
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
DocumentViewerImpl::CreateDocumentViewerUsing(nsIPresContext* aPresContext,
|
||||
nsIDocumentViewer*& aResult)
|
||||
{
|
||||
if (!mDocument) {
|
||||
// XXX better error
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
if (nsnull == aPresContext) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
// Create new viewer
|
||||
DocumentViewerImpl* viewer = new DocumentViewerImpl(aPresContext);
|
||||
if (nsnull == viewer) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
NS_ADDREF(viewer);
|
||||
|
||||
// XXX make sure the ua style sheet is used (for now; need to be
|
||||
// able to specify an alternate)
|
||||
viewer->SetUAStyleSheet(mUAStyleSheet);
|
||||
|
||||
// Bind the new viewer to the old document
|
||||
nsresult rv = viewer->BindToDocument(mDocument, "create");/* XXX verb? */
|
||||
|
||||
aResult = viewer;
|
||||
|
||||
return rv;
|
||||
}
|
||||
692
mozilla/layout/base/src/nsDocumentViewer.cpp
Normal file
692
mozilla/layout/base/src/nsDocumentViewer.cpp
Normal file
@ -0,0 +1,692 @@
|
||||
/* -*- 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.0 (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.
|
||||
*/
|
||||
#include "nslayout.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsCRT.h"
|
||||
#include "nsString.h"
|
||||
#include "nsISupports.h"
|
||||
#include "nsIContentViewerContainer.h"
|
||||
#include "nsIDocumentViewer.h"
|
||||
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIPresContext.h"
|
||||
#include "nsIPresShell.h"
|
||||
#include "nsIStyleSet.h"
|
||||
#include "nsIStyleSheet.h"
|
||||
#include "nsIFrame.h"
|
||||
|
||||
#include "nsIScriptContextOwner.h"
|
||||
#include "nsIScriptGlobalObject.h"
|
||||
#include "nsILinkHandler.h"
|
||||
#include "nsIDOMDocument.h"
|
||||
|
||||
#include "nsViewsCID.h"
|
||||
#include "nsWidgetsCID.h"
|
||||
#include "nsGfxCIID.h"
|
||||
#include "nsIDeviceContext.h"
|
||||
#include "nsIDeviceContextSpec.h"
|
||||
#include "nsIDeviceContextSpecFactory.h"
|
||||
#include "nsIViewManager.h"
|
||||
#include "nsIView.h"
|
||||
|
||||
#include "nsIPref.h"
|
||||
#include "nsIPageSequenceFrame.h"
|
||||
#include "nsIURL.h"
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
#undef NOISY_VIEWER
|
||||
#else
|
||||
#undef NOISY_VIEWER
|
||||
#endif
|
||||
|
||||
class DocumentViewerImpl : public nsIDocumentViewer
|
||||
{
|
||||
public:
|
||||
DocumentViewerImpl();
|
||||
DocumentViewerImpl(nsIPresContext* aPresContext);
|
||||
|
||||
NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW
|
||||
|
||||
// nsISupports interface...
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsIContentViewer interface...
|
||||
NS_IMETHOD Init(nsNativeWidget aParent,
|
||||
nsIDeviceContext* aDeviceContext,
|
||||
nsIPref* aPrefs,
|
||||
const nsRect& aBounds,
|
||||
nsScrollPreference aScrolling = nsScrollPreference_kAuto);
|
||||
NS_IMETHOD BindToDocument(nsISupports* aDoc, const char* aCommand);
|
||||
NS_IMETHOD SetContainer(nsIContentViewerContainer* aContainer);
|
||||
NS_IMETHOD GetContainer(nsIContentViewerContainer*& aContainerResult);
|
||||
NS_IMETHOD Stop(void);
|
||||
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 Print(void);
|
||||
|
||||
// nsIDocumentViewer interface...
|
||||
NS_IMETHOD SetUAStyleSheet(nsIStyleSheet* aUAStyleSheet);
|
||||
NS_IMETHOD GetDocument(nsIDocument*& aResult);
|
||||
NS_IMETHOD GetPresShell(nsIPresShell*& aResult);
|
||||
NS_IMETHOD GetPresContext(nsIPresContext*& aResult);
|
||||
NS_IMETHOD CreateDocumentViewerUsing(nsIPresContext* aPresContext,
|
||||
nsIDocumentViewer*& aResult);
|
||||
|
||||
protected:
|
||||
virtual ~DocumentViewerImpl();
|
||||
|
||||
private:
|
||||
void ForceRefresh(void);
|
||||
nsresult CreateStyleSet(nsIDocument* aDocument, nsIStyleSet** aStyleSet);
|
||||
nsresult MakeWindow(nsNativeWidget aNativeParent,
|
||||
const nsRect& aBounds,
|
||||
nsScrollPreference aScrolling);
|
||||
|
||||
protected:
|
||||
// IMPORTANT: The ownership implicit in the following member
|
||||
// variables has been explicitly checked and set using nsCOMPtr
|
||||
// for owning pointers and raw COM interface pointers for weak
|
||||
// (ie, non owning) references. If you add any members to this
|
||||
// class, please make the ownership explicit (pinkerton, scc).
|
||||
|
||||
nsIContentViewerContainer* mContainer; // [WEAK] it owns me!
|
||||
nsCOMPtr<nsIDeviceContext> mDeviceContext; // ??? can't hurt, but...
|
||||
nsIView* mView; // [WEAK] cleaned up by view mgr
|
||||
|
||||
// the following six items are explicitly in this order
|
||||
// so they will be destroyed in the reverse order (pinkerton, scc)
|
||||
nsCOMPtr<nsIDocument> mDocument;
|
||||
nsCOMPtr<nsIWidget> mWindow; // ??? should we really own it?
|
||||
nsCOMPtr<nsIViewManager> mViewManager;
|
||||
nsCOMPtr<nsIPresContext> mPresContext;
|
||||
nsCOMPtr<nsIPresShell> mPresShell;
|
||||
|
||||
nsCOMPtr<nsIStyleSheet> mUAStyleSheet;
|
||||
};
|
||||
|
||||
//Class IDs
|
||||
static NS_DEFINE_IID(kViewManagerCID, NS_VIEW_MANAGER_CID);
|
||||
static NS_DEFINE_IID(kScrollingViewCID, NS_SCROLLING_VIEW_CID);
|
||||
static NS_DEFINE_IID(kWidgetCID, NS_CHILD_CID);
|
||||
static NS_DEFINE_IID(kViewCID, NS_VIEW_CID);
|
||||
|
||||
|
||||
// Interface IDs
|
||||
static NS_DEFINE_IID(kIScriptContextOwnerIID, NS_ISCRIPTCONTEXTOWNER_IID);
|
||||
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
|
||||
static NS_DEFINE_IID(kIDocumentIID, NS_IDOCUMENT_IID);
|
||||
static NS_DEFINE_IID(kIDOMDocumentIID, NS_IDOMDOCUMENT_IID);
|
||||
static NS_DEFINE_IID(kIViewManagerIID, NS_IVIEWMANAGER_IID);
|
||||
static NS_DEFINE_IID(kIViewIID, NS_IVIEW_IID);
|
||||
static NS_DEFINE_IID(kScrollViewIID, NS_ISCROLLABLEVIEW_IID);
|
||||
static NS_DEFINE_IID(kIContentViewerIID, NS_ICONTENT_VIEWER_IID);
|
||||
static NS_DEFINE_IID(kIDocumentViewerIID, NS_IDOCUMENT_VIEWER_IID);
|
||||
static NS_DEFINE_IID(kILinkHandlerIID, NS_ILINKHANDLER_IID);
|
||||
|
||||
nsresult
|
||||
NS_NewDocumentViewer(nsIDocumentViewer** aResult)
|
||||
{
|
||||
NS_PRECONDITION(aResult, "null OUT ptr");
|
||||
if (!aResult) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
DocumentViewerImpl* it = new DocumentViewerImpl();
|
||||
if (nsnull == it) {
|
||||
*aResult = nsnull;
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
return it->QueryInterface(kIDocumentViewerIID, (void**) aResult);
|
||||
}
|
||||
|
||||
// Note: operator new zeros our memory
|
||||
DocumentViewerImpl::DocumentViewerImpl()
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
}
|
||||
|
||||
DocumentViewerImpl::DocumentViewerImpl(nsIPresContext* aPresContext)
|
||||
: mPresContext(dont_QueryInterface(aPresContext))
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
}
|
||||
|
||||
// ISupports implementation...
|
||||
NS_IMPL_ADDREF(DocumentViewerImpl)
|
||||
NS_IMPL_RELEASE(DocumentViewerImpl)
|
||||
|
||||
nsresult DocumentViewerImpl::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(kIDocumentViewerIID)) {
|
||||
nsIDocumentViewer* 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;
|
||||
}
|
||||
|
||||
|
||||
DocumentViewerImpl::~DocumentViewerImpl()
|
||||
{
|
||||
if (mDocument) {
|
||||
// Break global object circular reference on the document created
|
||||
// in the DocViewer Init
|
||||
nsIScriptContextOwner *mOwner = mDocument->GetScriptContextOwner();
|
||||
if (nsnull != mOwner) {
|
||||
nsIScriptGlobalObject *mGlobal;
|
||||
mOwner->GetScriptGlobalObject(&mGlobal);
|
||||
if (nsnull != mGlobal) {
|
||||
mGlobal->SetNewDocument(nsnull);
|
||||
NS_RELEASE(mGlobal);
|
||||
}
|
||||
NS_RELEASE(mOwner);
|
||||
|
||||
// out of band cleanup of webshell
|
||||
mDocument->SetScriptContextOwner(nsnull);
|
||||
}
|
||||
}
|
||||
|
||||
if (mDeviceContext)
|
||||
mDeviceContext->FlushFontCache();
|
||||
|
||||
if (mPresShell) {
|
||||
// Break circular reference (or something)
|
||||
mPresShell->EndObservingDocument();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 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
|
||||
DocumentViewerImpl::BindToDocument(nsISupports *aDoc, const char *aCommand)
|
||||
{
|
||||
NS_PRECONDITION(!mDocument, "Viewer is already bound to a document!");
|
||||
|
||||
#ifdef NOISY_VIEWER
|
||||
printf("DocumentViewerImpl::BindToDocument\n");
|
||||
#endif
|
||||
|
||||
nsresult rv;
|
||||
mDocument = do_QueryInterface(aDoc,&rv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
DocumentViewerImpl::SetContainer(nsIContentViewerContainer* aContainer)
|
||||
{
|
||||
mContainer = aContainer;
|
||||
if (mPresContext) {
|
||||
mPresContext->SetContainer(aContainer);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
DocumentViewerImpl::GetContainer(nsIContentViewerContainer*& aResult)
|
||||
{
|
||||
aResult = mContainer;
|
||||
NS_IF_ADDREF(aResult);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
DocumentViewerImpl::Init(nsNativeWidget aNativeParent,
|
||||
nsIDeviceContext* aDeviceContext,
|
||||
nsIPref* aPrefs,
|
||||
const nsRect& aBounds,
|
||||
nsScrollPreference aScrolling)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
if (!mDocument) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
mDeviceContext = dont_QueryInterface(aDeviceContext);
|
||||
|
||||
PRBool makeCX = PR_FALSE;
|
||||
if (!mPresContext) {
|
||||
// Create presentation context
|
||||
rv = NS_NewGalleyContext(getter_AddRefs(mPresContext));
|
||||
if (NS_OK != rv) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
mPresContext->Init(aDeviceContext, aPrefs);
|
||||
makeCX = PR_TRUE;
|
||||
}
|
||||
|
||||
if (nsnull != mContainer) {
|
||||
nsILinkHandler* linkHandler = nsnull;
|
||||
mContainer->QueryCapability(kILinkHandlerIID, (void**)&linkHandler);
|
||||
mPresContext->SetContainer(mContainer);
|
||||
mPresContext->SetLinkHandler(linkHandler);
|
||||
NS_IF_RELEASE(linkHandler);
|
||||
|
||||
// Set script-context-owner in the document
|
||||
nsIScriptContextOwner* owner = nsnull;
|
||||
mContainer->QueryCapability(kIScriptContextOwnerIID, (void**)&owner);
|
||||
if (nsnull != owner) {
|
||||
mDocument->SetScriptContextOwner(owner);
|
||||
nsIScriptGlobalObject* global;
|
||||
rv = owner->GetScriptGlobalObject(&global);
|
||||
if (NS_SUCCEEDED(rv) && (nsnull != global)) {
|
||||
nsIDOMDocument *domdoc = nsnull;
|
||||
mDocument->QueryInterface(kIDOMDocumentIID,
|
||||
(void**) &domdoc);
|
||||
if (nsnull != domdoc) {
|
||||
global->SetNewDocument(domdoc);
|
||||
NS_RELEASE(domdoc);
|
||||
}
|
||||
NS_RELEASE(global);
|
||||
}
|
||||
NS_RELEASE(owner);
|
||||
}
|
||||
}
|
||||
|
||||
// Create the ViewManager and Root View...
|
||||
MakeWindow(aNativeParent, aBounds, aScrolling);
|
||||
|
||||
// Create the style set...
|
||||
nsIStyleSet* styleSet;
|
||||
rv = CreateStyleSet(mDocument, &styleSet);
|
||||
if (NS_OK == rv) {
|
||||
// Now make the shell for the document
|
||||
rv = mDocument->CreateShell(mPresContext, mViewManager, styleSet,
|
||||
getter_AddRefs(mPresShell));
|
||||
NS_RELEASE(styleSet);
|
||||
if (NS_OK == rv) {
|
||||
// Initialize our view manager
|
||||
nsRect bounds;
|
||||
mWindow->GetBounds(bounds);
|
||||
nscoord width = bounds.width;
|
||||
nscoord height = bounds.height;
|
||||
float p2t;
|
||||
mPresContext->GetPixelsToTwips(&p2t);
|
||||
width = NSIntPixelsToTwips(width, p2t);
|
||||
height = NSIntPixelsToTwips(height, p2t);
|
||||
mViewManager->DisableRefresh();
|
||||
mViewManager->SetWindowDimensions(width, height);
|
||||
|
||||
if (!makeCX) {
|
||||
// Make shell an observer for next time
|
||||
mPresShell->BeginObservingDocument();
|
||||
|
||||
// Resize-reflow this time
|
||||
mPresShell->InitialReflow(width, height);
|
||||
|
||||
// Now trigger a refresh
|
||||
mViewManager->EnableRefresh();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
DocumentViewerImpl::Stop(void)
|
||||
{
|
||||
if (mPresContext) {
|
||||
mPresContext->Stop();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
DocumentViewerImpl::SetUAStyleSheet(nsIStyleSheet* aUAStyleSheet)
|
||||
{
|
||||
mUAStyleSheet = dont_QueryInterface(aUAStyleSheet);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
DocumentViewerImpl::GetDocument(nsIDocument*& aResult)
|
||||
{
|
||||
aResult = mDocument;
|
||||
NS_IF_ADDREF(aResult);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
DocumentViewerImpl::GetPresShell(nsIPresShell*& aResult)
|
||||
{
|
||||
aResult = mPresShell;
|
||||
NS_IF_ADDREF(aResult);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
DocumentViewerImpl::GetPresContext(nsIPresContext*& aResult)
|
||||
{
|
||||
aResult = mPresContext;
|
||||
NS_IF_ADDREF(aResult);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
DocumentViewerImpl::GetBounds(nsRect& aResult)
|
||||
{
|
||||
NS_PRECONDITION(mWindow, "null window");
|
||||
if (mWindow) {
|
||||
mWindow->GetBounds(aResult);
|
||||
}
|
||||
else {
|
||||
aResult.SetRect(0, 0, 0, 0);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
DocumentViewerImpl::SetBounds(const nsRect& aBounds)
|
||||
{
|
||||
NS_PRECONDITION(mWindow, "null window");
|
||||
if (mWindow) {
|
||||
// Don't have the widget repaint. Layout will generate repaint requests
|
||||
// during reflow
|
||||
mWindow->Resize(aBounds.x, aBounds.y, aBounds.width, aBounds.height,
|
||||
PR_FALSE);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
DocumentViewerImpl::Move(PRInt32 aX, PRInt32 aY)
|
||||
{
|
||||
NS_PRECONDITION(mWindow, "null window");
|
||||
if (mWindow) {
|
||||
mWindow->Move(aX, aY);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
DocumentViewerImpl::Show(void)
|
||||
{
|
||||
NS_PRECONDITION(mWindow, "null window");
|
||||
if (mWindow) {
|
||||
mWindow->Show(PR_TRUE);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
DocumentViewerImpl::Hide(void)
|
||||
{
|
||||
NS_PRECONDITION(mWindow, "null window");
|
||||
if (mWindow) {
|
||||
mWindow->Show(PR_FALSE);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
static NS_DEFINE_IID(kIDeviceContextSpecFactoryIID, NS_IDEVICE_CONTEXT_SPEC_FACTORY_IID);
|
||||
static NS_DEFINE_IID(kDeviceContextSpecFactoryCID, NS_DEVICE_CONTEXT_SPEC_FACTORY_CID);
|
||||
|
||||
NS_IMETHODIMP DocumentViewerImpl::Print(void)
|
||||
{
|
||||
nsIDeviceContextSpecFactory *factory = nsnull;
|
||||
|
||||
nsComponentManager::CreateInstance(kDeviceContextSpecFactoryCID, nsnull,
|
||||
kIDeviceContextSpecFactoryIID,
|
||||
(void **)&factory);
|
||||
|
||||
if (nsnull != factory)
|
||||
{
|
||||
nsIDeviceContextSpec *devspec = nsnull;
|
||||
nsCOMPtr<nsIDeviceContext> dx;
|
||||
nsIDeviceContext *newdx = nsnull;
|
||||
|
||||
factory->CreateDeviceContextSpec(nsnull, devspec, PR_FALSE);
|
||||
|
||||
if (nsnull != devspec) {
|
||||
mPresContext->GetDeviceContext(getter_AddRefs(dx));
|
||||
|
||||
if (NS_OK == dx->GetDeviceContextFor(devspec, newdx))
|
||||
{
|
||||
nsIPresShell *ps;
|
||||
nsIPresContext *cx;
|
||||
nsIStyleSet *ss;
|
||||
nsIPref *prefs;
|
||||
nsIViewManager *vm;
|
||||
PRInt32 width, height;
|
||||
nsIView *view;
|
||||
|
||||
NS_RELEASE(devspec);
|
||||
|
||||
newdx->BeginDocument();
|
||||
newdx->GetDeviceSurfaceDimensions(width, height);
|
||||
|
||||
NS_NewPrintContext(&cx);
|
||||
mPresContext->GetPrefs(&prefs);
|
||||
cx->Init(newdx, prefs);
|
||||
|
||||
CreateStyleSet(mDocument, &ss);
|
||||
|
||||
NS_NewPresShell(&ps);
|
||||
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
rv = nsComponentManager::CreateInstance(kViewManagerCID,
|
||||
nsnull,
|
||||
kIViewManagerIID,
|
||||
(void **)&vm);
|
||||
|
||||
if ((NS_OK != rv) || (NS_OK != vm->Init(newdx))) {
|
||||
NS_ASSERTION(PR_FALSE, "can't get good VM");
|
||||
}
|
||||
|
||||
nsRect tbounds = nsRect(0, 0, width, height);
|
||||
|
||||
// Create a child window of the parent that is our "root view/window"
|
||||
// Create a view
|
||||
rv = nsComponentManager::CreateInstance(kViewCID,
|
||||
nsnull,
|
||||
kIViewIID,
|
||||
(void **)&view);
|
||||
if ((NS_OK != rv) || (NS_OK != view->Init(vm,
|
||||
tbounds,
|
||||
nsnull))) {
|
||||
NS_ASSERTION(PR_FALSE, "can't get good view");
|
||||
}
|
||||
|
||||
// Setup hierarchical relationship in view manager
|
||||
vm->SetRootView(view);
|
||||
}
|
||||
|
||||
ps->Init(mDocument, cx, vm, ss);
|
||||
|
||||
//lay it out...
|
||||
//newdx->BeginDocument();
|
||||
ps->InitialReflow(width, height);
|
||||
|
||||
// Ask the page sequence frame to print all the pages
|
||||
nsIPageSequenceFrame* pageSequence;
|
||||
nsPrintOptions options;
|
||||
|
||||
ps->GetPageSequenceFrame(&pageSequence);
|
||||
NS_ASSERTION(nsnull != pageSequence, "no page sequence frame");
|
||||
pageSequence->Print(*cx, options, nsnull);
|
||||
newdx->EndDocument();
|
||||
|
||||
NS_RELEASE(ps);
|
||||
NS_RELEASE(vm);
|
||||
NS_RELEASE(ss);
|
||||
NS_RELEASE(newdx);
|
||||
NS_IF_RELEASE(prefs); // XXX why is the prefs null??
|
||||
}
|
||||
|
||||
}
|
||||
NS_RELEASE(factory);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void DocumentViewerImpl::ForceRefresh()
|
||||
{
|
||||
mWindow->Invalidate(PR_TRUE);
|
||||
}
|
||||
|
||||
nsresult
|
||||
DocumentViewerImpl::CreateStyleSet(nsIDocument* aDocument,
|
||||
nsIStyleSet** aStyleSet)
|
||||
{
|
||||
// this should eventually get expanded to allow for creating
|
||||
// different sets for different media
|
||||
nsresult rv;
|
||||
|
||||
if (!mUAStyleSheet) {
|
||||
NS_WARNING("unable to load UA style sheet");
|
||||
}
|
||||
|
||||
rv = NS_NewStyleSet(aStyleSet);
|
||||
if (NS_OK == rv) {
|
||||
PRInt32 index = aDocument->GetNumberOfStyleSheets();
|
||||
|
||||
while (0 < index--) {
|
||||
nsIStyleSheet* sheet = aDocument->GetStyleSheetAt(index);
|
||||
(*aStyleSet)->AddDocStyleSheet(sheet, aDocument);
|
||||
NS_RELEASE(sheet);
|
||||
}
|
||||
if (mUAStyleSheet) {
|
||||
(*aStyleSet)->AppendBackstopStyleSheet(mUAStyleSheet);
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
DocumentViewerImpl::MakeWindow(nsNativeWidget aNativeParent,
|
||||
const nsRect& aBounds,
|
||||
nsScrollPreference aScrolling)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
rv = nsComponentManager::CreateInstance(kViewManagerCID,
|
||||
nsnull,
|
||||
kIViewManagerIID,
|
||||
getter_AddRefs(mViewManager));
|
||||
|
||||
nsCOMPtr<nsIDeviceContext> dx;
|
||||
mPresContext->GetDeviceContext(getter_AddRefs(dx));
|
||||
|
||||
if ((NS_OK != rv) || (NS_OK != mViewManager->Init(dx))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsRect tbounds = aBounds;
|
||||
float p2t;
|
||||
mPresContext->GetPixelsToTwips(&p2t);
|
||||
tbounds *= p2t;
|
||||
|
||||
// Create a child window of the parent that is our "root view/window"
|
||||
// Create a view
|
||||
rv = nsComponentManager::CreateInstance(kViewCID,
|
||||
nsnull,
|
||||
kIViewIID,
|
||||
(void**)&mView);
|
||||
static NS_DEFINE_IID(kWidgetCID, NS_CHILD_CID);
|
||||
if ((NS_OK != rv) || (NS_OK != mView->Init(mViewManager,
|
||||
tbounds,
|
||||
nsnull))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = mView->CreateWidget(kWidgetCID, nsnull, aNativeParent);
|
||||
|
||||
if (rv != NS_OK)
|
||||
return rv;
|
||||
|
||||
// Setup hierarchical relationship in view manager
|
||||
mViewManager->SetRootView(mView);
|
||||
|
||||
mView->GetWidget(*getter_AddRefs(mWindow));
|
||||
|
||||
//set frame rate to 25 fps
|
||||
mViewManager->SetFrameRate(25);
|
||||
|
||||
// This SetFocus is necessary so the Arrow Key and Page Key events
|
||||
// go to the scrolled view as soon as the Window is created instead of going to
|
||||
// the browser window (this enables keyboard scrolling of the document)
|
||||
mWindow->SetFocus();
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
DocumentViewerImpl::CreateDocumentViewerUsing(nsIPresContext* aPresContext,
|
||||
nsIDocumentViewer*& aResult)
|
||||
{
|
||||
if (!mDocument) {
|
||||
// XXX better error
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
if (nsnull == aPresContext) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
// Create new viewer
|
||||
DocumentViewerImpl* viewer = new DocumentViewerImpl(aPresContext);
|
||||
if (nsnull == viewer) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
NS_ADDREF(viewer);
|
||||
|
||||
// XXX make sure the ua style sheet is used (for now; need to be
|
||||
// able to specify an alternate)
|
||||
viewer->SetUAStyleSheet(mUAStyleSheet);
|
||||
|
||||
// Bind the new viewer to the old document
|
||||
nsresult rv = viewer->BindToDocument(mDocument, "create");/* XXX verb? */
|
||||
|
||||
aResult = viewer;
|
||||
|
||||
return rv;
|
||||
}
|
||||
765
mozilla/layout/base/src/nsPluginViewer.cpp
Normal file
765
mozilla/layout/base/src/nsPluginViewer.cpp
Normal file
@ -0,0 +1,765 @@
|
||||
/* -*- 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.0 (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.
|
||||
*/
|
||||
#include "nscore.h"
|
||||
#include "nsCRT.h"
|
||||
#include "nsIContentViewer.h"
|
||||
#include "nsIContentViewerContainer.h"
|
||||
#include "nsIPluginHost.h"
|
||||
#include "nsIPluginInstance.h"
|
||||
#include "nsIStreamListener.h"
|
||||
#include "nsIURL.h"
|
||||
#include "nsIComponentManager.h"
|
||||
#include "nsWidgetsCID.h"
|
||||
#include "nsILinkHandler.h"
|
||||
#include "nsIWebShell.h"
|
||||
#include "nsIBrowserWindow.h"
|
||||
#include "nsIContent.h"
|
||||
#include "nsIDocument.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_ICONTENT_VIEWER_IID);
|
||||
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
|
||||
static NS_DEFINE_IID(kIPluginHostIID, NS_IPLUGINHOST_IID);
|
||||
static NS_DEFINE_IID(kIPluginInstanceOwnerIID, NS_IPLUGININSTANCEOWNER_IID);
|
||||
static NS_DEFINE_IID(kILinkHandlerIID, NS_ILINKHANDLER_IID);
|
||||
static NS_DEFINE_IID(kIStreamListenerIID, NS_ISTREAMLISTENER_IID);
|
||||
static NS_DEFINE_IID(kIWebShellIID, NS_IWEB_SHELL_IID);
|
||||
static NS_DEFINE_IID(kIBrowserWindowIID, NS_IBROWSER_WINDOW_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
|
||||
|
||||
// nsIStreamListener
|
||||
NS_IMETHOD OnStartBinding(nsIURL* aURL, const char *aContentType);
|
||||
NS_IMETHOD OnProgress(nsIURL* aURL, PRUint32 aProgress, PRUint32 aProgressMax);
|
||||
NS_IMETHOD OnStatus(nsIURL* aURL, const PRUnichar* aMsg);
|
||||
NS_IMETHOD OnStopBinding(nsIURL* aURL, nsresult aStatus,
|
||||
const PRUnichar* aMsg);
|
||||
NS_IMETHOD GetBindInfo(nsIURL* aURL, nsStreamBindingInfo* aInfo);
|
||||
NS_IMETHOD OnDataAvailable(nsIURL* aURL, nsIInputStream* aStream,
|
||||
PRUint32 aCount);
|
||||
|
||||
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);
|
||||
|
||||
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:
|
||||
PluginViewerImpl(const char* aCommand, nsIStreamListener** aDocListener);
|
||||
|
||||
NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW
|
||||
|
||||
// nsISupports
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsIContentViewer
|
||||
NS_IMETHOD Init(nsNativeWidget aParent,
|
||||
nsIDeviceContext* aDeviceContext,
|
||||
nsIPref* aPrefs,
|
||||
const nsRect& aBounds,
|
||||
nsScrollPreference aScrolling = nsScrollPreference_kAuto);
|
||||
NS_IMETHOD BindToDocument(nsISupports* aDoc, const char* aCommand);
|
||||
NS_IMETHOD SetContainer(nsIContentViewerContainer* aContainer);
|
||||
NS_IMETHOD GetContainer(nsIContentViewerContainer*& aContainerResult);
|
||||
NS_IMETHOD Stop(void);
|
||||
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 Print(void);
|
||||
|
||||
virtual ~PluginViewerImpl();
|
||||
|
||||
nsresult CreatePlugin(nsIPluginHost* aHost, const nsRect& aBounds,
|
||||
nsIStreamListener*& aResult);
|
||||
|
||||
nsresult MakeWindow(nsNativeWidget aParent,
|
||||
nsIDeviceContext* aDeviceContext,
|
||||
const nsRect& aBounds);
|
||||
|
||||
nsresult StartLoad(nsIURL* aURL, const char* aContentType,
|
||||
nsIStreamListener*& aResult);
|
||||
|
||||
void ForceRefresh(void);
|
||||
|
||||
nsresult GetURL(nsIURL *&aURL);
|
||||
|
||||
nsresult GetDocument(nsIDocument* *aDocument);
|
||||
|
||||
nsIWidget* mWindow;
|
||||
nsIDocument* mDocument;
|
||||
nsIContentViewerContainer* mContainer;
|
||||
nsIURL* mURL;
|
||||
nsString mContentType;
|
||||
pluginInstanceOwner *mOwner;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
nsresult
|
||||
NS_NewPluginContentViewer(const char* aCommand,
|
||||
nsIStreamListener** aDocListener,
|
||||
nsIContentViewer** aDocViewer)
|
||||
{
|
||||
PluginViewerImpl* it = new PluginViewerImpl(aCommand, aDocListener);
|
||||
if (nsnull == it) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
return it->QueryInterface(kIContentViewerIID, (void**) aDocViewer);
|
||||
}
|
||||
|
||||
// Note: operator new zeros our memory
|
||||
PluginViewerImpl::PluginViewerImpl(const char* aCommand,
|
||||
nsIStreamListener** aDocListener)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
nsIStreamListener* it = new PluginListener(this);
|
||||
*aDocListener = it;
|
||||
}
|
||||
|
||||
// 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)) {
|
||||
nsISupports* tmp = this;
|
||||
*aInstancePtr = (void*)tmp;
|
||||
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(mContainer);
|
||||
NS_IF_RELEASE(mURL);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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(nsIContentViewerContainer* aContainer)
|
||||
{
|
||||
NS_IF_RELEASE(mContainer);
|
||||
mContainer = aContainer;
|
||||
NS_IF_ADDREF(mContainer);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PluginViewerImpl::GetContainer(nsIContentViewerContainer*& aResult)
|
||||
{
|
||||
aResult = mContainer;
|
||||
NS_IF_ADDREF(mContainer);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
PluginViewerImpl::Init(nsNativeWidget aNativeParent,
|
||||
nsIDeviceContext* aDeviceContext,
|
||||
nsIPref* aPrefs,
|
||||
const nsRect& aBounds,
|
||||
nsScrollPreference aScrolling)
|
||||
{
|
||||
nsresult rv = MakeWindow(aNativeParent, 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(nsIURL* aURL, const char* aContentType,
|
||||
nsIStreamListener*& aResult)
|
||||
{
|
||||
printf("PluginViewerImpl::StartLoad: content-type=%s\n", aContentType);
|
||||
|
||||
NS_IF_RELEASE(mURL);
|
||||
mURL = aURL;
|
||||
NS_IF_ADDREF(aURL);
|
||||
mContentType = aContentType;
|
||||
|
||||
aResult = nsnull;
|
||||
|
||||
// Only instantiate the plugin if our container can host it
|
||||
nsIPluginHost* host;
|
||||
nsresult rv = mContainer->QueryCapability(kIPluginHostIID, (void **)&host);
|
||||
if (NS_OK == rv) {
|
||||
nsRect r;
|
||||
mWindow->GetClientBounds(r);
|
||||
rv = CreatePlugin(host, nsRect(0, 0, r.width, r.height), aResult);
|
||||
NS_RELEASE(host);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
PluginViewerImpl::CreatePlugin(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
|
||||
|
||||
PRUnichar* fullurl;
|
||||
mURL->ToString(&fullurl);
|
||||
|
||||
char* ct = mContentType.ToNewCString();
|
||||
nsAutoString str = fullurl;
|
||||
rv = aHost->InstantiateFullPagePlugin(ct, str, aResult, mOwner);
|
||||
delete fullurl;
|
||||
delete[] ct;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PluginViewerImpl::Stop(void)
|
||||
{
|
||||
// XXX write this
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static nsEventStatus PR_CALLBACK
|
||||
HandlePluginEvent(nsGUIEvent *aEvent)
|
||||
{
|
||||
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 :: Print(void)
|
||||
{
|
||||
// need to call the plugin from here somehow
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
PluginViewerImpl::ForceRefresh()
|
||||
{
|
||||
mWindow->Invalidate(PR_TRUE);
|
||||
}
|
||||
|
||||
nsresult PluginViewerImpl::GetURL(nsIURL *&aURL)
|
||||
{
|
||||
NS_IF_ADDREF(mURL);
|
||||
aURL = mURL;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult PluginViewerImpl::GetDocument(nsIDocument* *aDocument)
|
||||
{
|
||||
NS_IF_ADDREF(mDocument);
|
||||
*aDocument = mDocument;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
PluginListener::PluginListener(PluginViewerImpl* aViewer)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
mViewer = aViewer;
|
||||
NS_ADDREF(aViewer);
|
||||
mRefCnt = 1;
|
||||
}
|
||||
|
||||
PluginListener::~PluginListener()
|
||||
{
|
||||
NS_RELEASE(mViewer);
|
||||
NS_IF_RELEASE(mNextStream);
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(PluginListener, kIStreamListenerIID)
|
||||
|
||||
NS_IMETHODIMP
|
||||
PluginListener::OnStartBinding(nsIURL* aURL, const char *aContentType)
|
||||
{
|
||||
mViewer->StartLoad(aURL, aContentType, mNextStream);
|
||||
if (nsnull == mNextStream) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
return mNextStream->OnStartBinding(aURL, aContentType);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PluginListener::OnProgress(nsIURL* aURL, PRUint32 aProgress,
|
||||
PRUint32 aProgressMax)
|
||||
{
|
||||
if (nsnull == mNextStream) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
return mNextStream->OnProgress(aURL, aProgress, aProgressMax);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PluginListener::OnStatus(nsIURL* aURL, const PRUnichar* aMsg)
|
||||
{
|
||||
if (nsnull == mNextStream) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
return mNextStream->OnStatus(aURL, aMsg);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PluginListener::OnStopBinding(nsIURL* aURL, nsresult aStatus,
|
||||
const PRUnichar* aMsg)
|
||||
{
|
||||
if (nsnull == mNextStream) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
return mNextStream->OnStopBinding(aURL, aStatus, aMsg);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PluginListener::GetBindInfo(nsIURL* aURL, nsStreamBindingInfo* aInfo)
|
||||
{
|
||||
if (nsnull == mNextStream) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
return mNextStream->GetBindInfo(aURL, aInfo);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PluginListener::OnDataAvailable(nsIURL* aURL, nsIInputStream* aStream,
|
||||
PRUint32 aCount)
|
||||
{
|
||||
if (nsnull == mNextStream) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
return mNextStream->OnDataAvailable(aURL, aStream, aCount);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
pluginInstanceOwner :: pluginInstanceOwner()
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
|
||||
memset(&mPluginWindow, 0, sizeof(mPluginWindow));
|
||||
mInstance = nsnull;
|
||||
mWindow = nsnull;
|
||||
mViewer = nsnull;
|
||||
}
|
||||
|
||||
pluginInstanceOwner :: ~pluginInstanceOwner()
|
||||
{
|
||||
if (nsnull != mInstance)
|
||||
{
|
||||
mInstance->Stop();
|
||||
mInstance->Destroy();
|
||||
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_WINDOW);
|
||||
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)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
if (nsnull != mViewer)
|
||||
{
|
||||
nsIContentViewerContainer *cont;
|
||||
|
||||
rv = mViewer->GetContainer(cont);
|
||||
|
||||
if (NS_OK == rv)
|
||||
{
|
||||
nsILinkHandler *lh;
|
||||
|
||||
rv = cont->QueryInterface(kILinkHandlerIID, (void **)&lh);
|
||||
|
||||
if (NS_OK == rv)
|
||||
{
|
||||
nsIURL *url;
|
||||
|
||||
rv = mViewer->GetURL(url);
|
||||
|
||||
if (NS_OK == rv)
|
||||
{
|
||||
nsAutoString uniurl = nsAutoString(aURL);
|
||||
nsAutoString unitarget = nsAutoString(aTarget);
|
||||
const char* spec;
|
||||
(void)url->GetSpec(&spec);
|
||||
nsAutoString base = nsAutoString(spec);
|
||||
nsAutoString fullurl;
|
||||
|
||||
// Create an absolute URL
|
||||
rv = NS_MakeAbsoluteURL(url, base, uniurl, fullurl);
|
||||
|
||||
if (NS_OK == rv)
|
||||
rv = lh->OnLinkClick(nsnull, eLinkVerb_Replace, fullurl.GetUnicode(), unitarget.GetUnicode(), nsnull);
|
||||
|
||||
NS_RELEASE(url);
|
||||
}
|
||||
|
||||
NS_RELEASE(lh);
|
||||
}
|
||||
|
||||
NS_RELEASE(cont);
|
||||
}
|
||||
}
|
||||
else
|
||||
rv = NS_ERROR_FAILURE;
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP pluginInstanceOwner :: ShowStatus(const char *aStatusMsg)
|
||||
{
|
||||
nsresult rv = NS_ERROR_FAILURE;
|
||||
|
||||
if (nsnull != mViewer)
|
||||
{
|
||||
nsIContentViewerContainer *cont;
|
||||
|
||||
rv = mViewer->GetContainer(cont);
|
||||
|
||||
if ((NS_OK == rv) && (nsnull != cont))
|
||||
{
|
||||
nsIWebShell *ws;
|
||||
|
||||
rv = cont->QueryInterface(kIWebShellIID, (void **)&ws);
|
||||
|
||||
if (NS_OK == rv)
|
||||
{
|
||||
nsIWebShell *rootWebShell;
|
||||
|
||||
ws->GetRootWebShell(rootWebShell);
|
||||
|
||||
if (nsnull != rootWebShell)
|
||||
{
|
||||
nsIWebShellContainer *rootContainer;
|
||||
|
||||
rv = rootWebShell->GetContainer(rootContainer);
|
||||
|
||||
if (nsnull != rootContainer)
|
||||
{
|
||||
nsIBrowserWindow *browserWindow;
|
||||
|
||||
if (NS_OK == rootContainer->QueryInterface(kIBrowserWindowIID, (void**)&browserWindow))
|
||||
{
|
||||
nsAutoString msg = nsAutoString(aStatusMsg);
|
||||
|
||||
rv = browserWindow->SetStatus(msg.GetUnicode());
|
||||
NS_RELEASE(browserWindow);
|
||||
}
|
||||
|
||||
NS_RELEASE(rootContainer);
|
||||
}
|
||||
|
||||
NS_RELEASE(rootWebShell);
|
||||
}
|
||||
|
||||
NS_RELEASE(ws);
|
||||
}
|
||||
|
||||
NS_RELEASE(cont);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
765
mozilla/modules/plugin/base/src/nsPluginViewer.cpp
Normal file
765
mozilla/modules/plugin/base/src/nsPluginViewer.cpp
Normal file
@ -0,0 +1,765 @@
|
||||
/* -*- 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.0 (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.
|
||||
*/
|
||||
#include "nscore.h"
|
||||
#include "nsCRT.h"
|
||||
#include "nsIContentViewer.h"
|
||||
#include "nsIContentViewerContainer.h"
|
||||
#include "nsIPluginHost.h"
|
||||
#include "nsIPluginInstance.h"
|
||||
#include "nsIStreamListener.h"
|
||||
#include "nsIURL.h"
|
||||
#include "nsIComponentManager.h"
|
||||
#include "nsWidgetsCID.h"
|
||||
#include "nsILinkHandler.h"
|
||||
#include "nsIWebShell.h"
|
||||
#include "nsIBrowserWindow.h"
|
||||
#include "nsIContent.h"
|
||||
#include "nsIDocument.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_ICONTENT_VIEWER_IID);
|
||||
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
|
||||
static NS_DEFINE_IID(kIPluginHostIID, NS_IPLUGINHOST_IID);
|
||||
static NS_DEFINE_IID(kIPluginInstanceOwnerIID, NS_IPLUGININSTANCEOWNER_IID);
|
||||
static NS_DEFINE_IID(kILinkHandlerIID, NS_ILINKHANDLER_IID);
|
||||
static NS_DEFINE_IID(kIStreamListenerIID, NS_ISTREAMLISTENER_IID);
|
||||
static NS_DEFINE_IID(kIWebShellIID, NS_IWEB_SHELL_IID);
|
||||
static NS_DEFINE_IID(kIBrowserWindowIID, NS_IBROWSER_WINDOW_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
|
||||
|
||||
// nsIStreamListener
|
||||
NS_IMETHOD OnStartBinding(nsIURL* aURL, const char *aContentType);
|
||||
NS_IMETHOD OnProgress(nsIURL* aURL, PRUint32 aProgress, PRUint32 aProgressMax);
|
||||
NS_IMETHOD OnStatus(nsIURL* aURL, const PRUnichar* aMsg);
|
||||
NS_IMETHOD OnStopBinding(nsIURL* aURL, nsresult aStatus,
|
||||
const PRUnichar* aMsg);
|
||||
NS_IMETHOD GetBindInfo(nsIURL* aURL, nsStreamBindingInfo* aInfo);
|
||||
NS_IMETHOD OnDataAvailable(nsIURL* aURL, nsIInputStream* aStream,
|
||||
PRUint32 aCount);
|
||||
|
||||
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);
|
||||
|
||||
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:
|
||||
PluginViewerImpl(const char* aCommand, nsIStreamListener** aDocListener);
|
||||
|
||||
NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW
|
||||
|
||||
// nsISupports
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsIContentViewer
|
||||
NS_IMETHOD Init(nsNativeWidget aParent,
|
||||
nsIDeviceContext* aDeviceContext,
|
||||
nsIPref* aPrefs,
|
||||
const nsRect& aBounds,
|
||||
nsScrollPreference aScrolling = nsScrollPreference_kAuto);
|
||||
NS_IMETHOD BindToDocument(nsISupports* aDoc, const char* aCommand);
|
||||
NS_IMETHOD SetContainer(nsIContentViewerContainer* aContainer);
|
||||
NS_IMETHOD GetContainer(nsIContentViewerContainer*& aContainerResult);
|
||||
NS_IMETHOD Stop(void);
|
||||
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 Print(void);
|
||||
|
||||
virtual ~PluginViewerImpl();
|
||||
|
||||
nsresult CreatePlugin(nsIPluginHost* aHost, const nsRect& aBounds,
|
||||
nsIStreamListener*& aResult);
|
||||
|
||||
nsresult MakeWindow(nsNativeWidget aParent,
|
||||
nsIDeviceContext* aDeviceContext,
|
||||
const nsRect& aBounds);
|
||||
|
||||
nsresult StartLoad(nsIURL* aURL, const char* aContentType,
|
||||
nsIStreamListener*& aResult);
|
||||
|
||||
void ForceRefresh(void);
|
||||
|
||||
nsresult GetURL(nsIURL *&aURL);
|
||||
|
||||
nsresult GetDocument(nsIDocument* *aDocument);
|
||||
|
||||
nsIWidget* mWindow;
|
||||
nsIDocument* mDocument;
|
||||
nsIContentViewerContainer* mContainer;
|
||||
nsIURL* mURL;
|
||||
nsString mContentType;
|
||||
pluginInstanceOwner *mOwner;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
nsresult
|
||||
NS_NewPluginContentViewer(const char* aCommand,
|
||||
nsIStreamListener** aDocListener,
|
||||
nsIContentViewer** aDocViewer)
|
||||
{
|
||||
PluginViewerImpl* it = new PluginViewerImpl(aCommand, aDocListener);
|
||||
if (nsnull == it) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
return it->QueryInterface(kIContentViewerIID, (void**) aDocViewer);
|
||||
}
|
||||
|
||||
// Note: operator new zeros our memory
|
||||
PluginViewerImpl::PluginViewerImpl(const char* aCommand,
|
||||
nsIStreamListener** aDocListener)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
nsIStreamListener* it = new PluginListener(this);
|
||||
*aDocListener = it;
|
||||
}
|
||||
|
||||
// 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)) {
|
||||
nsISupports* tmp = this;
|
||||
*aInstancePtr = (void*)tmp;
|
||||
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(mContainer);
|
||||
NS_IF_RELEASE(mURL);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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(nsIContentViewerContainer* aContainer)
|
||||
{
|
||||
NS_IF_RELEASE(mContainer);
|
||||
mContainer = aContainer;
|
||||
NS_IF_ADDREF(mContainer);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PluginViewerImpl::GetContainer(nsIContentViewerContainer*& aResult)
|
||||
{
|
||||
aResult = mContainer;
|
||||
NS_IF_ADDREF(mContainer);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
PluginViewerImpl::Init(nsNativeWidget aNativeParent,
|
||||
nsIDeviceContext* aDeviceContext,
|
||||
nsIPref* aPrefs,
|
||||
const nsRect& aBounds,
|
||||
nsScrollPreference aScrolling)
|
||||
{
|
||||
nsresult rv = MakeWindow(aNativeParent, 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(nsIURL* aURL, const char* aContentType,
|
||||
nsIStreamListener*& aResult)
|
||||
{
|
||||
printf("PluginViewerImpl::StartLoad: content-type=%s\n", aContentType);
|
||||
|
||||
NS_IF_RELEASE(mURL);
|
||||
mURL = aURL;
|
||||
NS_IF_ADDREF(aURL);
|
||||
mContentType = aContentType;
|
||||
|
||||
aResult = nsnull;
|
||||
|
||||
// Only instantiate the plugin if our container can host it
|
||||
nsIPluginHost* host;
|
||||
nsresult rv = mContainer->QueryCapability(kIPluginHostIID, (void **)&host);
|
||||
if (NS_OK == rv) {
|
||||
nsRect r;
|
||||
mWindow->GetClientBounds(r);
|
||||
rv = CreatePlugin(host, nsRect(0, 0, r.width, r.height), aResult);
|
||||
NS_RELEASE(host);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
PluginViewerImpl::CreatePlugin(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
|
||||
|
||||
PRUnichar* fullurl;
|
||||
mURL->ToString(&fullurl);
|
||||
|
||||
char* ct = mContentType.ToNewCString();
|
||||
nsAutoString str = fullurl;
|
||||
rv = aHost->InstantiateFullPagePlugin(ct, str, aResult, mOwner);
|
||||
delete fullurl;
|
||||
delete[] ct;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PluginViewerImpl::Stop(void)
|
||||
{
|
||||
// XXX write this
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static nsEventStatus PR_CALLBACK
|
||||
HandlePluginEvent(nsGUIEvent *aEvent)
|
||||
{
|
||||
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 :: Print(void)
|
||||
{
|
||||
// need to call the plugin from here somehow
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
PluginViewerImpl::ForceRefresh()
|
||||
{
|
||||
mWindow->Invalidate(PR_TRUE);
|
||||
}
|
||||
|
||||
nsresult PluginViewerImpl::GetURL(nsIURL *&aURL)
|
||||
{
|
||||
NS_IF_ADDREF(mURL);
|
||||
aURL = mURL;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult PluginViewerImpl::GetDocument(nsIDocument* *aDocument)
|
||||
{
|
||||
NS_IF_ADDREF(mDocument);
|
||||
*aDocument = mDocument;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
PluginListener::PluginListener(PluginViewerImpl* aViewer)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
mViewer = aViewer;
|
||||
NS_ADDREF(aViewer);
|
||||
mRefCnt = 1;
|
||||
}
|
||||
|
||||
PluginListener::~PluginListener()
|
||||
{
|
||||
NS_RELEASE(mViewer);
|
||||
NS_IF_RELEASE(mNextStream);
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(PluginListener, kIStreamListenerIID)
|
||||
|
||||
NS_IMETHODIMP
|
||||
PluginListener::OnStartBinding(nsIURL* aURL, const char *aContentType)
|
||||
{
|
||||
mViewer->StartLoad(aURL, aContentType, mNextStream);
|
||||
if (nsnull == mNextStream) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
return mNextStream->OnStartBinding(aURL, aContentType);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PluginListener::OnProgress(nsIURL* aURL, PRUint32 aProgress,
|
||||
PRUint32 aProgressMax)
|
||||
{
|
||||
if (nsnull == mNextStream) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
return mNextStream->OnProgress(aURL, aProgress, aProgressMax);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PluginListener::OnStatus(nsIURL* aURL, const PRUnichar* aMsg)
|
||||
{
|
||||
if (nsnull == mNextStream) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
return mNextStream->OnStatus(aURL, aMsg);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PluginListener::OnStopBinding(nsIURL* aURL, nsresult aStatus,
|
||||
const PRUnichar* aMsg)
|
||||
{
|
||||
if (nsnull == mNextStream) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
return mNextStream->OnStopBinding(aURL, aStatus, aMsg);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PluginListener::GetBindInfo(nsIURL* aURL, nsStreamBindingInfo* aInfo)
|
||||
{
|
||||
if (nsnull == mNextStream) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
return mNextStream->GetBindInfo(aURL, aInfo);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PluginListener::OnDataAvailable(nsIURL* aURL, nsIInputStream* aStream,
|
||||
PRUint32 aCount)
|
||||
{
|
||||
if (nsnull == mNextStream) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
return mNextStream->OnDataAvailable(aURL, aStream, aCount);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
pluginInstanceOwner :: pluginInstanceOwner()
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
|
||||
memset(&mPluginWindow, 0, sizeof(mPluginWindow));
|
||||
mInstance = nsnull;
|
||||
mWindow = nsnull;
|
||||
mViewer = nsnull;
|
||||
}
|
||||
|
||||
pluginInstanceOwner :: ~pluginInstanceOwner()
|
||||
{
|
||||
if (nsnull != mInstance)
|
||||
{
|
||||
mInstance->Stop();
|
||||
mInstance->Destroy();
|
||||
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_WINDOW);
|
||||
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)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
if (nsnull != mViewer)
|
||||
{
|
||||
nsIContentViewerContainer *cont;
|
||||
|
||||
rv = mViewer->GetContainer(cont);
|
||||
|
||||
if (NS_OK == rv)
|
||||
{
|
||||
nsILinkHandler *lh;
|
||||
|
||||
rv = cont->QueryInterface(kILinkHandlerIID, (void **)&lh);
|
||||
|
||||
if (NS_OK == rv)
|
||||
{
|
||||
nsIURL *url;
|
||||
|
||||
rv = mViewer->GetURL(url);
|
||||
|
||||
if (NS_OK == rv)
|
||||
{
|
||||
nsAutoString uniurl = nsAutoString(aURL);
|
||||
nsAutoString unitarget = nsAutoString(aTarget);
|
||||
const char* spec;
|
||||
(void)url->GetSpec(&spec);
|
||||
nsAutoString base = nsAutoString(spec);
|
||||
nsAutoString fullurl;
|
||||
|
||||
// Create an absolute URL
|
||||
rv = NS_MakeAbsoluteURL(url, base, uniurl, fullurl);
|
||||
|
||||
if (NS_OK == rv)
|
||||
rv = lh->OnLinkClick(nsnull, eLinkVerb_Replace, fullurl.GetUnicode(), unitarget.GetUnicode(), nsnull);
|
||||
|
||||
NS_RELEASE(url);
|
||||
}
|
||||
|
||||
NS_RELEASE(lh);
|
||||
}
|
||||
|
||||
NS_RELEASE(cont);
|
||||
}
|
||||
}
|
||||
else
|
||||
rv = NS_ERROR_FAILURE;
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP pluginInstanceOwner :: ShowStatus(const char *aStatusMsg)
|
||||
{
|
||||
nsresult rv = NS_ERROR_FAILURE;
|
||||
|
||||
if (nsnull != mViewer)
|
||||
{
|
||||
nsIContentViewerContainer *cont;
|
||||
|
||||
rv = mViewer->GetContainer(cont);
|
||||
|
||||
if ((NS_OK == rv) && (nsnull != cont))
|
||||
{
|
||||
nsIWebShell *ws;
|
||||
|
||||
rv = cont->QueryInterface(kIWebShellIID, (void **)&ws);
|
||||
|
||||
if (NS_OK == rv)
|
||||
{
|
||||
nsIWebShell *rootWebShell;
|
||||
|
||||
ws->GetRootWebShell(rootWebShell);
|
||||
|
||||
if (nsnull != rootWebShell)
|
||||
{
|
||||
nsIWebShellContainer *rootContainer;
|
||||
|
||||
rv = rootWebShell->GetContainer(rootContainer);
|
||||
|
||||
if (nsnull != rootContainer)
|
||||
{
|
||||
nsIBrowserWindow *browserWindow;
|
||||
|
||||
if (NS_OK == rootContainer->QueryInterface(kIBrowserWindowIID, (void**)&browserWindow))
|
||||
{
|
||||
nsAutoString msg = nsAutoString(aStatusMsg);
|
||||
|
||||
rv = browserWindow->SetStatus(msg.GetUnicode());
|
||||
NS_RELEASE(browserWindow);
|
||||
}
|
||||
|
||||
NS_RELEASE(rootContainer);
|
||||
}
|
||||
|
||||
NS_RELEASE(rootWebShell);
|
||||
}
|
||||
|
||||
NS_RELEASE(ws);
|
||||
}
|
||||
|
||||
NS_RELEASE(cont);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
765
mozilla/modules/plugin/nglsrc/nsPluginViewer.cpp
Normal file
765
mozilla/modules/plugin/nglsrc/nsPluginViewer.cpp
Normal file
@ -0,0 +1,765 @@
|
||||
/* -*- 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.0 (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.
|
||||
*/
|
||||
#include "nscore.h"
|
||||
#include "nsCRT.h"
|
||||
#include "nsIContentViewer.h"
|
||||
#include "nsIContentViewerContainer.h"
|
||||
#include "nsIPluginHost.h"
|
||||
#include "nsIPluginInstance.h"
|
||||
#include "nsIStreamListener.h"
|
||||
#include "nsIURL.h"
|
||||
#include "nsIComponentManager.h"
|
||||
#include "nsWidgetsCID.h"
|
||||
#include "nsILinkHandler.h"
|
||||
#include "nsIWebShell.h"
|
||||
#include "nsIBrowserWindow.h"
|
||||
#include "nsIContent.h"
|
||||
#include "nsIDocument.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_ICONTENT_VIEWER_IID);
|
||||
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
|
||||
static NS_DEFINE_IID(kIPluginHostIID, NS_IPLUGINHOST_IID);
|
||||
static NS_DEFINE_IID(kIPluginInstanceOwnerIID, NS_IPLUGININSTANCEOWNER_IID);
|
||||
static NS_DEFINE_IID(kILinkHandlerIID, NS_ILINKHANDLER_IID);
|
||||
static NS_DEFINE_IID(kIStreamListenerIID, NS_ISTREAMLISTENER_IID);
|
||||
static NS_DEFINE_IID(kIWebShellIID, NS_IWEB_SHELL_IID);
|
||||
static NS_DEFINE_IID(kIBrowserWindowIID, NS_IBROWSER_WINDOW_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
|
||||
|
||||
// nsIStreamListener
|
||||
NS_IMETHOD OnStartBinding(nsIURL* aURL, const char *aContentType);
|
||||
NS_IMETHOD OnProgress(nsIURL* aURL, PRUint32 aProgress, PRUint32 aProgressMax);
|
||||
NS_IMETHOD OnStatus(nsIURL* aURL, const PRUnichar* aMsg);
|
||||
NS_IMETHOD OnStopBinding(nsIURL* aURL, nsresult aStatus,
|
||||
const PRUnichar* aMsg);
|
||||
NS_IMETHOD GetBindInfo(nsIURL* aURL, nsStreamBindingInfo* aInfo);
|
||||
NS_IMETHOD OnDataAvailable(nsIURL* aURL, nsIInputStream* aStream,
|
||||
PRUint32 aCount);
|
||||
|
||||
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);
|
||||
|
||||
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:
|
||||
PluginViewerImpl(const char* aCommand, nsIStreamListener** aDocListener);
|
||||
|
||||
NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW
|
||||
|
||||
// nsISupports
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsIContentViewer
|
||||
NS_IMETHOD Init(nsNativeWidget aParent,
|
||||
nsIDeviceContext* aDeviceContext,
|
||||
nsIPref* aPrefs,
|
||||
const nsRect& aBounds,
|
||||
nsScrollPreference aScrolling = nsScrollPreference_kAuto);
|
||||
NS_IMETHOD BindToDocument(nsISupports* aDoc, const char* aCommand);
|
||||
NS_IMETHOD SetContainer(nsIContentViewerContainer* aContainer);
|
||||
NS_IMETHOD GetContainer(nsIContentViewerContainer*& aContainerResult);
|
||||
NS_IMETHOD Stop(void);
|
||||
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 Print(void);
|
||||
|
||||
virtual ~PluginViewerImpl();
|
||||
|
||||
nsresult CreatePlugin(nsIPluginHost* aHost, const nsRect& aBounds,
|
||||
nsIStreamListener*& aResult);
|
||||
|
||||
nsresult MakeWindow(nsNativeWidget aParent,
|
||||
nsIDeviceContext* aDeviceContext,
|
||||
const nsRect& aBounds);
|
||||
|
||||
nsresult StartLoad(nsIURL* aURL, const char* aContentType,
|
||||
nsIStreamListener*& aResult);
|
||||
|
||||
void ForceRefresh(void);
|
||||
|
||||
nsresult GetURL(nsIURL *&aURL);
|
||||
|
||||
nsresult GetDocument(nsIDocument* *aDocument);
|
||||
|
||||
nsIWidget* mWindow;
|
||||
nsIDocument* mDocument;
|
||||
nsIContentViewerContainer* mContainer;
|
||||
nsIURL* mURL;
|
||||
nsString mContentType;
|
||||
pluginInstanceOwner *mOwner;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
nsresult
|
||||
NS_NewPluginContentViewer(const char* aCommand,
|
||||
nsIStreamListener** aDocListener,
|
||||
nsIContentViewer** aDocViewer)
|
||||
{
|
||||
PluginViewerImpl* it = new PluginViewerImpl(aCommand, aDocListener);
|
||||
if (nsnull == it) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
return it->QueryInterface(kIContentViewerIID, (void**) aDocViewer);
|
||||
}
|
||||
|
||||
// Note: operator new zeros our memory
|
||||
PluginViewerImpl::PluginViewerImpl(const char* aCommand,
|
||||
nsIStreamListener** aDocListener)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
nsIStreamListener* it = new PluginListener(this);
|
||||
*aDocListener = it;
|
||||
}
|
||||
|
||||
// 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)) {
|
||||
nsISupports* tmp = this;
|
||||
*aInstancePtr = (void*)tmp;
|
||||
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(mContainer);
|
||||
NS_IF_RELEASE(mURL);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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(nsIContentViewerContainer* aContainer)
|
||||
{
|
||||
NS_IF_RELEASE(mContainer);
|
||||
mContainer = aContainer;
|
||||
NS_IF_ADDREF(mContainer);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PluginViewerImpl::GetContainer(nsIContentViewerContainer*& aResult)
|
||||
{
|
||||
aResult = mContainer;
|
||||
NS_IF_ADDREF(mContainer);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
PluginViewerImpl::Init(nsNativeWidget aNativeParent,
|
||||
nsIDeviceContext* aDeviceContext,
|
||||
nsIPref* aPrefs,
|
||||
const nsRect& aBounds,
|
||||
nsScrollPreference aScrolling)
|
||||
{
|
||||
nsresult rv = MakeWindow(aNativeParent, 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(nsIURL* aURL, const char* aContentType,
|
||||
nsIStreamListener*& aResult)
|
||||
{
|
||||
printf("PluginViewerImpl::StartLoad: content-type=%s\n", aContentType);
|
||||
|
||||
NS_IF_RELEASE(mURL);
|
||||
mURL = aURL;
|
||||
NS_IF_ADDREF(aURL);
|
||||
mContentType = aContentType;
|
||||
|
||||
aResult = nsnull;
|
||||
|
||||
// Only instantiate the plugin if our container can host it
|
||||
nsIPluginHost* host;
|
||||
nsresult rv = mContainer->QueryCapability(kIPluginHostIID, (void **)&host);
|
||||
if (NS_OK == rv) {
|
||||
nsRect r;
|
||||
mWindow->GetClientBounds(r);
|
||||
rv = CreatePlugin(host, nsRect(0, 0, r.width, r.height), aResult);
|
||||
NS_RELEASE(host);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
PluginViewerImpl::CreatePlugin(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
|
||||
|
||||
PRUnichar* fullurl;
|
||||
mURL->ToString(&fullurl);
|
||||
|
||||
char* ct = mContentType.ToNewCString();
|
||||
nsAutoString str = fullurl;
|
||||
rv = aHost->InstantiateFullPagePlugin(ct, str, aResult, mOwner);
|
||||
delete fullurl;
|
||||
delete[] ct;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PluginViewerImpl::Stop(void)
|
||||
{
|
||||
// XXX write this
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static nsEventStatus PR_CALLBACK
|
||||
HandlePluginEvent(nsGUIEvent *aEvent)
|
||||
{
|
||||
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 :: Print(void)
|
||||
{
|
||||
// need to call the plugin from here somehow
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
PluginViewerImpl::ForceRefresh()
|
||||
{
|
||||
mWindow->Invalidate(PR_TRUE);
|
||||
}
|
||||
|
||||
nsresult PluginViewerImpl::GetURL(nsIURL *&aURL)
|
||||
{
|
||||
NS_IF_ADDREF(mURL);
|
||||
aURL = mURL;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult PluginViewerImpl::GetDocument(nsIDocument* *aDocument)
|
||||
{
|
||||
NS_IF_ADDREF(mDocument);
|
||||
*aDocument = mDocument;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
PluginListener::PluginListener(PluginViewerImpl* aViewer)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
mViewer = aViewer;
|
||||
NS_ADDREF(aViewer);
|
||||
mRefCnt = 1;
|
||||
}
|
||||
|
||||
PluginListener::~PluginListener()
|
||||
{
|
||||
NS_RELEASE(mViewer);
|
||||
NS_IF_RELEASE(mNextStream);
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(PluginListener, kIStreamListenerIID)
|
||||
|
||||
NS_IMETHODIMP
|
||||
PluginListener::OnStartBinding(nsIURL* aURL, const char *aContentType)
|
||||
{
|
||||
mViewer->StartLoad(aURL, aContentType, mNextStream);
|
||||
if (nsnull == mNextStream) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
return mNextStream->OnStartBinding(aURL, aContentType);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PluginListener::OnProgress(nsIURL* aURL, PRUint32 aProgress,
|
||||
PRUint32 aProgressMax)
|
||||
{
|
||||
if (nsnull == mNextStream) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
return mNextStream->OnProgress(aURL, aProgress, aProgressMax);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PluginListener::OnStatus(nsIURL* aURL, const PRUnichar* aMsg)
|
||||
{
|
||||
if (nsnull == mNextStream) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
return mNextStream->OnStatus(aURL, aMsg);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PluginListener::OnStopBinding(nsIURL* aURL, nsresult aStatus,
|
||||
const PRUnichar* aMsg)
|
||||
{
|
||||
if (nsnull == mNextStream) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
return mNextStream->OnStopBinding(aURL, aStatus, aMsg);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PluginListener::GetBindInfo(nsIURL* aURL, nsStreamBindingInfo* aInfo)
|
||||
{
|
||||
if (nsnull == mNextStream) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
return mNextStream->GetBindInfo(aURL, aInfo);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PluginListener::OnDataAvailable(nsIURL* aURL, nsIInputStream* aStream,
|
||||
PRUint32 aCount)
|
||||
{
|
||||
if (nsnull == mNextStream) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
return mNextStream->OnDataAvailable(aURL, aStream, aCount);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
pluginInstanceOwner :: pluginInstanceOwner()
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
|
||||
memset(&mPluginWindow, 0, sizeof(mPluginWindow));
|
||||
mInstance = nsnull;
|
||||
mWindow = nsnull;
|
||||
mViewer = nsnull;
|
||||
}
|
||||
|
||||
pluginInstanceOwner :: ~pluginInstanceOwner()
|
||||
{
|
||||
if (nsnull != mInstance)
|
||||
{
|
||||
mInstance->Stop();
|
||||
mInstance->Destroy();
|
||||
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_WINDOW);
|
||||
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)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
if (nsnull != mViewer)
|
||||
{
|
||||
nsIContentViewerContainer *cont;
|
||||
|
||||
rv = mViewer->GetContainer(cont);
|
||||
|
||||
if (NS_OK == rv)
|
||||
{
|
||||
nsILinkHandler *lh;
|
||||
|
||||
rv = cont->QueryInterface(kILinkHandlerIID, (void **)&lh);
|
||||
|
||||
if (NS_OK == rv)
|
||||
{
|
||||
nsIURL *url;
|
||||
|
||||
rv = mViewer->GetURL(url);
|
||||
|
||||
if (NS_OK == rv)
|
||||
{
|
||||
nsAutoString uniurl = nsAutoString(aURL);
|
||||
nsAutoString unitarget = nsAutoString(aTarget);
|
||||
const char* spec;
|
||||
(void)url->GetSpec(&spec);
|
||||
nsAutoString base = nsAutoString(spec);
|
||||
nsAutoString fullurl;
|
||||
|
||||
// Create an absolute URL
|
||||
rv = NS_MakeAbsoluteURL(url, base, uniurl, fullurl);
|
||||
|
||||
if (NS_OK == rv)
|
||||
rv = lh->OnLinkClick(nsnull, eLinkVerb_Replace, fullurl.GetUnicode(), unitarget.GetUnicode(), nsnull);
|
||||
|
||||
NS_RELEASE(url);
|
||||
}
|
||||
|
||||
NS_RELEASE(lh);
|
||||
}
|
||||
|
||||
NS_RELEASE(cont);
|
||||
}
|
||||
}
|
||||
else
|
||||
rv = NS_ERROR_FAILURE;
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP pluginInstanceOwner :: ShowStatus(const char *aStatusMsg)
|
||||
{
|
||||
nsresult rv = NS_ERROR_FAILURE;
|
||||
|
||||
if (nsnull != mViewer)
|
||||
{
|
||||
nsIContentViewerContainer *cont;
|
||||
|
||||
rv = mViewer->GetContainer(cont);
|
||||
|
||||
if ((NS_OK == rv) && (nsnull != cont))
|
||||
{
|
||||
nsIWebShell *ws;
|
||||
|
||||
rv = cont->QueryInterface(kIWebShellIID, (void **)&ws);
|
||||
|
||||
if (NS_OK == rv)
|
||||
{
|
||||
nsIWebShell *rootWebShell;
|
||||
|
||||
ws->GetRootWebShell(rootWebShell);
|
||||
|
||||
if (nsnull != rootWebShell)
|
||||
{
|
||||
nsIWebShellContainer *rootContainer;
|
||||
|
||||
rv = rootWebShell->GetContainer(rootContainer);
|
||||
|
||||
if (nsnull != rootContainer)
|
||||
{
|
||||
nsIBrowserWindow *browserWindow;
|
||||
|
||||
if (NS_OK == rootContainer->QueryInterface(kIBrowserWindowIID, (void**)&browserWindow))
|
||||
{
|
||||
nsAutoString msg = nsAutoString(aStatusMsg);
|
||||
|
||||
rv = browserWindow->SetStatus(msg.GetUnicode());
|
||||
NS_RELEASE(browserWindow);
|
||||
}
|
||||
|
||||
NS_RELEASE(rootContainer);
|
||||
}
|
||||
|
||||
NS_RELEASE(rootWebShell);
|
||||
}
|
||||
|
||||
NS_RELEASE(ws);
|
||||
}
|
||||
|
||||
NS_RELEASE(cont);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user