pjs/webshell/embed/gtk/lib/GtkMozillaContainer.cpp

607 строки
14 KiB
C++

/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "MPL"); you may not use this file except in
* compliance with the MPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of the Original Code is Alexander. Portions
* created by Alexander Larsson are Copyright (C) 1999
* Alexander Larsson. All Rights Reserved.
*/
#include "GtkMozillaContainer.h"
#include "nsRepository.h"
#include "nsIBaseWindow.h"
#include "nsIWebShell.h"
#include "nsIURL.h"
#include "nsIIOService.h"
#include "nsIServiceManager.h"
#include "nsNetUtil.h"
#include "nsFileSpec.h"
#include "nsIDocumentLoader.h"
#include "nsIDocumentLoaderFactory.h"
#include "nsIContentViewer.h"
#include "prprf.h"
#include "nsIPref.h"
static NS_DEFINE_CID(kWebShellCID, NS_WEB_SHELL_CID);
static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
GtkMozillaContainer::GtkMozillaContainer(GtkMozilla *moz, nsIPref * aPrefs)
{
mWebShell = nsnull;
width = height = 0;
mStream = nsnull;
mChannel = nsnull;
mLoadGroup = nsnull;
mContext = nsnull;
mMozArea = nsnull;
mSuperWin = nsnull;
mozilla = moz;
gtk_widget_set_app_paintable(GTK_WIDGET(moz), PR_TRUE);
mPrefs = aPrefs;
NS_IF_ADDREF(mPrefs);
}
GtkMozillaContainer::~GtkMozillaContainer(void)
{
NS_IF_RELEASE(mWebShell);
NS_IF_RELEASE(mPrefs);
}
void
GtkMozillaContainer::Show()
{
GtkAllocation *alloc = &GTK_WIDGET(mozilla)->allocation;
// g_print("GtkMozillaContainer::Show\n");
nsresult rv = nsRepository::CreateInstance(kWebShellCID,
nsnull,
NS_GET_IID(nsIWebShell),
(void**) &mWebShell);
if (NS_FAILED(rv) || !mWebShell)
{
printf("Cannot create WebShell!\n");
return;
}
if (mozilla)
{
width = alloc->width;
height = alloc->height;
// we need to create the mozbox here that will shim
// between the superwin and the widget.
mMozArea = gtk_mozarea_new();
gtk_container_add(GTK_CONTAINER(mozilla), mMozArea);
gtk_widget_realize(mMozArea);
gtk_widget_show(mMozArea);
mSuperWin = GTK_MOZAREA(mMozArea)->superwin;
//printf("Init, size: %d, %d\n", width, height);
mWebShell->Init((nsNativeWidget *)mSuperWin,
0,
0,
width,
height);
mWebShell->SetContainer(this);
if(mPrefs)
{
mWebShell->SetPrefs(mPrefs);
}
}
gdk_window_show(mSuperWin->bin_window);
gdk_window_show(mSuperWin->shell_window);
if (mWebShell)
{
nsCOMPtr<nsIBaseWindow> window = do_QueryInterface(mWebShell);
if (window) {
window->SetVisibility(PR_TRUE);
}
}
}
void
GtkMozillaContainer::Resize(gint w, gint h)
{
GtkAllocation alloc;
// g_print("GtkMozillaContainer::Resize called width: %d, %d\n", w, h);
if (mWebShell) {
width = w;
height = h;
//printf("GtkMozillaContainer::Resize setting to: %d, %d\n", width, height);
alloc.x = GTK_WIDGET(mozilla)->allocation.x;
alloc.y = GTK_WIDGET(mozilla)->allocation.y;
alloc.width = w;
alloc.height = h;
// gtk_widget_size_allocate(GTK_WIDGET(mozilla), &alloc);
gdk_superwin_resize(mSuperWin, width, height);
nsCOMPtr<nsIBaseWindow> window = do_QueryInterface(mWebShell);
if (window) {
window->SetPositionAndSize(0, 0, width, height, PR_FALSE);
}
}
}
void
GtkMozillaContainer::LoadURL(const gchar *url)
{
PRUnichar *u_url;
int len, i;
len = strlen(url);
u_url = new (PRUnichar)[len+1];
for (i=0;i<len;i++)
u_url[i] = (PRUnichar) url[i];
u_url[len] = 0;
mWebShell->LoadURL(u_url);
delete [] u_url;
}
void
GtkMozillaContainer::Stop()
{
mWebShell->Stop();
}
void
GtkMozillaContainer::Reload(GtkMozillaReloadType type)
{
mWebShell->Reload((nsLoadFlags)type);
}
gint
GtkMozillaContainer::Back()
{
return NS_SUCCEEDED(mWebShell->Back());
}
gint
GtkMozillaContainer::CanBack()
{
return mWebShell->CanBack()==NS_OK;
}
gint
GtkMozillaContainer::Forward()
{
return NS_SUCCEEDED(mWebShell->Forward());
}
gint
GtkMozillaContainer::CanForward()
{
return mWebShell->CanForward()==NS_OK;
}
gint
GtkMozillaContainer::GoTo(gint history_index)
{
return NS_SUCCEEDED(mWebShell->GoTo((PRInt32)history_index));
}
gint
GtkMozillaContainer::GetHistoryLength()
{
PRInt32 Result;
if (NS_SUCCEEDED(mWebShell->GetHistoryLength(Result)))
return (gint) Result;
else
return 0;
}
gint
GtkMozillaContainer::GetHistoryIndex()
{
PRInt32 Result;
if (NS_SUCCEEDED(mWebShell->GetHistoryIndex(Result)))
return (gint) Result;
else
return 0;
}
NS_IMETHODIMP
GtkMozillaContainer::QueryInterface(REFNSIID aIID, void** aInstancePtr)
{
if (NULL == aInstancePtr) {
return NS_ERROR_NULL_POINTER;
}
nsISupports *ifp = nsnull;
if (aIID.Equals(NS_GET_IID(nsIWebShellContainer))) {
ifp = (nsIWebShellContainer*)this;
} else if(aIID.Equals(NS_GET_IID(nsISupports))) {
ifp = this;
} else {
*aInstancePtr = 0;
return NS_NOINTERFACE;
}
*aInstancePtr = (void *)ifp;
NS_ADDREF(ifp);
return NS_OK;
}
nsrefcnt
GtkMozillaContainer::AddRef()
{
// This object is not reference counted so we just return a number > 0
return 3;
}
nsrefcnt
GtkMozillaContainer::Release()
{
// This object is not reference counted so we just return a number > 0
return 2;
}
static char *simple_unicode_to_char(const PRUnichar* aURL)
{
int i;
int len=0;
const PRUnichar* ptr;
char *str;
ptr=aURL;
while (*ptr++)
len++;
str = (char *)malloc(len+1);
if (str==NULL)
return NULL;
for (i=0;i<len;i++) {
if (aURL[i]<127)
str[i] = (char) aURL[i]&0xff;
else
str[i] = '_';
}
str[len] = 0;
return str;
}
NS_IMETHODIMP
GtkMozillaContainer::WillLoadURL(nsIWebShell* aShell,
const PRUnichar* aURL,
nsLoadType aReason)
{
gint result = 1;
char *url = simple_unicode_to_char(aURL);
gtk_signal_emit_by_name(GTK_OBJECT(mozilla), "will_load_url",
url, (gint) aReason, &result);
if (url)
free(url);
return (result)?NS_OK:NS_ERROR_FAILURE;
}
NS_IMETHODIMP
GtkMozillaContainer::BeginLoadURL(nsIWebShell* aShell, const PRUnichar* aURL)
{
char *url = simple_unicode_to_char(aURL);
gtk_signal_emit_by_name(GTK_OBJECT(mozilla), "begin_load_url", url);
if (url)
free(url);
return NS_OK;
}
NS_IMETHODIMP
GtkMozillaContainer::EndLoadURL(nsIWebShell* aShell,
const PRUnichar* aURL,
nsresult aStatus)
{
char *url = simple_unicode_to_char(aURL);
gtk_signal_emit_by_name(GTK_OBJECT(mozilla), "end_load_url",
url, (gint) aStatus);
if (url)
free(url);
return NS_OK;
}
nsresult
GtkMozillaContainer::CreateContentViewer(const char *aCommand,
nsIChannel *aChannel,
nsILoadGroup *aLoadGroup,
const char *aContentType,
nsIContentViewerContainer* aContainer,
nsISupports* aExtraInfo,
nsIStreamListener** aDocListenerResult,
nsIContentViewer** aDocViewerResult)
{
// Lookup class-id for the command plus content-type combination
nsCID cid;
char id[500];
PR_snprintf(id, sizeof(id),
NS_DOCUMENT_LOADER_FACTORY_PROGID_PREFIX "%s/%s",
aCommand, aContentType);
nsresult rv = nsComponentManager::ProgIDToClassID(id, &cid);
if (NS_FAILED(rv)) {
return rv;
}
// Create an instance of the document-loader-factory object
nsIDocumentLoaderFactory* factory;
rv = nsComponentManager::CreateInstance(cid, (nsISupports *)nsnull,
NS_GET_IID(nsIDocumentLoaderFactory),
(void **)&factory);
if (NS_FAILED(rv)) {
return rv;
}
// Now create an instance of the content viewer
rv = factory->CreateInstance(aCommand,
aChannel,
aLoadGroup,
aContentType,
aContainer,
aExtraInfo,
aDocListenerResult,
aDocViewerResult);
NS_RELEASE(factory);
return rv;
}
NS_IMETHODIMP
GtkMozillaContainer::ProgressLoadURL(nsIWebShell* aShell, const PRUnichar* aURL, PRInt32 aProgress,
PRInt32 aProgressMax)
{
printf("Progress: %d (0..%d)\n", aProgress, aProgressMax);
return NS_OK;
}
NS_IMETHODIMP
GtkMozillaContainer::NewWebShell(PRUint32 aChromeMask, PRBool aVisible, nsIWebShell *&aNewWebShell)
{
printf("NewWebShell\n");
aNewWebShell = nsnull;
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
GtkMozillaContainer::FindWebShellWithName(const PRUnichar* aName, nsIWebShell*& aResult)
{
printf("FindWebShellWithName\n");
aResult = nsnull;
if (NS_OK == mWebShell->FindChildWithName(aName, aResult)) {
if (nsnull != aResult) {
return NS_OK;
}
}
return NS_OK;
}
NS_IMETHODIMP
GtkMozillaContainer::ContentShellAdded(nsIWebShell* aChildShell, nsIContent* frameNode)
{
printf("ContentShellAdded\n");
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
GtkMozillaContainer::CreatePopup(nsIDOMElement* aElement, nsIDOMElement* aPopupContent,
PRInt32 aXPos, PRInt32 aYPos,
const nsString& aPopupType,
const nsString& anAnchorAlignment,
const nsString& aPopupAlignment,
nsIDOMWindow* aWindow,
nsIDOMWindow** outPopup)
{
printf("CreatePopup\n");
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
GtkMozillaContainer::CanCreateNewWebShell(PRBool& aResult)
{
printf("CanCreateNewWebShell\n");
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
GtkMozillaContainer::SetNewWebShellInfo(const nsString& aName, const nsString& anURL,
nsIWebShell* aOpenerShell, PRUint32 aChromeMask,
nsIWebShell** aNewShell, nsIWebShell** anInnerShell)
{
printf("SetNewWebShellInfo\n");
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
GtkMozillaContainer::ChildShellAdded(nsIWebShell** aChildShell, nsIContent* frameNode)
{
printf("ChildShellAdded\n");
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
GtkMozillaContainer::FocusAvailable(nsIWebShell* aFocusedWebShell, PRBool& aFocusTaken)
{
printf("FocusAvailable\n");
return NS_ERROR_FAILURE;
}
gint
GtkMozillaContainer::StartStream(const char *base_url,
const char *action,
nsISupports * ctxt,
const char *content_type)
{
nsresult rv = NS_OK;
nsIURI* url = nsnull;
nsIContentViewer* viewer = nsnull;
nsString url_str(base_url);
nsIInputStream *istream = NULL;
mStream = new GtkMozillaInputStream();
if (mStream == nsnull)
goto error;
NS_ADDREF(mStream); /* Own this */
rv = CallQueryInterface(mStream, &istream);
if (NS_FAILED(rv))
goto error;
rv = NS_NewURI(&url, url_str, NULL);
if (NS_FAILED(rv))
goto error;
rv = NS_NewLoadGroup(nsnull, &mLoadGroup);
if (NS_FAILED(rv))
goto error;
rv = NS_NewInputStreamChannel(url, content_type,
1024/*len*/, istream,
mLoadGroup,
nsnull, // notificationCallbacks
nsIChannel::LOAD_NORMAL,
nsnull, 0, 0, &mChannel);
if (NS_FAILED(rv))
goto error;
NS_RELEASE(istream);
rv = CreateContentViewer(action, mChannel, mLoadGroup, content_type,
mWebShell, nsnull, &mListener, &viewer);
if (NS_FAILED(rv)) {
printf("GtkMozillaContainer: Unable to create ContentViewer for action=%s, content-type=%s\n", action, content_type);
goto error;
}
rv = viewer->SetContainer((nsIContentViewerContainer*)mWebShell);
if (NS_FAILED(rv))
goto error;
rv = mWebShell->Embed(viewer, action, nsnull);
if (NS_FAILED(rv))
goto error;
/*
* Pass the OnStartRequest(...) notification out to the document
* IStreamListener.
*/
rv = mListener->OnStartRequest(mChannel, ctxt);
if (NS_FAILED(rv))
goto error;
mContext = ctxt;
NS_IF_RELEASE(viewer);
if (NS_SUCCEEDED(rv))
return 0;
else
return -1;
error:
if (mStream != NULL) {
delete mStream;
mStream = NULL;
}
NS_IF_RELEASE(istream);
NS_IF_RELEASE(url);
NS_IF_RELEASE(mLoadGroup);
NS_IF_RELEASE(mChannel);
NS_IF_RELEASE(viewer);
NS_IF_RELEASE(mListener);
return -1;
}
gint
GtkMozillaContainer::WriteStream(const char *data,
gint offset,
gint len)
{
nsresult rv = NS_OK;
PRUint32 Count;
mStream->Fill(data, len);
rv = mListener->OnDataAvailable(mChannel,
mContext,
mStream,
offset,
len);
if (NS_FAILED(rv))
return 0;
// Busted in NECKO
// rv = mListener->OnProgress(mChannel, len, len+1);
if (NS_FAILED(rv))
return 0;
mStream->FillResult(&Count);
return (gint) Count;
}
void
GtkMozillaContainer::EndStream(void)
{
nsresult rv = NS_OK;
mStream->Fill(NULL, 0);
rv = mListener->OnDataAvailable(mChannel,
mContext,
mStream,
0,
0);
if (NS_FAILED(rv))
return;
rv = mListener->OnStopRequest(mChannel,
mContext,
NS_OK,
NULL);
if (NS_FAILED(rv))
return;
// Busted in NECKO
// rv = mListener->OnProgress(mChannel, 10, 10);
if (NS_FAILED(rv))
return;
NS_IF_RELEASE(mChannel);
NS_IF_RELEASE(mLoadGroup);
NS_IF_RELEASE(mListener);
NS_IF_RELEASE(mStream);
}