Back to index

lightning-sunbird  0.9+nobinonly
ActiveScriptSite.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *   Adam Lock <adamlock@eircom.net>
00024  *
00025  * Alternatively, the contents of this file may be used under the terms of
00026  * either the GNU General Public License Version 2 or later (the "GPL"), or
00027  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00028  * in which case the provisions of the GPL or the LGPL are applicable instead
00029  * of those above. If you wish to allow use of your version of this file only
00030  * under the terms of either the GPL or the LGPL, and not to allow others to
00031  * use your version of this file under the terms of the MPL, indicate your
00032  * decision by deleting the provisions above and replace them with the notice
00033  * and other provisions required by the GPL or the LGPL. If you do not delete
00034  * the provisions above, a recipient may use your version of this file under
00035  * the terms of any one of the MPL, the GPL or the LGPL.
00036  *
00037  * ***** END LICENSE BLOCK ***** */
00038 
00039 #include "stdafx.h"
00040 #include <sys/types.h>
00041 #include <sys/stat.h>
00042 #include "ActiveScriptSite.h"
00043 
00044 
00045 CActiveScriptSite::CActiveScriptSite()
00046 {
00047     m_ssScriptState = SCRIPTSTATE_UNINITIALIZED;
00048 }
00049 
00050 
00051 CActiveScriptSite::~CActiveScriptSite()
00052 {
00053     Detach();
00054 }
00055 
00056 
00057 HRESULT CActiveScriptSite::Attach(CLSID clsidScriptEngine)
00058 {
00059     // Detach to anything already attached to
00060     Detach();
00061 
00062     // Create the new script engine
00063     HRESULT hr = m_spIActiveScript.CoCreateInstance(clsidScriptEngine);
00064     if (FAILED(hr))
00065     {
00066         return hr;
00067     }
00068 
00069     // Attach the script engine to this site
00070     m_spIActiveScript->SetScriptSite(this);
00071 
00072     // Initialise the script engine
00073     CIPtr(IActiveScriptParse) spActiveScriptParse = m_spIActiveScript;
00074     if (spActiveScriptParse)
00075     {
00076         spActiveScriptParse->InitNew();
00077     }
00078     else
00079     {
00080     }
00081 
00082     return S_OK;
00083 }
00084 
00085 
00086 HRESULT CActiveScriptSite::Detach()
00087 {
00088     if (m_spIActiveScript)
00089     {
00090         StopScript();
00091         m_spIActiveScript->Close();
00092         m_spIActiveScript.Release();
00093     }
00094 
00095     return S_OK;
00096 }
00097 
00098 
00099 HRESULT CActiveScriptSite::AttachVBScript()
00100 {
00101     static const CLSID CLSID_VBScript =
00102     { 0xB54F3741, 0x5B07, 0x11CF, { 0xA4, 0xB0, 0x00, 0xAA, 0x00, 0x4A, 0x55, 0xE8} };
00103     
00104     return Attach(CLSID_VBScript);
00105 }
00106 
00107 
00108 HRESULT CActiveScriptSite::AttachJScript()
00109 {
00110     static const CLSID CLSID_JScript =
00111     { 0xF414C260, 0x6AC0, 0x11CF, { 0xB6, 0xD1, 0x00, 0xAA, 0x00, 0xBB, 0xBB, 0x58} };
00112 
00113     return Attach(CLSID_JScript);
00114 }
00115 
00116 
00117 HRESULT CActiveScriptSite::AddNamedObject(const TCHAR *szName, IUnknown *pObject, BOOL bGlobalMembers)
00118 {
00119     if (m_spIActiveScript == NULL)
00120     {
00121         return E_UNEXPECTED;
00122     }
00123 
00124     if (pObject == NULL || szName == NULL)
00125     {
00126         return E_INVALIDARG;
00127     }
00128 
00129     // Check for objects of the same name already
00130     CNamedObjectList::iterator i = m_cObjectList.find(szName);
00131     if (i != m_cObjectList.end())
00132     {
00133         return E_FAIL;
00134     }
00135 
00136     // Add object to the list
00137     m_cObjectList.insert(CNamedObjectList::value_type(szName, pObject));
00138 
00139     // Tell the script engine about the object
00140     HRESULT hr;
00141     USES_CONVERSION;
00142     DWORD dwFlags = SCRIPTITEM_ISSOURCE | SCRIPTITEM_ISVISIBLE;
00143     if (bGlobalMembers)
00144     {
00145         dwFlags |= SCRIPTITEM_GLOBALMEMBERS;
00146     }
00147 
00148     hr = m_spIActiveScript->AddNamedItem(T2OLE(szName), dwFlags);
00149 
00150     if (FAILED(hr))
00151     {
00152         m_cObjectList.erase(szName);
00153         return hr;
00154     }
00155 
00156     return S_OK;
00157 }
00158 
00159 
00160 HRESULT CActiveScriptSite::ParseScriptFile(const TCHAR *szFile)
00161 {
00162     USES_CONVERSION;
00163     const char *pszFileName = T2CA(szFile);
00164     
00165     // Stat the file and get its length;
00166     struct _stat cStat;
00167     _stat(pszFileName, &cStat);
00168 
00169     // Allocate a buffer
00170     size_t nBufSize = cStat.st_size + 1;
00171     char *pBuffer = (char *) malloc(nBufSize);
00172     if (pBuffer == NULL)
00173     {
00174         return E_OUTOFMEMORY;
00175     }
00176     memset(pBuffer, 0, nBufSize);
00177 
00178     // Read the script into the buffer and parse it
00179     HRESULT hr = E_FAIL;
00180     FILE *f = fopen(pszFileName, "rb");
00181     if (f)
00182     {
00183         fread(pBuffer, 1, nBufSize - 1, f);
00184         hr = ParseScriptText(A2T(pBuffer));
00185         fclose(f);
00186     }
00187 
00188     free(pBuffer);
00189 
00190     return hr;
00191 }
00192 
00193 
00194 HRESULT CActiveScriptSite::ParseScriptText(const TCHAR *szScript)
00195 {
00196     if (m_spIActiveScript == NULL)
00197     {
00198         return E_UNEXPECTED;
00199     }
00200 
00201     CIPtr(IActiveScriptParse) spIActiveScriptParse = m_spIActiveScript;
00202     if (spIActiveScriptParse)
00203     {
00204         USES_CONVERSION;
00205 
00206         CComVariant vResult;
00207         DWORD dwCookie = 0; // TODO
00208         DWORD dwFlags = 0;
00209         EXCEPINFO cExcepInfo;
00210         HRESULT hr;
00211 
00212         hr = spIActiveScriptParse->ParseScriptText(
00213                     T2OLE(szScript),
00214                     NULL, NULL, NULL, dwCookie, 0, dwFlags,
00215                     &vResult, &cExcepInfo);
00216 
00217         if (FAILED(hr))
00218         {
00219             return E_FAIL;
00220         }
00221     }
00222     else
00223     {
00224         CIPtr(IPersistStream) spPersistStream = m_spIActiveScript;
00225         CIPtr(IStream) spStream;
00226 
00227         // Load text into the stream IPersistStream
00228         if (spPersistStream &&
00229             SUCCEEDED(CreateStreamOnHGlobal(NULL, TRUE, &spStream)))
00230         {
00231             USES_CONVERSION;
00232             LARGE_INTEGER cPos = { 0, 0 };
00233             LPOLESTR szText = T2OLE(szScript);
00234             spStream->Write(szText, wcslen(szText) * sizeof(WCHAR), NULL);
00235             spStream->Seek(cPos, STREAM_SEEK_SET, NULL);
00236             spPersistStream->Load(spStream);
00237         }
00238         else
00239         {
00240             return E_UNEXPECTED;
00241         }
00242     }
00243 
00244     return S_OK;
00245 }
00246 
00247 
00248 HRESULT CActiveScriptSite::PlayScript()
00249 {
00250     if (m_spIActiveScript == NULL)
00251     {
00252         return E_UNEXPECTED;
00253     }
00254 
00255     m_spIActiveScript->SetScriptState(SCRIPTSTATE_CONNECTED);
00256 
00257     return S_OK;
00258 }
00259 
00260 
00261 HRESULT CActiveScriptSite::StopScript()
00262 {
00263     if (m_spIActiveScript == NULL)
00264     {
00265         return E_UNEXPECTED;
00266     }
00267 
00268     m_spIActiveScript->SetScriptState(SCRIPTSTATE_DISCONNECTED);
00269 
00270     return S_OK;
00271 }
00272 
00273 
00275 // IActiveScriptSite implementation
00276 
00277 HRESULT STDMETHODCALLTYPE CActiveScriptSite::GetLCID(/* [out] */ LCID __RPC_FAR *plcid)
00278 {
00279     // Use the system defined locale
00280     return E_NOTIMPL;
00281 }
00282 
00283 
00284 HRESULT STDMETHODCALLTYPE CActiveScriptSite::GetItemInfo(/* [in] */ LPCOLESTR pstrName, /* [in] */ DWORD dwReturnMask, /* [out] */ IUnknown __RPC_FAR *__RPC_FAR *ppiunkItem, /* [out] */ ITypeInfo __RPC_FAR *__RPC_FAR *ppti)
00285 {
00286     if (pstrName == NULL)
00287     {
00288         return E_INVALIDARG;
00289     }
00290     
00291     if (ppiunkItem)
00292     {
00293         *ppiunkItem = NULL;
00294     }
00295 
00296     if (ppti)
00297     {
00298         *ppti = NULL;
00299     }
00300 
00301     USES_CONVERSION;
00302 
00303     // Find object in list
00304     CIUnkPtr spUnkObject;
00305     CNamedObjectList::iterator i = m_cObjectList.find(OLE2T(pstrName));
00306     if (i != m_cObjectList.end())
00307     {
00308         spUnkObject = (*i).second;
00309     }
00310 
00311     // Fill in the output values
00312     if (spUnkObject == NULL) 
00313     {
00314         return TYPE_E_ELEMENTNOTFOUND;
00315     }
00316     if (dwReturnMask & SCRIPTINFO_IUNKNOWN) 
00317     {
00318         spUnkObject->QueryInterface(IID_IUnknown, (void **) ppiunkItem);
00319     }
00320     if (dwReturnMask & SCRIPTINFO_ITYPEINFO) 
00321     {
00322         // Return the typeinfo in ptti
00323         CIPtr(IDispatch) spIDispatch = spUnkObject;
00324         if (spIDispatch)
00325         {
00326             HRESULT hr;
00327             hr = spIDispatch->GetTypeInfo(0, GetSystemDefaultLCID(), ppti);
00328             if (FAILED(hr))
00329             {
00330                 *ppti = NULL;
00331             }
00332         }
00333     }
00334 
00335     return S_OK;
00336 }
00337 
00338 
00339 HRESULT STDMETHODCALLTYPE CActiveScriptSite::GetDocVersionString(/* [out] */ BSTR __RPC_FAR *pbstrVersion)
00340 {
00341     return E_NOTIMPL;
00342 }
00343 
00344 
00345 HRESULT STDMETHODCALLTYPE CActiveScriptSite::OnScriptTerminate(/* [in] */ const VARIANT __RPC_FAR *pvarResult, /* [in] */ const EXCEPINFO __RPC_FAR *pexcepinfo)
00346 {
00347     return S_OK;
00348 }
00349 
00350 
00351 HRESULT STDMETHODCALLTYPE CActiveScriptSite::OnStateChange(/* [in] */ SCRIPTSTATE ssScriptState)
00352 {
00353     m_ssScriptState = ssScriptState;
00354     return S_OK;
00355 }
00356 
00357 
00358 HRESULT STDMETHODCALLTYPE CActiveScriptSite::OnScriptError(/* [in] */ IActiveScriptError __RPC_FAR *pscripterror)
00359 {
00360     BSTR bstrSourceLineText = NULL;
00361     DWORD dwSourceContext = 0;
00362     ULONG pulLineNumber = 0;
00363     LONG  ichCharPosition = 0;
00364     EXCEPINFO cExcepInfo;
00365 
00366     memset(&cExcepInfo, 0, sizeof(cExcepInfo));
00367 
00368     // Get error information
00369     pscripterror->GetSourcePosition(&dwSourceContext, &pulLineNumber, &ichCharPosition);
00370     pscripterror->GetSourceLineText(&bstrSourceLineText);
00371     pscripterror->GetExceptionInfo(&cExcepInfo);
00372 
00373     tstring szDescription(_T("(No description)"));
00374     if (cExcepInfo.bstrDescription)
00375     {
00376         // Dump info
00377         USES_CONVERSION;
00378         szDescription = OLE2T(cExcepInfo.bstrDescription);
00379     }
00380 
00381     ATLTRACE(_T("Script Error: %s, code=0x%08x\n"), szDescription.c_str(), cExcepInfo.scode);
00382 
00383     SysFreeString(bstrSourceLineText);
00384 
00385     return S_OK;
00386 }
00387 
00388 
00389 HRESULT STDMETHODCALLTYPE CActiveScriptSite::OnEnterScript(void)
00390 {
00391     return S_OK;
00392 }
00393 
00394 
00395 HRESULT STDMETHODCALLTYPE CActiveScriptSite::OnLeaveScript(void)
00396 {
00397     return S_OK;
00398 }
00399 
00400