Back to index

lightning-sunbird  0.9+nobinonly
MRJNetworking.cpp
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is mozilla.org code.
00015  *
00016  * The Initial Developer of the Original Code is
00017  * Netscape Communications Corporation.
00018  * Portions created by the Initial Developer are Copyright (C) 1998
00019  * the Initial Developer. All Rights Reserved.
00020  *
00021  * Contributor(s):
00022  *
00023  * Alternatively, the contents of this file may be used under the terms of
00024  * either of the GNU General Public License Version 2 or later (the "GPL"),
00025  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00026  * in which case the provisions of the GPL or the LGPL are applicable instead
00027  * of those above. If you wish to allow use of your version of this file only
00028  * under the terms of either the GPL or the LGPL, and not to allow others to
00029  * use your version of this file under the terms of the MPL, indicate your
00030  * decision by deleting the provisions above and replace them with the notice
00031  * and other provisions required by the GPL or the LGPL. If you do not delete
00032  * the provisions above, a recipient may use your version of this file under
00033  * the terms of any one of the MPL, the GPL or the LGPL.
00034  *
00035  * ***** END LICENSE BLOCK ***** */
00036 
00037 /*
00038     MRJNetworking.cpp
00039     
00040     by Patrick C. Beard.
00041  */
00042 
00043 #include <TextCommon.h>
00044 #include <JManager.h>
00045 #include "JMURLConnection.h"
00046 
00047 #include "MRJNetworking.h"
00048 #include "MRJContext.h"
00049 #include "MRJPlugin.h"
00050 #include "MRJSession.h"
00051 #include "MRJMonitor.h"
00052 #include "nsIPluginManager2.h"
00053 
00054 #include <vector>
00055 
00056 extern nsIPluginManager* thePluginManager;              // now in badaptor.cpp.
00057 extern nsIPluginManager2* thePluginManager2;
00058 
00059 static char* JMTextToEncoding(JMTextRef textRef, JMTextEncoding encoding)
00060 {
00061        UInt32 length = 0;
00062     OSStatus status = ::JMGetTextLengthInBytes(textRef, encoding, &length);
00063     if (status != noErr)
00064         return NULL;
00065     char* text = new char[length + 1];
00066     if (text != NULL) {
00067         UInt32 actualLength;
00068        status = ::JMGetTextBytes(textRef, encoding, text, length, &actualLength);
00069            if (status != noErr) {
00070                delete text;
00071                return NULL;
00072            }
00073            text[length] = '\0';
00074     }
00075     return text;
00076 }
00077 
00078 class MRJInputStream : public nsIPluginStreamListener {
00079     MRJMonitor mMonitor;
00080     typedef std::vector<char> buffer_t;
00081     buffer_t mBuffer;
00082     size_t mOffset;
00083     bool mComplete;
00084 public:
00085     NS_DECL_ISUPPORTS
00086 
00087     MRJInputStream(MRJSession* session)
00088         :   mMonitor(session), mOffset(0), mComplete(false)
00089     {
00090         mBuffer.reserve(8192);
00091     }
00092     
00093     NS_IMETHOD
00094     OnStartBinding(nsIPluginStreamInfo* pluginInfo)
00095     {
00096         return NS_OK;
00097     }
00098 
00099     NS_IMETHOD
00100     OnDataAvailable(nsIPluginStreamInfo* pluginInfo, nsIInputStream* input, PRUint32 length);
00101 
00102     NS_IMETHOD
00103     OnFileAvailable(nsIPluginStreamInfo* pluginInfo, const char* fileName)
00104     {
00105         return NS_OK;
00106     }
00107  
00108     NS_IMETHOD
00109     OnStopBinding(nsIPluginStreamInfo* pluginInfo, nsresult status)
00110     {
00111         if (!mComplete) {
00112             mComplete = true;
00113             mMonitor.notify();
00114         }
00115         return NS_OK;
00116     }
00117     
00118     NS_IMETHOD
00119     GetStreamType(nsPluginStreamType *result)
00120     {
00121         *result = nsPluginStreamType_Normal;
00122         return NS_OK;
00123     }
00124 
00125     OSStatus read(void* buffer, SInt32 bufferSize, SInt32* bytesRead);
00126 };
00127 NS_IMPL_ISUPPORTS1(MRJInputStream, nsIPluginStreamListener)
00128 
00129 NS_IMETHODIMP
00130 MRJInputStream::OnDataAvailable(nsIPluginStreamInfo* pluginInfo, nsIInputStream* input, PRUint32 length)
00131 {
00132     size_t oldSize = mBuffer.size();
00133     mBuffer.resize(oldSize + length);
00134     buffer_t::iterator buffer = mBuffer.begin() + oldSize;
00135     input->Read(buffer, length, &length);
00136     mMonitor.notify();
00137     return NS_OK;
00138 }
00139 
00140 OSStatus MRJInputStream::read(void* buffer, SInt32 bufferSize, SInt32* bytesRead)
00141 {
00142     size_t sz = mBuffer.size();
00143     while (mOffset >= sz && !mComplete) {
00144         // wait until there is some data to read.
00145         mMonitor.wait();
00146         sz = mBuffer.size();
00147     }
00148     
00149     SInt32 available = (sz - mOffset);
00150     if (bufferSize > available)
00151         bufferSize = available;
00152 
00153     if (bufferSize <= 0 && mComplete) {
00154         *bytesRead = 0;
00155         return noErr;
00156     }
00157 
00158     ::BlockMoveData(mBuffer.begin() + mOffset, buffer, bufferSize);
00159     *bytesRead = bufferSize;
00160     mOffset += bufferSize;
00161     
00162     return noErr;
00163 }
00164 
00165 class MRJURLConnection {
00166 public:
00167     MRJURLConnection(JMTextRef url, JMTextRef requestMethod,
00168                      JMURLConnectionOptions options,
00169                      JMAppletViewerRef appletViewer);
00170 
00171     ~MRJURLConnection();
00172 
00173     MRJPluginInstance* getInstance();
00174     const char* getURL();
00175     const char* getRequestMethod();
00176     Boolean getUsingProxy();
00177 
00178 private:
00179     MRJPluginInstance* mInstance;
00180     char* mURL;
00181     char* mRequestMethod;
00182     JMURLConnectionOptions mOptions;
00183     Boolean mUsingProxy;
00184 };
00185 
00186 MRJURLConnection::MRJURLConnection(JMTextRef url, JMTextRef requestMethod,
00187                                    JMURLConnectionOptions options,
00188                                    JMAppletViewerRef appletViewer)
00189     :   mInstance(0), mURL(0), mRequestMethod(0), mOptions(options), mUsingProxy(false)
00190 {
00191     MRJPluginInstance* instance = MRJPluginInstance::getInstances();
00192     if (appletViewer != NULL) {
00193         while (instance != NULL) {
00194             MRJContext* context = instance->getContext();
00195             if (context->getViewerRef() == appletViewer) {
00196                 mInstance = instance;
00197                 break;
00198             }
00199             instance = instance->getNextInstance();
00200         }
00201     } else {
00202         // any instance will do?
00203         mInstance = instance;
00204         NS_IF_ADDREF(instance);
00205     }
00206     
00207     TextEncoding utf8 = ::CreateTextEncoding(kTextEncodingUnicodeDefault,
00208                                              kTextEncodingDefaultVariant,
00209                                              kUnicodeUTF8Format);
00210     
00211     // pull the text out of the url and requestMethod.
00212     mURL = ::JMTextToEncoding(url, utf8);
00213     mRequestMethod = ::JMTextToEncoding(requestMethod, utf8);
00214     
00215     // see if a proxy will be used for this URL.
00216     if (thePluginManager2 != NULL) {
00217         char* proxyForURL = NULL;
00218         if (thePluginManager2->FindProxyForURL(mURL, &proxyForURL) == NS_OK) {
00219             mUsingProxy = (::strcmp("DIRECT", proxyForURL) != 0);
00220             delete[] proxyForURL;
00221         }
00222     }
00223 }
00224 
00225 MRJURLConnection::~MRJURLConnection()
00226 {
00227     delete[] mURL;
00228     delete[] mRequestMethod;
00229 }
00230 
00231 inline MRJPluginInstance* MRJURLConnection::getInstance()
00232 {
00233     return mInstance;
00234 }
00235 
00236 inline const char* MRJURLConnection::getURL()
00237 {
00238     return mURL;
00239 }
00240 
00241 inline const char* MRJURLConnection::getRequestMethod()
00242 {
00243     return mRequestMethod;
00244 }
00245 
00246 inline Boolean MRJURLConnection::getUsingProxy()
00247 {
00248     return mUsingProxy;
00249 }
00250 
00251 static OSStatus openConnection(
00252        /* in URL = */ JMTextRef url,
00253        /* in RequestMethod = */ JMTextRef requestMethod,
00254        /* in ConnectionOptions = */ JMURLConnectionOptions options,
00255        /* in AppletViewer = */ JMAppletViewerRef appletViewer,
00256        /* out URLConnectionRef = */ JMURLConnectionRef* urlConnectionRef
00257        )
00258 {
00259     MRJURLConnection* connection = new MRJURLConnection(url, requestMethod,
00260                                                         options, appletViewer);
00261     *urlConnectionRef = connection;
00262     return noErr;
00263 }
00264 
00265 static OSStatus closeConnection(
00266        /* in URLConnectionRef = */ JMURLConnectionRef urlConnectionRef
00267        )
00268 {
00269     MRJURLConnection* connection = reinterpret_cast<MRJURLConnection*>(urlConnectionRef);
00270     delete connection;
00271     return noErr;
00272 }
00273 
00274 static Boolean usingProxy(
00275        /* in URLConnectionRef = */ JMURLConnectionRef urlConnectionRef
00276        )
00277 {
00278     MRJURLConnection* connection = reinterpret_cast<MRJURLConnection*>(urlConnectionRef);
00279     return connection->getUsingProxy();
00280 }
00281 
00282 static OSStatus getCookie(
00283        /* in URLConnectionRef = */ JMURLConnectionRef urlConnectionRef,
00284        /* out CookieValue = */ JMTextRef* cookie
00285        )
00286 {
00287     return paramErr;
00288 }
00289 
00290 static OSStatus setCookie(
00291        /* in URLConnectionRef = */ JMURLConnectionRef urlConnectionRef,
00292        /* in CookieValue = */ JMTextRef cookie
00293        )
00294 {
00295     return paramErr;
00296 }
00297 
00298 static OSStatus setRequestProperties(
00299        /* in URLConnectionRef = */ JMURLConnectionRef urlConnectionRef,
00300        /* in NumberOfProperties = */ int numberOfProperties,
00301        /* in PropertyNames = */ JMTextRef* keys,
00302        /* in Values = */ JMTextRef* value
00303        )
00304 {
00305     return paramErr;
00306 }
00307 
00308 static OSStatus getResponsePropertiesCount(
00309        /* in URLConnectionRef = */ JMURLInputStreamRef urlInputStreamRef,
00310        /* out numberOfProperties = */ int* numberOfProperties
00311        )
00312 {
00313     if (numberOfProperties == NULL)
00314         return paramErr;
00315     *numberOfProperties = 0;
00316     return noErr;
00317 }
00318 
00319 static OSStatus getResponseProperties(
00320        /* in URLConnectionRef = */ JMURLInputStreamRef urlInputStreamRef,
00321        /* in numberOfProperties = */ int numberOfProperties,
00322        /* out PropertyNames = */ JMTextRef* keys,
00323        /* out Values = */ JMTextRef* values
00324        )
00325 {
00326     return noErr;
00327 }
00328 
00329 static OSStatus openInputStream(
00330        /* in URLConnectionRef = */ JMURLConnectionRef urlConnectionRef,
00331        /* out URLStreamRef = */ JMURLInputStreamRef* urlInputStreamRef
00332        )
00333 {
00334     MRJURLConnection* connection = reinterpret_cast<MRJURLConnection*>(urlConnectionRef);
00335     MRJInputStream* inputStream = new MRJInputStream(connection->getInstance()->getSession());
00336     if (!inputStream)
00337         return memFullErr;
00338 
00339     inputStream->AddRef();
00340     *urlInputStreamRef = inputStream;
00341 
00342     nsIPluginInstance* pluginInstance = connection->getInstance();
00343     nsIPluginStreamListener* listener = inputStream;
00344     nsresult rv = thePluginManager->GetURL(pluginInstance, connection->getURL(), NULL, listener);
00345 
00346     return noErr;
00347 }
00348 
00349 static OSStatus openOutputStream(
00350        /* in URLConnectionRef = */ JMURLConnectionRef urlConnectionRef,
00351        /* out URLOutputStreamRef = */ JMURLOutputStreamRef* urlOutputStreamRef
00352        )
00353 {
00354     return paramErr;
00355 }
00356 
00357 static OSStatus closeInputStream(
00358        /* in URLInputStreamRef = */ JMURLInputStreamRef urlInputStreamRef
00359        )
00360 {
00361     MRJInputStream* inputStream = reinterpret_cast<MRJInputStream*>(urlInputStreamRef);
00362     inputStream->Release();
00363     return noErr;
00364 }
00365 
00366 static OSStatus closeOutputStream(
00367        /* in URLOutputStreamRef = */ JMURLOutputStreamRef urlOutputStreamRef
00368        )
00369 {
00370     return paramErr;
00371 }
00372 
00373 static OSStatus readInputStream(
00374        /* in URLConnectionRef = */ JMURLInputStreamRef urlInputStreamRef,
00375        /* out Buffer = */ void* buffer,
00376        /* in BufferSize = */ UInt32 bufferSize,
00377        /* out BytesRead = */ SInt32* bytesRead
00378        )
00379 {
00380     MRJInputStream* inputStream = reinterpret_cast<MRJInputStream*>(urlInputStreamRef);
00381     return inputStream->read(buffer, bufferSize, bytesRead);
00382 }
00383 
00384 static OSStatus writeOutputStream(
00385        /* in URLConnectionRef = */ JMURLOutputStreamRef oStreamRef,
00386        /* in Buffer = */ void* buffer,
00387        /* in BytesToWrite = */ SInt32 bytesToWrite
00388        )
00389 {
00390     return paramErr;
00391 }
00392 
00393 static JMURLCallbacks theURLCallbacks = {
00394     kJMVersion,
00395        &openConnection, &closeConnection,
00396        &usingProxy, &getCookie, &setCookie,
00397        &setRequestProperties,
00398        &getResponsePropertiesCount,
00399        &getResponseProperties,
00400     &openInputStream, &openOutputStream,
00401     &closeInputStream, &closeOutputStream,
00402     &readInputStream, &writeOutputStream
00403 };
00404 
00405 OSStatus OpenMRJNetworking(MRJSession* session)
00406 {
00407     OSStatus rv = paramErr;
00408     if (&::JMURLSetCallbacks != 0) {
00409         rv = ::JMURLSetCallbacks(session->getSessionRef(),
00410                                  "http", &theURLCallbacks);
00411         rv = ::JMURLSetCallbacks(session->getSessionRef(),
00412                                  "https", &theURLCallbacks);
00413     }
00414     return rv;
00415 }
00416 
00417 OSStatus CloseMRJNetworking(MRJSession* session)
00418 {
00419     return noErr;
00420 }