- Timestamp:
- Apr 5, 2007 4:19:01 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
r118 r1958 21 21 * Contributor(s): 22 22 * Darin Fisher <[email protected]> 23 * Dmitry A. Kuminov <[email protected]> 23 24 * 24 25 * Alternatively, the contents of this file may be used under the terms of … … 45 46 #include "nsIInterfaceInfoManager.h" 46 47 #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 if 161 // NS_FAILED(status) (see ipcDConnectService::SerializeException) 160 162 }; 161 163 … … 181 183 { 182 184 nsresult result; 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 called185 // method has set an exception for the current thread using nsIExceptionManager185 // followed by an array of out-param blobs if NS_SUCCEEDED(result), or by a 186 // specially serialized nsIException instance if NS_FAILED(result) 187 // (see ipcDConnectService::SerializeException) 186 188 }; 187 189 … … 1116 1118 } 1117 1119 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 nsIException 1132 // 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 if 1136 // the called party terminates immediately after returning an exception. 1137 // To achieve this, all cacheable information is serialized together with 1138 // the instance wrapper itself. 1139 1140 class ExceptionStub : public nsIException 1141 { 1142 public: 1143 1144 NS_DECL_ISUPPORTS 1145 NS_DECL_NSIEXCEPTION 1146 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_IMETHODIMP 1176 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 sequence 1190 1191 nsISupports* foundInterface = 0; 1192 1193 if (aIID.Equals(NS_GET_IID(nsIException))) 1194 foundInterface = NS_STATIC_CAST(nsIException*, this); 1195 else 1196 if (aIID.Equals(NS_GET_IID(nsISupports))) 1197 foundInterface = NS_STATIC_CAST(nsISupports*, 1198 NS_STATIC_CAST(nsIException *, this)); 1199 else 1200 if (mXcptStub) 1201 { 1202 // ask the real nsIException object 1203 return mXcptStub->QueryInterface(aIID, aInstancePtr); 1204 } 1205 1206 nsresult status; 1207 if (!foundInterface) 1208 status = NS_NOINTERFACE; 1209 else 1210 { 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 nsresult 1305 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 as 1312 // in SerializeInterfaceParam() except that when the exception to serialize 1313 // is an ExceptionStub instance and the real instance it stores as mXcpt 1314 // is a DConnectStub corresponding to an object in the address space of the 1315 // 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 address 1326 writer.PutBytes(&xcpt, sizeof(xcpt)); 1327 } 1328 else 1329 { 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 peer 1335 void *p = stub->Stub()->Instance(); 1336 writer.PutBytes(&p, sizeof(p)); 1337 } 1338 else 1339 { 1340 // create instance wrapper 1341 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 object 1351 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 wrapper 1365 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 client 1375 // (will be released upon DCON_OP_RELEASE) 1376 1377 // send address of the instance wrapper, and set the low bit 1378 // 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 when 1383 // accessing exception data on the peer side 1384 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 // message 1398 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 else 1408 writer.PutInt32(0); 1409 1410 // result 1411 nsresult res = 0; 1412 xcpt->GetResult(&res); 1413 writer.PutInt32(res); 1414 1415 // name 1416 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 else 1426 writer.PutInt32(0); 1427 1428 // filename 1429 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 else 1439 writer.PutInt32(0); 1440 1441 // lineNumber 1442 num = 0; 1443 xcpt->GetLineNumber(&num); 1444 writer.PutInt32(num); 1445 1446 // columnNumber 1447 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 nsresult 1455 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 else 1516 { 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 info 1524 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 else 1535 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 before 1542 // (the remote method we've called had called us back and got an exception 1543 // from us that it decided to return as its own result). Replace it with 1544 // 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 else 1553 { 1554 NS_NOTREACHED("instance wrapper not found"); 1555 rv = NS_ERROR_INVALID_ARG; 1556 } 1557 } 1558 else 1559 { 1560 // the peer explicitly passed us a NULL exception to indicate that the 1561 // exception on the current thread should be reset 1562 *xcpt = NULL; 1563 return NS_OK; 1564 } 1565 1566 1567 return rv; 1568 } 1569 1570 //----------------------------------------------------------------------------- 1571 1118 1572 DConnectStub::~DConnectStub() 1119 1573 { … … 1278 1732 1279 1733 // reset the exception early. this is necessary because we may return a 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. 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. 1285 1741 1286 1742 nsCOMPtr <nsIExceptionService> es; … … 1399 1855 if (NS_FAILED(rv)) 1400 1856 { 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 } 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"); 1455 1874 } 1456 1875 } … … 1546 1965 } 1547 1966 1967 if (opLen < sizeof(DConnectSetupReply)) 1968 { 1969 NS_NOTREACHED("unexpected response size"); 1970 mStatus = NS_ERROR_UNEXPECTED; 1971 return; 1972 } 1973 1548 1974 const DConnectSetupReply *reply = (const DConnectSetupReply *) op; 1549 1975 … … 1554 1980 mStatus = reply->status; 1555 1981 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)); 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); 1567 1995 if (NS_SUCCEEDED(rv)) 1568 1996 { 1569 if (reply->instance) 1997 nsCOMPtr <nsIExceptionManager> em; 1998 rv = es->GetCurrentExceptionManager (getter_AddRefs(em)); 1999 if (NS_SUCCEEDED(rv)) 1570 2000 { 1571 2001 // ensure ipcDConnectService is not deleted before we finish 1572 2002 nsRefPtr <ipcDConnectService> dConnect (ipcDConnectService::GetInstance()); 1573 2003 if (dConnect) 1574 rv = dConnect->CreateStub(nsIException::GetIID(), sender, reply->instance, 1575 getter_AddRefs(mStub)); 2004 { 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 } 2013 } 1576 2014 else 1577 rv = NS_ERROR_FAILURE; 1578 if (NS_SUCCEEDED(rv)) 1579 { 1580 rv = em->SetCurrentException((nsIException *)(nsISupports *) mStub); 1581 } 1582 } 1583 else 1584 { 1585 // reset the exception (as requested by the peer) 1586 rv = em->SetCurrentException(NULL); 2015 rv = NS_ERROR_UNEXPECTED; 1587 2016 } 1588 2017 } 1589 } 1590 1591 if (NS_FAILED(rv)) 1592 mStatus = rv; 2018 NS_ASSERTION(NS_SUCCEEDED(rv), "failed to deserialize/set exception"); 2019 } 1593 2020 } 1594 2021 else … … 2339 2766 break; 2340 2767 } 2768 2769 nsVoidArray wrappers; 2341 2770 2342 2771 // now, create instance wrapper, and store it in our instances set. … … 2371 2800 // reference the newly created wrapper 2372 2801 wrapper->AddRef(); 2802 2803 if (!wrappers.AppendElement(wrapper)) 2804 { 2805 NS_RELEASE(wrapper); 2806 rv = NS_ERROR_OUT_OF_MEMORY; 2807 } 2373 2808 } 2374 2809 } … … 2379 2814 } 2380 2815 } 2381 else 2816 2817 NS_IF_RELEASE(instance); 2818 2819 ipcMessageWriter writer(64); 2820 2821 DConnectSetupReply msg; 2822 msg.opcode_major = DCON_OP_SETUP_REPLY; 2823 msg.opcode_minor = 0; 2824 msg.request_index = setup->request_index; 2825 msg.instance = wrapper; 2826 msg.status = rv; 2827 2828 writer.PutBytes(&msg, sizeof(msg)); 2829 2830 if (NS_FAILED(rv)) 2382 2831 { 2383 2832 // try to fetch an nsIException possibly set by one of the setup methods 2384 2833 // and send it instead of the failed instance (even if it is null) 2385 nsresult setup_rv = rv;2386 2834 nsCOMPtr <nsIExceptionService> es; 2387 2835 es = do_GetService(NS_EXCEPTIONSERVICE_CONTRACTID, &rv); … … 2399 2847 (nsIException *)exception)); 2400 2848 2401 if (exception) 2402 { 2403 nsCOMPtr<nsIInterfaceInfo> iinfo; 2404 rv = GetInterfaceInfo(nsIException::GetIID(), getter_AddRefs(iinfo)); 2405 if (NS_SUCCEEDED(rv)) 2406 { 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) 2434 } 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; 2849 rv = SerializeException(writer, peer, exception, wrappers); 2441 2850 } 2442 2851 } 2443 2852 } 2444 } 2445 2446 NS_IF_RELEASE(instance); 2447 2448 DConnectSetupReply msg; 2449 msg.opcode_major = DCON_OP_SETUP_REPLY; 2450 msg.opcode_minor = 0; 2451 msg.request_index = setup->request_index; 2452 msg.instance = wrapper; 2453 msg.status = rv; 2853 NS_ASSERTION(NS_SUCCEEDED(rv), "failed to get/serialze exception"); 2854 } 2454 2855 2455 2856 // fire off SETUP_REPLY, don't wait for a response 2456 IPC_SendMessage(peer, kDConnectTargetID, 2457 (const PRUint8 *) &msg, sizeof(msg)); 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 } 2458 2869 } 2459 2870 … … 2650 3061 if (got_exception) 2651 3062 { 2652 // serialize the exception 2653 rv = SerializeInterfaceParam(writer, peer, nsIException::GetIID(), 2654 exception, wrappers); 3063 rv = SerializeException(writer, peer, exception, wrappers); 3064 NS_ASSERTION(NS_SUCCEEDED(rv), "failed to get/serialze exception"); 2655 3065 } 2656 3066 else if (NS_SUCCEEDED(rv) && params) -
trunk/src/libs/xpcom18a4/ipc/ipcd/extensions/dconnect/src/ipcDConnectService.h
r1 r1958 21 21 * Contributor(s): 22 22 * Darin Fisher <[email protected]> 23 * Dmitry A. Kuminov <[email protected]> 23 24 * 24 25 * Alternatively, the contents of this file may be used under the terms of … … 79 80 }; 80 81 81 #endif 82 82 #endif // DCONNECT_MULTITHREADED 83 84 class nsIException; 83 85 class ipcMessageWriter; 84 86 … … 216 218 nsISupports *obj, 217 219 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); 218 226 219 227 NS_HIDDEN_(void) ReleaseWrappers(nsVoidArray &wrappers);
Note:
See TracChangeset
for help on using the changeset viewer.