diff --git a/mozilla/embedding/browser/gtk/src/GtkMozEmbedChrome.cpp b/mozilla/embedding/browser/gtk/src/GtkMozEmbedChrome.cpp index 1dbb16a6d63..094d7782987 100644 --- a/mozilla/embedding/browser/gtk/src/GtkMozEmbedChrome.cpp +++ b/mozilla/embedding/browser/gtk/src/GtkMozEmbedChrome.cpp @@ -20,11 +20,19 @@ */ #include "GtkMozEmbedChrome.h" +#include "GtkMozEmbedStream.h" #include "nsCWebBrowser.h" #include "nsIURI.h" +#include "nsNetUtil.h" #include "nsIDocShellTreeItem.h" #include "nsCRT.h" #include "prlog.h" +#include "prprf.h" +#include "nsIDocumentLoaderFactory.h" +#include "nsIContentViewerContainer.h" +#include "nsIDocShell.h" + +static NS_DEFINE_CID(kSimpleURICID, NS_SIMPLEURI_CID); // this is a define to make sure that we don't call certain function // before the object has been properly initialized @@ -73,6 +81,8 @@ GtkMozEmbedChrome::GtkMozEmbedChrome() mLocation = NULL; mTitle = NULL; mChromeMask = 0; + mOffset = 0; + mDoingStream = PR_FALSE; if (!mozEmbedLm) mozEmbedLm = PR_NewLogModule("GtkMozEmbedChrome"); if (!sBrowsers) @@ -223,6 +233,157 @@ NS_IMETHODIMP GtkMozEmbedChrome::GetTitleChar (char **retval) return NS_OK; } +NS_IMETHODIMP GtkMozEmbedChrome::OpenStream (const char *aBaseURI, const char *aContentType) +{ + NS_ENSURE_ARG_POINTER(aBaseURI); + NS_ENSURE_ARG_POINTER(aContentType); + + nsresult rv = NS_OK; + GtkMozEmbedStream *newStream = nsnull; + + nsCOMPtr docLoaderFactory; + nsCOMPtr docShell; + nsCOMPtr viewerContainer; + nsCOMPtr contentViewer; + nsCOMPtr uri; + nsCAutoString docLoaderProgID; + nsCAutoString spec(aBaseURI); + + // check to see if we need to close the current stream + if (mDoingStream) + CloseStream(); + mDoingStream = PR_TRUE; + // create our new stream object + newStream = new GtkMozEmbedStream(); + if (!newStream) + return NS_ERROR_OUT_OF_MEMORY; + // we own this + NS_ADDREF(newStream); + // QI it to the right interface + mStream = do_QueryInterface(newStream); + if (!mStream) + return NS_ERROR_FAILURE; + // ok, now we're just using it for an nsIInputStream interface so + // release our second reference to it. + NS_RELEASE(newStream); + + // get our hands on the docShell + mWebBrowser->GetDocShell(getter_AddRefs(docShell)); + if (!docShell) + return NS_ERROR_FAILURE; + + // QI that to a content viewer container + viewerContainer = do_QueryInterface(docShell); + if (!viewerContainer) + return NS_ERROR_FAILURE; + + // create a new uri object + uri = do_CreateInstance(kSimpleURICID, &rv); + if (NS_FAILED(rv)) + return rv; + rv = uri->SetSpec(spec.GetBuffer()); + if (NS_FAILED(rv)) + return rv; + + // create a new load group + rv = NS_NewLoadGroup(getter_AddRefs(mLoadGroup), nsnull); + if (NS_FAILED(rv)) + return rv; + + // create a new input stream channel + rv = NS_NewInputStreamChannel(getter_AddRefs(mChannel), uri, mStream, aContentType, + 1024 /* len */); + if (NS_FAILED(rv)) + return rv; + + // set the channel's load group + rv = mChannel->SetLoadGroup(mLoadGroup); + if (NS_FAILED(rv)) + return rv; + + // find a document loader for this command plus content type + // combination + + docLoaderProgID = NS_DOCUMENT_LOADER_FACTORY_PROGID_PREFIX; + docLoaderProgID += "view"; + docLoaderProgID += "/"; + docLoaderProgID += aContentType; + + docLoaderFactory = do_CreateInstance(docLoaderProgID, &rv); + if (NS_FAILED(rv)) + return rv; + + // ok, create an instance of the content viewer for that command and + // mime type + rv = docLoaderFactory->CreateInstance("view", + mChannel, + mLoadGroup, + aContentType, + viewerContainer, + nsnull, + getter_AddRefs(mStreamListener), + getter_AddRefs(contentViewer)); + + if (NS_FAILED(rv)) + return rv; + + // set the container viewer container for this content view + rv = contentViewer->SetContainer(viewerContainer); + if (NS_FAILED(rv)) + return rv; + + // embed this sucker. + rv = viewerContainer->Embed(contentViewer, "view", nsnull); + if (NS_FAILED(rv)) + return rv; + + // start our request + rv = mStreamListener->OnStartRequest(mChannel, NULL); + if (NS_FAILED(rv)) + return rv; + + return NS_OK; +} + +NS_IMETHODIMP GtkMozEmbedChrome::AppendToStream (const char *aData, gint32 aLen) +{ + GtkMozEmbedStream *embedStream = (GtkMozEmbedStream *)mStream.get(); + nsresult rv; + NS_ENSURE_STATE(mDoingStream); + rv = embedStream->Append(aData, aLen); + if (NS_FAILED(rv)) + return rv; + rv = mStreamListener->OnDataAvailable(mChannel, + NULL, + mStream, + mOffset, /* offset */ + aLen); /* len */ + mOffset += aLen; + if (NS_FAILED(rv)) + return rv; + return NS_OK; +} + +NS_IMETHODIMP GtkMozEmbedChrome::CloseStream (void) +{ + nsresult rv; + NS_ENSURE_STATE(mDoingStream); + mDoingStream = PR_FALSE; + rv = mStreamListener->OnStopRequest(mChannel, + NULL, + NS_OK, + NULL); + if (NS_FAILED(rv)) + return rv; + mStream = nsnull; + mLoadGroup = nsnull; + mChannel = nsnull; + mStreamListener = nsnull; + mContentViewer = nsnull; + mOffset = 0; + return NS_OK; +} + // nsIInterfaceRequestor interface NS_IMETHODIMP GtkMozEmbedChrome::GetInterface(const nsIID &aIID, void** aInstancePtr) diff --git a/mozilla/embedding/browser/gtk/src/GtkMozEmbedChrome.h b/mozilla/embedding/browser/gtk/src/GtkMozEmbedChrome.h index 3b950c1731e..211d2d791ac 100644 --- a/mozilla/embedding/browser/gtk/src/GtkMozEmbedChrome.h +++ b/mozilla/embedding/browser/gtk/src/GtkMozEmbedChrome.h @@ -33,6 +33,11 @@ #include "nsIWebProgressListener.h" #include "nsIWebProgress.h" #include "nsIInterfaceRequestor.h" +#include "nsIInputStream.h" +#include "nsILoadGroup.h" +#include "nsIChannel.h" +#include "nsIContentViewer.h" +#include "nsIStreamListener.h" // utility classes #include "nsXPIDLString.h" @@ -70,6 +75,9 @@ public: NS_IMETHOD GetJSStatus (char **retval); NS_IMETHOD GetLocation (char **retval); NS_IMETHOD GetTitleChar (char **retval); + NS_IMETHOD OpenStream (const char *aBaseURI, const char *aContentType); + NS_IMETHOD AppendToStream (const char *aData, gint32 aLen); + NS_IMETHOD CloseStream (void); NS_DECL_ISUPPORTS @@ -113,6 +121,13 @@ private: nsString mTitleUnicode; PRUint32 mChromeMask; static nsVoidArray *sBrowsers; + nsCOMPtr mStream; + nsCOMPtr mLoadGroup; + nsCOMPtr mChannel; + nsCOMPtr mContentViewer; + nsCOMPtr mStreamListener; + PRUint32 mOffset; + PRBool mDoingStream; }; #endif /* __GtkMozEmbedChrome_h */ diff --git a/mozilla/embedding/browser/gtk/src/GtkMozEmbedStream.cpp b/mozilla/embedding/browser/gtk/src/GtkMozEmbedStream.cpp new file mode 100644 index 00000000000..8cc94cefada --- /dev/null +++ b/mozilla/embedding/browser/gtk/src/GtkMozEmbedStream.cpp @@ -0,0 +1,149 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is Christopher Blizzard. + * Portions created by Christopher Blizzard are Copyright (C) + * Christopher Blizzard. All Rights Reserved. + * + * Contributor(s): + * Christopher Blizzard + */ + +#include "GtkMozEmbedStream.h" +#include "nsIAllocator.h" + +// nsIInputStream interface + +NS_IMPL_ADDREF(GtkMozEmbedStream) +NS_IMPL_RELEASE(GtkMozEmbedStream) + +NS_INTERFACE_MAP_BEGIN(GtkMozEmbedStream) + NS_INTERFACE_MAP_ENTRY(nsISupports) + NS_INTERFACE_MAP_ENTRY(nsIInputStream) +NS_INTERFACE_MAP_END + +GtkMozEmbedStream::GtkMozEmbedStream() +{ + NS_INIT_REFCNT(); + mLength = 0; + mBuffer = 0; +} + +GtkMozEmbedStream::~GtkMozEmbedStream() +{ + if (mBuffer) + nsAllocator::Free(mBuffer); +} + +NS_IMETHODIMP GtkMozEmbedStream::Available(PRUint32 *_retval) +{ + NS_ENSURE_ARG_POINTER(_retval); + *_retval = mLength; + return NS_OK; +} + +NS_IMETHODIMP GtkMozEmbedStream::Read(char * aBuf, PRUint32 aCount, PRUint32 *_retval) +{ + PRUint32 bytesToRead; + + NS_ENSURE_ARG_POINTER(aBuf); + NS_ENSURE_ARG_POINTER(_retval); + *_retval = 0; + + // shortcut? + if (aCount == 0) + return NS_OK; + + // check to see how many bytes we can read + if (aCount > mLength) + bytesToRead = mLength; + else + bytesToRead = aCount; + + // copy our data + *_retval = bytesToRead; + memcpy(aBuf, mBuffer, bytesToRead); + + // see if we can truncate the buffer entirely + if (bytesToRead == mBufLen) + { + mBuffer = nsnull; + mLength = 0; + mBufLen = 0; + return NS_OK; + } + // truncate it some, then + memmove(mBuffer, &mBuffer[bytesToRead], (mLength - bytesToRead)); + mLength -= bytesToRead; + + return NS_OK; +} + +// nsIBaseStream interface + +NS_IMETHODIMP GtkMozEmbedStream::Close(void) +{ + if (mBuffer) + nsAllocator::Free(mBuffer); + mLength = 0; + mBufLen = 0; + return NS_OK; +} + +NS_METHOD GtkMozEmbedStream::Append(const char *aData, PRUint32 aLen) +{ + // shortcut? + if (aLen == 0 || aData == NULL) + return NS_OK; + mLength += aLen; + // first time + if (!mBuffer) + { + mBuffer = (char *)nsAllocator::Alloc(mLength); + mBufLen = mLength; + if (!mBuffer) + { + mLength = 0; + mBufLen = 0; + return NS_ERROR_OUT_OF_MEMORY; + } + memcpy(mBuffer, aData, aLen); + return NS_OK; + } + else + { + // see if we need to realloc + if (mLength > mBufLen) + { + char *newBuffer; + newBuffer = (char *)nsAllocator::Realloc(mBuffer, mLength); + if (!newBuffer) + { + mLength = 0; + mBufLen = 0; + nsAllocator::Free(mBuffer); + mBuffer = NULL; + return NS_ERROR_OUT_OF_MEMORY; + } + mBuffer = newBuffer; + mBufLen = mLength; + memcpy(&mBuffer[mLength - aLen], aData, aLen); + } + else + // no realloc required and don't have to update mBufLen, just + // update + memcpy(&mBuffer[mLength - aLen], aData, aLen); + } + + return NS_OK; +} diff --git a/mozilla/embedding/browser/gtk/src/GtkMozEmbedStream.h b/mozilla/embedding/browser/gtk/src/GtkMozEmbedStream.h new file mode 100644 index 00000000000..c122ad774c3 --- /dev/null +++ b/mozilla/embedding/browser/gtk/src/GtkMozEmbedStream.h @@ -0,0 +1,46 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is Christopher Blizzard. + * Portions created by Christopher Blizzard are Copyright (C) + * Christopher Blizzard. All Rights Reserved. + * + * Contributor(s): + * Christopher Blizzard + */ + +#include "nsISupports.h" +#include "nsIInputStream.h" + +class GtkMozEmbedStream : public nsIInputStream +{ + public: + + GtkMozEmbedStream(); + virtual ~GtkMozEmbedStream(); + + // nsISupports + NS_DECL_ISUPPORTS + // nsIInputStream + NS_DECL_NSIINPUTSTREAM + // nsIBaseStream + NS_DECL_NSIBASESTREAM + + NS_METHOD Append(const char *aData, PRUint32 aLen); + + private: + + char * mBuffer; + PRUint32 mLength; + PRUint32 mBufLen; +}; diff --git a/mozilla/embedding/browser/gtk/src/Makefile.in b/mozilla/embedding/browser/gtk/src/Makefile.in index b9a5e750441..93a0b546b2f 100644 --- a/mozilla/embedding/browser/gtk/src/Makefile.in +++ b/mozilla/embedding/browser/gtk/src/Makefile.in @@ -31,6 +31,7 @@ REQUIRES = xpcom CPPSRCS = \ GtkMozEmbedChrome.cpp \ + GtkMozEmbedStream.cpp \ nsSetupRegistry.cpp \ gtkmozembed.cpp diff --git a/mozilla/embedding/browser/gtk/src/gtkmozembed.cpp b/mozilla/embedding/browser/gtk/src/gtkmozembed.cpp index 91fea25faf7..0696f076263 100644 --- a/mozilla/embedding/browser/gtk/src/gtkmozembed.cpp +++ b/mozilla/embedding/browser/gtk/src/gtkmozembed.cpp @@ -447,6 +447,63 @@ gtk_moz_embed_go_forward (GtkMozEmbed *embed) embed_private->navigation->GoForward(); } +void +gtk_moz_embed_render_data (GtkMozEmbed *embed, + const char *data, guint32 len, + const char *base_uri, const char *mime_type) +{ + GtkMozEmbedPrivate *embed_private; + + g_return_if_fail (embed != NULL); + g_return_if_fail (GTK_IS_MOZ_EMBED(embed)); + + embed_private = (GtkMozEmbedPrivate *)embed->data; + + embed_private->embed->OpenStream(base_uri, mime_type); + embed_private->embed->AppendToStream(data, len); + embed_private->embed->CloseStream(); +} + +void +gtk_moz_embed_open_stream (GtkMozEmbed *embed, + const char *base_uri, const char *mime_type) +{ + GtkMozEmbedPrivate *embed_private; + + g_return_if_fail (embed != NULL); + g_return_if_fail (GTK_IS_MOZ_EMBED(embed)); + + embed_private = (GtkMozEmbedPrivate *)embed->data; + + embed_private->embed->OpenStream(base_uri, mime_type); +} + +void +gtk_moz_embed_append_data (GtkMozEmbed *embed, const char *data, guint32 len) +{ + GtkMozEmbedPrivate *embed_private; + + g_return_if_fail (embed != NULL); + g_return_if_fail (GTK_IS_MOZ_EMBED(embed)); + + embed_private = (GtkMozEmbedPrivate *)embed->data; + + embed_private->embed->AppendToStream(data, len); +} + +void +gtk_moz_embed_close_stream (GtkMozEmbed *embed) +{ + GtkMozEmbedPrivate *embed_private; + + g_return_if_fail (embed != NULL); + g_return_if_fail (GTK_IS_MOZ_EMBED(embed)); + + embed_private = (GtkMozEmbedPrivate *)embed->data; + + embed_private->embed->CloseStream(); +} + void gtk_moz_embed_reload (GtkMozEmbed *embed, gint32 flags) { diff --git a/mozilla/embedding/browser/gtk/src/gtkmozembed.h b/mozilla/embedding/browser/gtk/src/gtkmozembed.h index bbca00f22dd..97ebcac3445 100644 --- a/mozilla/embedding/browser/gtk/src/gtkmozembed.h +++ b/mozilla/embedding/browser/gtk/src/gtkmozembed.h @@ -69,6 +69,14 @@ extern gboolean gtk_moz_embed_can_go_back (GtkMozEmbed *embed); extern gboolean gtk_moz_embed_can_go_forward (GtkMozEmbed *embed); extern void gtk_moz_embed_go_back (GtkMozEmbed *embed); extern void gtk_moz_embed_go_forward (GtkMozEmbed *embed); +extern void gtk_moz_embed_render_data (GtkMozEmbed *embed, + const char *data, guint32 len, + const char *base_uri, const char *mime_type); +extern void gtk_moz_embed_open_stream (GtkMozEmbed *embed, + const char *base_uri, const char *mime_type); +extern void gtk_moz_embed_append_data (GtkMozEmbed *embed, + const char *data, guint32 len); +extern void gtk_moz_embed_close_stream (GtkMozEmbed *embed); extern char *gtk_moz_embed_get_link_message (GtkMozEmbed *embed); extern char *gtk_moz_embed_get_js_status (GtkMozEmbed *embed); extern char *gtk_moz_embed_get_title (GtkMozEmbed *embed); diff --git a/mozilla/embedding/browser/gtk/src/nsIGtkEmbed.h b/mozilla/embedding/browser/gtk/src/nsIGtkEmbed.h index ddceaf0f3a4..7682fe2c5f6 100644 --- a/mozilla/embedding/browser/gtk/src/nsIGtkEmbed.h +++ b/mozilla/embedding/browser/gtk/src/nsIGtkEmbed.h @@ -62,6 +62,9 @@ public: NS_IMETHOD GetJSStatus (char **retval) = 0; NS_IMETHOD GetLocation (char **retval) = 0; NS_IMETHOD GetTitleChar (char **retval) = 0; + NS_IMETHOD OpenStream (const char *aBaseURI, const char *aContentType) = 0; + NS_IMETHOD AppendToStream (const char *aData, gint32 aLen) = 0; + NS_IMETHOD CloseStream (void) = 0; }; #endif /* __nsIGtkEmbed_h__ */ diff --git a/mozilla/embedding/browser/gtk/tests/TestGtkEmbed.cpp b/mozilla/embedding/browser/gtk/tests/TestGtkEmbed.cpp index 574d5b88902..924b79b4c88 100644 --- a/mozilla/embedding/browser/gtk/tests/TestGtkEmbed.cpp +++ b/mozilla/embedding/browser/gtk/tests/TestGtkEmbed.cpp @@ -32,6 +32,7 @@ typedef struct _TestGtkBrowser { GtkWidget *stopButton; GtkWidget *forwardButton; GtkWidget *reloadButton; + GtkWidget *streamButton; GtkWidget *urlEntry; GtkWidget *mozEmbed; GtkWidget *progressAreaHBox; @@ -53,6 +54,7 @@ static void back_clicked_cb (GtkButton *button, TestGtkBrowser *browser static void stop_clicked_cb (GtkButton *button, TestGtkBrowser *browser); static void forward_clicked_cb (GtkButton *button, TestGtkBrowser *browser); static void reload_clicked_cb (GtkButton *button, TestGtkBrowser *browser); +static void stream_clicked_cb (GtkButton *button, TestGtkBrowser *browser); static void url_activate_cb (GtkEditable *widget, TestGtkBrowser *browser); static gboolean delete_cb (GtkWidget *widget, GdkEventAny *event, TestGtkBrowser *browser); @@ -158,6 +160,14 @@ new_gtk_browser(guint32 chromeMask) 0, // XXX replace with icon GTK_SIGNAL_FUNC(reload_clicked_cb), browser); + // new stream button + browser->streamButton = gtk_toolbar_append_item(GTK_TOOLBAR(browser->toolbar), + "Stream", + "Stream", + "Stream", + 0, // XXX replace with icon + GTK_SIGNAL_FUNC(stream_clicked_cb), + browser); // create the url text entry browser->urlEntry = gtk_entry_new(); // add it to the hbox @@ -263,15 +273,31 @@ stop_clicked_cb (GtkButton *button, TestGtkBrowser *browser) void forward_clicked_cb (GtkButton *button, TestGtkBrowser *browser) { + g_print("forward_clicked_cb\n"); gtk_moz_embed_go_forward(GTK_MOZ_EMBED(browser->mozEmbed)); } void reload_clicked_cb (GtkButton *button, TestGtkBrowser *browser) { + g_print("reload_clicked_cb\n"); gtk_moz_embed_reload(GTK_MOZ_EMBED(browser->mozEmbed), gtk_moz_embed_flag_reloadNormal); } +void +stream_clicked_cb (GtkButton *button, TestGtkBrowser *browser) +{ + char *data; + char *data2; + data = "Hi"; + data2 = " there\n"; + g_print("stream_clicked_cb\n"); + gtk_moz_embed_open_stream(GTK_MOZ_EMBED(browser->mozEmbed), "file://", "text/html"); + gtk_moz_embed_append_data(GTK_MOZ_EMBED(browser->mozEmbed), data, strlen(data)); + gtk_moz_embed_append_data(GTK_MOZ_EMBED(browser->mozEmbed), data2, strlen(data2)); + gtk_moz_embed_close_stream(GTK_MOZ_EMBED(browser->mozEmbed)); +} + void url_activate_cb (GtkEditable *widget, TestGtkBrowser *browser) {