Changeset 1964 in vbox for trunk/src/libs/xpcom18a4/ipc/ipcd/extensions
- Timestamp:
- Apr 5, 2007 9:02:45 PM (18 years ago)
- Location:
- trunk/src/libs/xpcom18a4/ipc/ipcd/extensions/dconnect/src
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/libs/xpcom18a4/ipc/ipcd/extensions/dconnect/src/ipcDConnectService.cpp
r1958 r1964 21 21 * Contributor(s): 22 22 * Darin Fisher <[email protected]> 23 * Dmitry A. Kuminov <[email protected]>24 23 * 25 24 * Alternatively, the contents of this file may be used under the terms of … … 46 45 #include "nsIInterfaceInfoManager.h" 47 46 #include "nsIExceptionService.h" 47 #include "nsAutoPtr.h" 48 48 #include "nsString.h" 49 49 #include "nsVoidArray.h" … … 158 158 DConAddr instance; 159 159 nsresult status; 160 // followed by a specially serialized nsIException instance if161 // NS_FAILED(status) (see ipcDConnectService::SerializeException)162 160 }; 163 161 … … 183 181 { 184 182 nsresult result; 185 // followed by an array of out-param blobs if NS_SUCCEEDED (result), or by a186 // specially serialized nsIException instance if NS_FAILED(result)187 // (see ipcDConnectService::SerializeException)183 // followed by an array of out-param blobs if NS_SUCCEEDED (result) 184 // or by an nsIException instance if NS_FAILED (result) and the called 185 // method has set an exception for the current thread using nsIExceptionManager 188 186 }; 189 187 … … 1118 1116 } 1119 1117 1120 //-----------------------------------------------------------------------------1121 1122 #define EXCEPTION_STUB_ID \1123 { /* 70578d68-b25e-4370-a70c-89bbe56e6699 */ \1124 0x70578d68, \1125 0xb25e, \1126 0x4370, \1127 {0xa7, 0x0c, 0x89, 0xbb, 0xe5, 0x6e, 0x66, 0x99} \1128 }1129 static NS_DEFINE_IID(kExceptionStubID, EXCEPTION_STUB_ID);1130 1131 // ExceptionStub is used to cache all primitive-typed bits of a remote nsIException1132 // instance (such as the error message or line number) to:1133 //1134 // a) reduce the number of IPC calls;1135 // b) make sure exception information is available to the calling party even if1136 // the called party terminates immediately after returning an exception.1137 // To achieve this, all cacheable information is serialized together with1138 // the instance wrapper itself.1139 1140 class ExceptionStub : public nsIException1141 {1142 public:1143 1144 NS_DECL_ISUPPORTS1145 NS_DECL_NSIEXCEPTION1146 1147 ExceptionStub(const nsACString &aMessage, nsresult aResult,1148 const nsACString &aName, const nsACString &aFilename,1149 PRUint32 aLineNumber, PRUint32 aColumnNumber,1150 DConnectStub *aXcptStub)1151 : mMessage(aMessage), mResult(aResult)1152 , mName(aName), mFilename(aFilename)1153 , mLineNumber (aLineNumber), mColumnNumber (aColumnNumber)1154 , mXcptStub (aXcptStub) { NS_ASSERTION(aXcptStub, "NULL"); }1155 1156 ~ExceptionStub() {}1157 1158 nsIException *Exception() { return (nsIException *)(nsISupports *) mXcptStub; }1159 DConnectStub *Stub() { return mXcptStub; }1160 1161 private:1162 1163 nsCString mMessage;1164 nsresult mResult;1165 nsCString mName;1166 nsCString mFilename;1167 PRUint32 mLineNumber;1168 PRUint32 mColumnNumber;1169 nsRefPtr<DConnectStub> mXcptStub;1170 };1171 1172 NS_IMPL_ADDREF(ExceptionStub)1173 NS_IMPL_RELEASE(ExceptionStub)1174 1175 NS_IMETHODIMP1176 ExceptionStub::QueryInterface(const nsID &aIID, void **aInstancePtr)1177 {1178 NS_ASSERTION(aInstancePtr,1179 "QueryInterface requires a non-NULL destination!");1180 1181 // used to discover if this is an ExceptionStub instance.1182 if (aIID.Equals(kExceptionStubID))1183 {1184 *aInstancePtr = this;1185 NS_ADDREF_THIS();1186 return NS_OK;1187 }1188 1189 // regular NS_IMPL_QUERY_INTERFACE1 sequence1190 1191 nsISupports* foundInterface = 0;1192 1193 if (aIID.Equals(NS_GET_IID(nsIException)))1194 foundInterface = NS_STATIC_CAST(nsIException*, this);1195 else1196 if (aIID.Equals(NS_GET_IID(nsISupports)))1197 foundInterface = NS_STATIC_CAST(nsISupports*,1198 NS_STATIC_CAST(nsIException *, this));1199 else1200 if (mXcptStub)1201 {1202 // ask the real nsIException object1203 return mXcptStub->QueryInterface(aIID, aInstancePtr);1204 }1205 1206 nsresult status;1207 if (!foundInterface)1208 status = NS_NOINTERFACE;1209 else1210 {1211 NS_ADDREF(foundInterface);1212 status = NS_OK;1213 }1214 *aInstancePtr = foundInterface;1215 return status;1216 }1217 1218 /* readonly attribute string message; */1219 NS_IMETHODIMP ExceptionStub::GetMessage(char **aMessage)1220 {1221 if (!aMessage)1222 return NS_ERROR_INVALID_POINTER;1223 *aMessage = ToNewCString(mMessage);1224 return NS_OK;1225 }1226 1227 /* readonly attribute nsresult result; */1228 NS_IMETHODIMP ExceptionStub::GetResult(nsresult *aResult)1229 {1230 if (!aResult)1231 return NS_ERROR_INVALID_POINTER;1232 *aResult = mResult;1233 return NS_OK;1234 }1235 1236 /* readonly attribute string name; */1237 NS_IMETHODIMP ExceptionStub::GetName(char **aName)1238 {1239 if (!aName)1240 return NS_ERROR_INVALID_POINTER;1241 *aName = ToNewCString(mName);1242 return NS_OK;1243 }1244 1245 /* readonly attribute string filename; */1246 NS_IMETHODIMP ExceptionStub::GetFilename(char **aFilename)1247 {1248 if (!aFilename)1249 return NS_ERROR_INVALID_POINTER;1250 *aFilename = ToNewCString(mFilename);1251 return NS_OK;1252 }1253 1254 /* readonly attribute PRUint32 lineNumber; */1255 NS_IMETHODIMP ExceptionStub::GetLineNumber(PRUint32 *aLineNumber)1256 {1257 if (!aLineNumber)1258 return NS_ERROR_INVALID_POINTER;1259 *aLineNumber = mLineNumber;1260 return NS_OK;1261 }1262 1263 /* readonly attribute PRUint32 columnNumber; */1264 NS_IMETHODIMP ExceptionStub::GetColumnNumber(PRUint32 *aColumnNumber)1265 {1266 if (!aColumnNumber)1267 return NS_ERROR_INVALID_POINTER;1268 *aColumnNumber = mColumnNumber;1269 return NS_OK;1270 }1271 1272 /* readonly attribute nsIStackFrame location; */1273 NS_IMETHODIMP ExceptionStub::GetLocation(nsIStackFrame **aLocation)1274 {1275 if (Exception())1276 return Exception()->GetLocation (aLocation);1277 return NS_ERROR_UNEXPECTED;1278 }1279 1280 /* readonly attribute nsIException inner; */1281 NS_IMETHODIMP ExceptionStub::GetInner(nsIException **aInner)1282 {1283 if (Exception())1284 return Exception()->GetInner (aInner);1285 return NS_ERROR_UNEXPECTED;1286 }1287 1288 /* readonly attribute nsISupports data; */1289 NS_IMETHODIMP ExceptionStub::GetData(nsISupports * *aData)1290 {1291 if (Exception())1292 return Exception()->GetData (aData);1293 return NS_ERROR_UNEXPECTED;1294 }1295 1296 /* string toString (); */1297 NS_IMETHODIMP ExceptionStub::ToString(char **_retval)1298 {1299 if (Exception())1300 return Exception()->ToString (_retval);1301 return NS_ERROR_UNEXPECTED;1302 }1303 1304 nsresult1305 ipcDConnectService::SerializeException(ipcMessageWriter &writer,1306 PRUint32 peer, nsIException *xcpt,1307 nsVoidArray &wrappers)1308 {1309 PRBool cache_fields = PR_FALSE;1310 1311 // first, seralize the nsIException pointer. The code is merely the same as1312 // in SerializeInterfaceParam() except that when the exception to serialize1313 // is an ExceptionStub instance and the real instance it stores as mXcpt1314 // is a DConnectStub corresponding to an object in the address space of the1315 // peer, we simply pass that object back instead of creating a new wrapper.1316 1317 {1318 nsAutoLock lock (mLock);1319 1320 if (mDisconnected)1321 return NS_ERROR_NOT_INITIALIZED;1322 1323 if (!xcpt)1324 {1325 // write null address1326 writer.PutBytes(&xcpt, sizeof(xcpt));1327 }1328 else1329 {1330 ExceptionStub *stub = nsnull;1331 nsresult rv = xcpt->QueryInterface(kExceptionStubID, (void **) &stub);1332 if (NS_SUCCEEDED(rv) && (stub->Stub()->PeerID() == peer))1333 {1334 // send the wrapper instance back to the peer1335 void *p = stub->Stub()->Instance();1336 writer.PutBytes(&p, sizeof(p));1337 }1338 else1339 {1340 // create instance wrapper1341 1342 const nsID &iid = nsIException::GetIID();1343 nsCOMPtr<nsIInterfaceInfo> iinfo;1344 rv = GetInterfaceInfo(iid, getter_AddRefs(iinfo));1345 if (NS_FAILED(rv))1346 return rv;1347 1348 DConnectInstance *wrapper = nsnull;1349 1350 // first try to find an existing wrapper for the given object1351 if (!FindInstanceAndAddRef(peer, xcpt, &iid, &wrapper))1352 {1353 wrapper = new DConnectInstance(peer, iinfo, xcpt);1354 if (!wrapper)1355 return NS_ERROR_OUT_OF_MEMORY;1356 1357 rv = StoreInstance(wrapper);1358 if (NS_FAILED(rv))1359 {1360 delete wrapper;1361 return rv;1362 }1363 1364 // reference the newly created wrapper1365 wrapper->AddRef();1366 }1367 1368 if (!wrappers.AppendElement(wrapper))1369 {1370 wrapper->Release();1371 return NS_ERROR_OUT_OF_MEMORY;1372 }1373 1374 // wrapper remains referenced when passing it to the client1375 // (will be released upon DCON_OP_RELEASE)1376 1377 // send address of the instance wrapper, and set the low bit1378 // to indicate that this is an instance wrapper.1379 PtrBits bits = ((PtrBits) wrapper) | 0x1;1380 writer.PutBytes(&bits, sizeof(bits));1381 1382 // we want to cache fields to minimize the number of IPC calls when1383 // accessing exception data on the peer side1384 cache_fields = PR_TRUE;1385 }1386 NS_IF_RELEASE(stub);1387 }1388 }1389 1390 if (!cache_fields)1391 return NS_OK;1392 1393 nsresult rv;1394 nsXPIDLCString str;1395 PRUint32 num;1396 1397 // message1398 rv = xcpt->GetMessage(getter_Copies(str));1399 if (NS_SUCCEEDED (rv))1400 {1401 PRUint32 len = str.Length();1402 nsACString::const_iterator begin;1403 const char *data = str.BeginReading(begin).get();1404 writer.PutInt32(len);1405 writer.PutBytes(data, len);1406 }1407 else1408 writer.PutInt32(0);1409 1410 // result1411 nsresult res = 0;1412 xcpt->GetResult(&res);1413 writer.PutInt32(res);1414 1415 // name1416 rv = xcpt->GetName(getter_Copies(str));1417 if (NS_SUCCEEDED (rv))1418 {1419 PRUint32 len = str.Length();1420 nsACString::const_iterator begin;1421 const char *data = str.BeginReading(begin).get();1422 writer.PutInt32(len);1423 writer.PutBytes(data, len);1424 }1425 else1426 writer.PutInt32(0);1427 1428 // filename1429 rv = xcpt->GetFilename(getter_Copies(str));1430 if (NS_SUCCEEDED (rv))1431 {1432 PRUint32 len = str.Length();1433 nsACString::const_iterator begin;1434 const char *data = str.BeginReading(begin).get();1435 writer.PutInt32(len);1436 writer.PutBytes(data, len);1437 }1438 else1439 writer.PutInt32(0);1440 1441 // lineNumber1442 num = 0;1443 xcpt->GetLineNumber(&num);1444 writer.PutInt32(num);1445 1446 // columnNumber1447 num = 0;1448 xcpt->GetColumnNumber(&num);1449 writer.PutInt32(num);1450 1451 return writer.HasError() ? NS_ERROR_OUT_OF_MEMORY : NS_OK;1452 }1453 1454 nsresult1455 ipcDConnectService::DeserializeException(const PRUint8 *data,1456 PRUint32 dataLen,1457 PRUint32 peer,1458 nsIException **xcpt)1459 {1460 NS_ASSERTION (xcpt, "NULL");1461 if (!xcpt)1462 return NS_ERROR_INVALID_POINTER;1463 1464 ipcMessageReader reader(data, dataLen);1465 1466 nsresult rv;1467 PRUint32 len;1468 1469 void *instance = 0;1470 reader.GetBytes(&instance, sizeof(void *));1471 if (reader.HasError())1472 return NS_ERROR_INVALID_ARG;1473 1474 PtrBits bits = (PtrBits) (instance);1475 1476 if (bits & 0x1)1477 {1478 // pointer is a peer-side exception instance wrapper,1479 // read cahced exception data and create a stub for it.1480 1481 nsCAutoString message;1482 len = reader.GetInt32();1483 if (len)1484 {1485 message.SetLength(len);1486 char *buf = message.BeginWriting();1487 reader.GetBytes(buf, len);1488 }1489 1490 nsresult result = reader.GetInt32();1491 1492 nsCAutoString name;1493 len = reader.GetInt32();1494 if (len)1495 {1496 name.SetLength(len);1497 char *buf = name.BeginWriting();1498 reader.GetBytes(buf, len);1499 }1500 1501 nsCAutoString filename;1502 len = reader.GetInt32();1503 if (len)1504 {1505 filename.SetLength(len);1506 char *buf = filename.BeginWriting();1507 reader.GetBytes(buf, len);1508 }1509 1510 PRUint32 lineNumber = reader.GetInt32();1511 PRUint32 columnNumber = reader.GetInt32();1512 1513 if (reader.HasError())1514 rv = NS_ERROR_INVALID_ARG;1515 else1516 {1517 DConAddr addr = (DConAddr) (bits & ~0x1);1518 nsRefPtr<DConnectStub> stub;1519 rv = CreateStub(nsIException::GetIID(), peer, addr,1520 getter_AddRefs(stub));1521 if (NS_SUCCEEDED(rv))1522 {1523 // create a special exception "stub" with cached error info1524 ExceptionStub *xcptStub =1525 new ExceptionStub (message, result,1526 name, filename,1527 lineNumber, columnNumber,1528 stub);1529 if (xcptStub)1530 {1531 *xcpt = xcptStub;1532 NS_ADDREF(xcptStub);1533 }1534 else1535 rv = NS_ERROR_OUT_OF_MEMORY;1536 }1537 }1538 }1539 else if (bits)1540 {1541 // pointer is to our instance wrapper for nsIException we've sent before1542 // (the remote method we've called had called us back and got an exception1543 // from us that it decided to return as its own result). Replace it with1544 // the real instance.1545 DConnectInstance *wrapper = (DConnectInstance *) bits;1546 if (CheckInstanceAndAddRef(wrapper))1547 {1548 *xcpt = (nsIException *) wrapper->RealInstance();1549 NS_ADDREF(wrapper->RealInstance());1550 wrapper->Release();1551 }1552 else1553 {1554 NS_NOTREACHED("instance wrapper not found");1555 rv = NS_ERROR_INVALID_ARG;1556 }1557 }1558 else1559 {1560 // the peer explicitly passed us a NULL exception to indicate that the1561 // exception on the current thread should be reset1562 *xcpt = NULL;1563 return NS_OK;1564 }1565 1566 1567 return rv;1568 }1569 1570 //-----------------------------------------------------------------------------1571 1572 1118 DConnectStub::~DConnectStub() 1573 1119 { … … 1732 1278 1733 1279 // reset the exception early. this is necessary because we may return a 1734 // failure from here without setting an exception (which might be expected 1735 // by the caller to detect the error origin: the interface we are stubbing 1736 // may indicate in some way that it always sets the exception info on 1737 // failure, therefore an "infoless" failure means the origin is RPC). 1738 // besides that, resetting the excetion before every IPC call is exactly the 1739 // same thing as Win32 RPC does, so doing this is useful for getting 1740 // similarity in behaviors. 1280 // failure from here without setting an exception (which might be expected by 1281 // the caller because the interface we are stubbing may indicate in some way 1282 // that it always sets the exception info on failure). besides that, resetting 1283 // the excetion before every IPC call is exactly the same thing as Win32 RPC 1284 // does, so doing this is useful for getting similarity in behaviors. 1741 1285 1742 1286 nsCOMPtr <nsIExceptionService> es; … … 1855 1399 if (NS_FAILED(rv)) 1856 1400 { 1857 NS_ASSERTION(completion.ParamsLen() >= sizeof(void*), 1858 "invalid nsIException serialization length"); 1859 if (completion.ParamsLen() >= sizeof(void*)) 1860 { 1861 LOG(("got nsIException instance (%p), will create a stub\n", 1862 *((void **) completion.Params()))); 1863 1864 nsIException *xcpt = nsnull; 1865 rv = dConnect->DeserializeException (completion.Params(), 1866 completion.ParamsLen(), 1867 mPeerID, &xcpt); 1868 if (NS_SUCCEEDED(rv)) 1869 { 1870 rv = em->SetCurrentException(xcpt); 1871 NS_IF_RELEASE(xcpt); 1872 } 1873 NS_ASSERTION(NS_SUCCEEDED(rv), "failed to deserialize/set exception"); 1401 if (completion.ParamsLen() > 0) 1402 { 1403 // we've got an nsIException instance, deserialize it and set in the 1404 // current thread 1405 nsresult invoke_rv = rv; 1406 PtrBits bits = (PtrBits) *((void **) completion.Params()); 1407 1408 LOG(("got nsIException instance (%p), will create a stub\n", bits)); 1409 1410 NS_ASSERTION(completion.ParamsLen() == sizeof(void*), 1411 "wrong nsIException serialization"); 1412 1413 if (bits & 0x1) 1414 { 1415 DConAddr addr = (DConAddr) (bits & ~0x1); 1416 nsRefPtr<DConnectStub> stub; 1417 rv = dConnect->CreateStub(nsIException::GetIID(), mPeerID, addr, 1418 getter_AddRefs(stub)); 1419 if (NS_SUCCEEDED(rv)) 1420 { 1421 rv = em->SetCurrentException((nsIException *)(nsISupports *) stub); 1422 // restore the method's result 1423 rv = invoke_rv; 1424 } 1425 } 1426 else if (bits) 1427 { 1428 // pointer is to our instance wrapper for nsIException we've set 1429 // before (the remote method we've just called had called us back 1430 // and got an exception from us that it decided to return as its 1431 // own result). Replace it with the real instance. 1432 DConnectInstance *wrapper = (DConnectInstance *) bits; 1433 if (dConnect->CheckInstanceAndAddRef(wrapper)) 1434 { 1435 rv = em->SetCurrentException((nsIException *) wrapper->RealInstance()); 1436 // restore the method's result 1437 rv = invoke_rv; 1438 wrapper->Release(); 1439 } 1440 else 1441 { 1442 NS_NOTREACHED("instance wrapper not found"); 1443 rv = NS_ERROR_INVALID_ARG; 1444 } 1445 } 1446 else 1447 { 1448 // reset the exception (as requested by the peer) 1449 // (it doesn't seem to be really necessary since we always reset it at 1450 // the beginning, but leave it here for clarity) 1451 rv = em->SetCurrentException(NULL); 1452 // restore the method's result 1453 rv = invoke_rv; 1454 } 1874 1455 } 1875 1456 } … … 1965 1546 } 1966 1547 1967 if (opLen < sizeof(DConnectSetupReply))1968 {1969 NS_NOTREACHED("unexpected response size");1970 mStatus = NS_ERROR_UNEXPECTED;1971 return;1972 }1973 1974 1548 const DConnectSetupReply *reply = (const DConnectSetupReply *) op; 1975 1549 … … 1980 1554 mStatus = reply->status; 1981 1555 1982 const PRUint8 *params = ((const PRUint8 *) op) + sizeof (DConnectSetupReply); 1983 const PRUint32 paramsLen = opLen - sizeof (DConnectSetupReply); 1984 1985 NS_ASSERTION(paramsLen >= sizeof(void*), 1986 "invalid nsIException serialization length"); 1987 if (paramsLen >= sizeof(void*)) 1988 { 1989 LOG(("got nsIException instance (%p), will create a stub\n", 1990 *((void **) params))); 1991 1992 nsresult rv; 1993 nsCOMPtr <nsIExceptionService> es; 1994 es = do_GetService (NS_EXCEPTIONSERVICE_CONTRACTID, &rv); 1556 // we've been sent an nsIException (that can be null) in case of any error, 1557 // set it in the current thread 1558 LOG(("got nsIException instance (%p), will create a stub\n", reply->instance)); 1559 1560 nsresult rv; 1561 nsCOMPtr <nsIExceptionService> es; 1562 es = do_GetService (NS_EXCEPTIONSERVICE_CONTRACTID, &rv); 1563 if (NS_SUCCEEDED(rv)) 1564 { 1565 nsCOMPtr <nsIExceptionManager> em; 1566 rv = es->GetCurrentExceptionManager (getter_AddRefs(em)); 1995 1567 if (NS_SUCCEEDED(rv)) 1996 1568 { 1997 nsCOMPtr <nsIExceptionManager> em; 1998 rv = es->GetCurrentExceptionManager (getter_AddRefs(em)); 1999 if (NS_SUCCEEDED(rv)) 1569 if (reply->instance) 2000 1570 { 2001 1571 // ensure ipcDConnectService is not deleted before we finish 2002 1572 nsRefPtr <ipcDConnectService> dConnect (ipcDConnectService::GetInstance()); 2003 1573 if (dConnect) 1574 rv = dConnect->CreateStub(nsIException::GetIID(), sender, reply->instance, 1575 getter_AddRefs(mStub)); 1576 else 1577 rv = NS_ERROR_FAILURE; 1578 if (NS_SUCCEEDED(rv)) 2004 1579 { 2005 nsIException *xcpt = nsnull; 2006 rv = dConnect->DeserializeException (params, paramsLen, 2007 sender, &xcpt); 2008 if (NS_SUCCEEDED(rv)) 2009 { 2010 rv = em->SetCurrentException(xcpt); 2011 NS_IF_RELEASE(xcpt); 2012 } 1580 rv = em->SetCurrentException((nsIException *)(nsISupports *) mStub); 2013 1581 } 2014 else 2015 rv = NS_ERROR_UNEXPECTED; 1582 } 1583 else 1584 { 1585 // reset the exception (as requested by the peer) 1586 rv = em->SetCurrentException(NULL); 2016 1587 } 2017 1588 } 2018 NS_ASSERTION(NS_SUCCEEDED(rv), "failed to deserialize/set exception"); 2019 } 1589 } 1590 1591 if (NS_FAILED(rv)) 1592 mStatus = rv; 2020 1593 } 2021 1594 else … … 2766 2339 break; 2767 2340 } 2768 2769 nsVoidArray wrappers;2770 2341 2771 2342 // now, create instance wrapper, and store it in our instances set. … … 2800 2371 // reference the newly created wrapper 2801 2372 wrapper->AddRef(); 2802 2803 if (!wrappers.AppendElement(wrapper)) 2373 } 2374 } 2375 } 2376 2377 // wrapper remains referenced when passing it to the client 2378 // (will be released upon DCON_OP_RELEASE) 2379 } 2380 } 2381 else 2382 { 2383 // try to fetch an nsIException possibly set by one of the setup methods 2384 // and send it instead of the failed instance (even if it is null) 2385 nsresult setup_rv = rv; 2386 nsCOMPtr <nsIExceptionService> es; 2387 es = do_GetService(NS_EXCEPTIONSERVICE_CONTRACTID, &rv); 2388 if (NS_SUCCEEDED(rv)) 2389 { 2390 nsCOMPtr <nsIExceptionManager> em; 2391 rv = es->GetCurrentExceptionManager (getter_AddRefs (em)); 2392 if (NS_SUCCEEDED(rv)) 2393 { 2394 nsCOMPtr <nsIException> exception; 2395 rv = em->GetCurrentException (getter_AddRefs (exception)); 2396 if (NS_SUCCEEDED(rv)) 2397 { 2398 LOG(("got nsIException instance (%p), will serialize\n", 2399 (nsIException *)exception)); 2400 2401 if (exception) 2402 { 2403 nsCOMPtr<nsIInterfaceInfo> iinfo; 2404 rv = GetInterfaceInfo(nsIException::GetIID(), getter_AddRefs(iinfo)); 2405 if (NS_SUCCEEDED(rv)) 2804 2406 { 2805 NS_RELEASE(wrapper); 2806 rv = NS_ERROR_OUT_OF_MEMORY; 2407 nsAutoLock lock (mLock); 2408 2409 // first try to find an existing wrapper for the given object 2410 if (!FindInstanceAndAddRef(peer, exception, 2411 &nsIException::GetIID(), &wrapper)) 2412 { 2413 wrapper = new DConnectInstance(peer, iinfo, exception); 2414 if (!wrapper) 2415 rv = NS_ERROR_OUT_OF_MEMORY; 2416 else 2417 { 2418 rv = StoreInstance(wrapper); 2419 if (NS_FAILED(rv)) 2420 { 2421 delete wrapper; 2422 wrapper = nsnull; 2423 } 2424 else 2425 { 2426 // reference the newly created wrapper 2427 wrapper->AddRef(); 2428 } 2429 } 2430 } 2431 2432 // wrapper remains referenced when passing it to the client 2433 // (will be released upon DCON_OP_RELEASE) 2807 2434 } 2808 2435 } 2436 // otherwise, wrapper = nsnull, which will indicate a null nsIException 2437 2438 // restore the setup result 2439 if (NS_SUCCEEDED(rv)) 2440 rv = setup_rv; 2809 2441 } 2810 2442 } 2811 2812 // wrapper remains referenced when passing it to the client2813 // (will be released upon DCON_OP_RELEASE)2814 2443 } 2815 2444 } 2816 2445 2817 2446 NS_IF_RELEASE(instance); 2818 2819 ipcMessageWriter writer(64);2820 2447 2821 2448 DConnectSetupReply msg; … … 2826 2453 msg.status = rv; 2827 2454 2828 writer.PutBytes(&msg, sizeof(msg));2829 2830 if (NS_FAILED(rv))2831 {2832 // try to fetch an nsIException possibly set by one of the setup methods2833 // and send it instead of the failed instance (even if it is null)2834 nsCOMPtr <nsIExceptionService> es;2835 es = do_GetService(NS_EXCEPTIONSERVICE_CONTRACTID, &rv);2836 if (NS_SUCCEEDED(rv))2837 {2838 nsCOMPtr <nsIExceptionManager> em;2839 rv = es->GetCurrentExceptionManager (getter_AddRefs (em));2840 if (NS_SUCCEEDED(rv))2841 {2842 nsCOMPtr <nsIException> exception;2843 rv = em->GetCurrentException (getter_AddRefs (exception));2844 if (NS_SUCCEEDED(rv))2845 {2846 LOG(("got nsIException instance (%p), will serialize\n",2847 (nsIException *)exception));2848 2849 rv = SerializeException(writer, peer, exception, wrappers);2850 }2851 }2852 }2853 NS_ASSERTION(NS_SUCCEEDED(rv), "failed to get/serialze exception");2854 }2855 2856 2455 // fire off SETUP_REPLY, don't wait for a response 2857 if (NS_FAILED(rv)) 2858 rv = IPC_SendMessage(peer, kDConnectTargetID, 2859 (const PRUint8 *) &msg, sizeof(msg)); 2860 else 2861 rv = IPC_SendMessage(peer, kDConnectTargetID, 2862 writer.GetBuffer(), writer.GetSize()); 2863 2864 if (NS_FAILED(rv)) 2865 { 2866 LOG(("unable to send SETUP_REPLY: rv=%x\n", rv)); 2867 ReleaseWrappers(wrappers); 2868 } 2456 IPC_SendMessage(peer, kDConnectTargetID, 2457 (const PRUint8 *) &msg, sizeof(msg)); 2869 2458 } 2870 2459 … … 3061 2650 if (got_exception) 3062 2651 { 3063 rv = SerializeException(writer, peer, exception, wrappers); 3064 NS_ASSERTION(NS_SUCCEEDED(rv), "failed to get/serialze exception"); 2652 // serialize the exception 2653 rv = SerializeInterfaceParam(writer, peer, nsIException::GetIID(), 2654 exception, wrappers); 3065 2655 } 3066 2656 else if (NS_SUCCEEDED(rv) && params) -
trunk/src/libs/xpcom18a4/ipc/ipcd/extensions/dconnect/src/ipcDConnectService.h
r1958 r1964 21 21 * Contributor(s): 22 22 * Darin Fisher <[email protected]> 23 * Dmitry A. Kuminov <[email protected]>24 23 * 25 24 * Alternatively, the contents of this file may be used under the terms of … … 80 79 }; 81 80 82 #endif // DCONNECT_MULTITHREADED 83 84 class nsIException; 81 #endif 82 85 83 class ipcMessageWriter; 86 84 … … 218 216 nsISupports *obj, 219 217 nsVoidArray &wrappers); 220 221 NS_HIDDEN_(nsresult) SerializeException(ipcMessageWriter &writer,222 PRUint32 peer, nsIException *xcpt,223 nsVoidArray &wrappers);224 NS_HIDDEN_(nsresult) DeserializeException(const PRUint8 *data, PRUint32 dataLen,225 PRUint32 peer, nsIException **xcpt);226 218 227 219 NS_HIDDEN_(void) ReleaseWrappers(nsVoidArray &wrappers);
Note:
See TracChangeset
for help on using the changeset viewer.