Overview
Comment: | ChromeOS: Made JavaScript talking to PCSC more robust |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: | 455296a053b280807ba1149ffe231e21371e5589 |
User & Date: | rkeene on 2016-02-28 21:18:17 |
Other Links: | manifest | tags |
Context
2016-02-28
| ||
21:22 | ChromeOS: Improved cleanup after crash check-in: 789f3b2324 user: rkeene tags: trunk | |
21:18 | ChromeOS: Made JavaScript talking to PCSC more robust check-in: 455296a053 user: rkeene tags: trunk | |
2016-02-26
| ||
21:40 | ChromeOS: Deal with CACKey crashing by restarting check-in: f631a1ccb2 user: rkeene tags: trunk | |
Changes
Modified build/chrome/cackey.js from [fda208ef5f] to [84d3b8d4ee].
9 9 } 10 10 11 11 /* 12 12 * Handle for the CACKey NaCl Target 13 13 */ 14 14 var cackeyHandle = null; 15 15 var cackeyPCSCHandle = null; 16 +var cackeyPCSCHandleUsable = false; 16 17 17 18 /* 18 19 * Handle and ID for outstanding callbacks 19 20 */ 20 21 var cackeyOutstandingCallbacks = {} 21 22 var cackeyOutstandingCallbackCounter = -1; 22 23 ................................................................................ 32 33 var cackeyMessagesToRetry = []; 33 34 34 35 /* 35 36 * Stored PIN for a given certificate 36 37 */ 37 38 var cackeyCertificateToPINMap = {}; 38 39 40 +/* 41 + * Callbacks to perform after PCSC comes online 42 + */ 43 +cackeyCallbackAfterInit = [] 44 + 39 45 /* 40 46 * Compute a text-based handle for a certificate to be hashed by 41 47 */ 42 48 function cackeyCertificateToPINID(certificate) { 43 49 var id; 44 50 var certificateArray; 45 51 ................................................................................ 65 71 var idx; 66 72 var certificates = []; 67 73 68 74 for (idx = 0; idx < message.certificates.length; idx++) { 69 75 certificates.push( 70 76 { 71 77 certificate: message.certificates[idx], 72 - supportedHashes: ['SHA1', 'SHA256'] 78 + supportedHashes: ['SHA1', 'SHA256', 'MD5_SHA1'] 73 79 } 74 80 ); 75 81 } 76 82 77 83 chromeCallback(certificates, 78 84 function(rejectedCerts) { 79 85 if (chrome.runtime.lastError) { ................................................................................ 83 89 if (rejectedCerts.length !== 0) { 84 90 onCertificatesRejected(rejectedCerts); 85 91 } 86 92 87 93 return; 88 94 } 89 95 ); 96 + 97 + return; 90 98 } 91 99 92 100 /* 93 101 * Handle a response from the NaCl side regarding signing a message 94 102 */ 95 103 function cackeyMessageIncomingSignMessage(message, chromeCallback) { 96 104 var payload; 97 105 98 106 payload = message.signedData; 99 107 100 108 chromeCallback(payload); 109 + 110 + return; 101 111 } 102 112 103 113 /* 104 114 * Handle an incoming message from the NaCl side and pass it off to 105 115 * one of the handlers above for actual formatting and passing to 106 116 * the callback 107 117 * ................................................................................ 227 237 228 238 cackeyMessageIncoming(tmpMessageEvent); 229 239 } else { 230 240 tmpMessageEvent.data.originalrequest.pin = pinWindowPINValue; 231 241 232 242 cackeyCertificateToPINMap[cackeyCertificateToPINID(tmpMessageEvent.data.originalrequest.certificate)] = pinWindowPINValue; 233 243 234 - cackeyHandle.postMessage(tmpMessageEvent.data.originalrequest); 244 + cackeyInitPCSC(function() { 245 + cackeyHandle.postMessage(tmpMessageEvent.data.originalrequest); 246 + }); 235 247 } 236 248 } 237 249 238 250 239 251 /* 240 252 * Delete the existing handle and create a new one 241 253 */ ................................................................................ 297 309 298 310 if (GoogleSmartCard.IS_DEBUG_BUILD) { 299 311 console.log("[cackey] Asked to provide a list of certificates -- throwing that request over to the NaCl side... "); 300 312 } 301 313 302 314 callbackId = cackeyOutstandingCallbackCounter + 1; 303 315 304 - cackeyHandle.postMessage( 305 - { 306 - 'target': "cackey", 307 - 'command': "listcertificates", 308 - 'id': callbackId 316 + cackeyInitPCSC(function() { 317 + cackeyHandle.postMessage( 318 + { 319 + 'target': "cackey", 320 + 'command': "listcertificates", 321 + 'id': callbackId 322 + } 323 + ); 324 + 325 + cackeyOutstandingCallbackCounter = callbackId; 326 + cackeyOutstandingCallbacks[callbackId] = chromeCallback; 327 + 328 + if (GoogleSmartCard.IS_DEBUG_BUILD) { 329 + console.log("[cackey] Thrown."); 309 330 } 310 - ); 311 - 312 - cackeyOutstandingCallbackCounter = callbackId; 313 - cackeyOutstandingCallbacks[callbackId] = chromeCallback; 314 - 315 - if (GoogleSmartCard.IS_DEBUG_BUILD) { 316 - console.log("[cackey] Thrown."); 317 - } 331 + }); 318 332 319 333 return; 320 334 } 321 335 322 336 /* 323 337 * Handler for messages from Chrome related to signing a hash of some sort 324 338 */ ................................................................................ 371 385 372 386 certificateId = cackeyCertificateToPINID(command.certificate); 373 387 374 388 if (cackeyCertificateToPINMap[certificateId]) { 375 389 command.pin = cackeyCertificateToPINMap[certificateId]; 376 390 } 377 391 378 - cackeyHandle.postMessage(command); 392 + cackeyInitPCSC(function() { 393 + cackeyHandle.postMessage(command); 379 394 380 - cackeyOutstandingCallbackCounter = callbackId; 381 - cackeyOutstandingCallbacks[callbackId] = chromeCallback; 395 + cackeyOutstandingCallbackCounter = callbackId; 396 + cackeyOutstandingCallbacks[callbackId] = chromeCallback; 382 397 383 - if (GoogleSmartCard.IS_DEBUG_BUILD) { 384 - console.log("[cackey] Thrown."); 398 + if (GoogleSmartCard.IS_DEBUG_BUILD) { 399 + console.log("[cackey] Thrown."); 400 + } 401 + }); 402 + 403 + return; 404 +} 405 + 406 +/* 407 + * Unititalizes the CACKey PCSC connection 408 + */ 409 +function cackeyUninitPCSC() { 410 + console.log("[cackey] cackeyUninitPCSC() called"); 411 + 412 + if (cackeyPCSCHandle != null) { 413 + console.log("[cackey] Deleting PCSC handle"); 414 + 415 + delete cackeyPCSCHandle; 416 + 417 + cackeyPCSCHandle = null; 385 418 } 386 419 420 + cackeyPCSCHandleUsable = false; 421 + 422 + console.log("[cackey] cackeyUninitPCSC() returning"); 423 + 387 424 return; 388 425 } 389 426 390 427 /* 391 428 * Uninitializes CACKey (probably due to a crash) 392 429 */ 393 430 function cackeyUninit() { 431 + console.log("[cackey] cackeyUninit() called"); 432 + 394 433 if (chrome.certificateProvider) { 434 + console.log("[cackey] Unregistered Chrome certificate handlers"); 435 + 395 436 chrome.certificateProvider.onCertificatesRequested.removeListener(cackeyListCertificates); 396 437 chrome.certificateProvider.onSignDigestRequested.removeListener(cackeySignMessage); 397 438 } 398 439 399 - if (cackeyPCSCHandle != null) { 400 - delete cackeyPCSCHandle; 401 - 402 - cackeyPCSCHandle = null; 403 - } 440 + cackeyUninitPCSC(); 404 441 405 442 if (cackeyHandle != null) { 443 + console.log("[cackey] Deleting PNaCl module"); 444 + 406 445 try { 407 446 document.body.removeChild(cackeyHandle); 408 447 } catch (e) { } 409 448 410 449 delete cackeyHandle; 411 450 412 451 cackeyHandle = null; 413 452 } 453 + 454 + console.log("[cackey] cackeyUninit() complete"); 455 + 456 + return; 414 457 } 415 458 416 459 /* 417 460 * Restarts CACKey 418 461 */ 419 462 function cackeyRestart() { 420 463 cackeyUninit(); 421 464 cackeyInit(); 465 + 466 + return; 422 467 } 423 468 424 469 /* 425 470 * Handle a CACKey crash (probably due to loss of connectivity to the PCSC daemon) 426 471 */ 427 472 function cackeyCrash() { 428 473 /* 429 474 * Schedule the restart to occur in 30 seconds in case we really are 430 475 * not working. 431 476 */ 432 477 setTimeout(cackeyRestart, 30000); 478 + 479 + return; 480 +} 481 + 482 +function cackeyInitPCSCCompleted() { 483 + var idx; 484 + 485 + cackeyPCSCHandleUsable = true; 486 + 487 + for (idx = 0; idx < cackeyCallbackAfterInit.length; idx++) { 488 + if (!cackeyCallbackAfterInit[idx]) { 489 + continue; 490 + } 491 + 492 + cackeyCallbackAfterInit[idx](); 493 + } 494 + 495 + delete cackeyCallbackAfterInit; 496 + 497 + cackeyCallbackAfterInit = []; 498 + 499 + return; 433 500 } 434 501 435 502 /* 436 - * Finish performing initialization that must wait until we have loaded the CACKey module 503 + * Initialize the PCSC connection 437 504 */ 438 -function cackeyInitLoaded(messageEvent) { 439 - console.log("[cackey] Loaded CACKey PNaCl Module"); 505 +function cackeyInitPCSC(callbackAfterInit) { 506 + /* 507 + * Start the Google PCSC Interface 508 + */ 440 509 441 - /* Register listeners with Chrome */ 442 - if (chrome.certificateProvider) { 443 - chrome.certificateProvider.onCertificatesRequested.addListener(cackeyListCertificates); 444 - chrome.certificateProvider.onSignDigestRequested.addListener(cackeySignMessage); 510 + console.log("[cackey] cackeyInitPCSC() called"); 511 + 512 + /* 513 + * Queue this callback to be completed when initialization is complete 514 + */ 515 + if (callbackAfterInit) { 516 + cackeyCallbackAfterInit.push(callbackAfterInit); 517 + } 518 + 519 + /* 520 + * No additional work is required 521 + */ 522 + 523 + if (cackeyPCSCHandle) { 524 + console.log("[cackey] PCSC handle is already valid, nothing to do."); 525 + 526 + if (cackeyPCSCHandleUsable) { 527 + cackeyInitPCSCCompleted(); 528 + } 529 + 530 + return; 531 + } 532 + 533 + /* 534 + * Sanely initialize this 535 + */ 536 + cackeyPCSCHandleUsable = false; 537 + 538 + /* 539 + * Initialize the CACKey PNaCl module if needed 540 + */ 541 + if (cackeyHandle == null) { 542 + cackeyInit(); 445 543 } 446 544 447 545 /* 448 546 * Initialize CACKey with the correct handle to talk to the Google Smartcard Manager App 449 547 */ 450 548 cackeyHandle.postMessage( 451 549 { ................................................................................ 452 550 "target": "cackey", 453 551 "command": "init", 454 552 "smartcardManagerAppId": "khpfeaanjngmcnplbdlpegiifgpfgdco" 455 553 } 456 554 ); 457 555 458 556 /* 459 - * Start the Google PCSC Interface 557 + * Initialize the PCSC NaCl interface 460 558 */ 461 559 cackeyPCSCHandle = new GoogleSmartCard.PcscNacl(cackeyHandle); 560 + 561 + console.log("[cackey] cackeyInitPCSC() complete"); 562 + 563 + return; 564 +} 565 + 566 +/* 567 + * Finish performing initialization that must wait until we have loaded the CACKey module 568 + */ 569 +function cackeyInitLoaded(messageEvent) { 570 + console.log("[cackey] Loaded CACKey PNaCl Module"); 571 + 572 + /* Register listeners with Chrome */ 573 + if (chrome.certificateProvider) { 574 + console.log("[cackey] Registered Certificate handlers with Chrome"); 575 + 576 + chrome.certificateProvider.onCertificatesRequested.addListener(cackeyListCertificates); 577 + chrome.certificateProvider.onSignDigestRequested.addListener(cackeySignMessage); 578 + } 462 579 463 580 return; 464 581 } 465 582 466 583 /* 467 584 * Initialize CACKey and the PCSC library from Google 468 585 */ ................................................................................ 511 628 /* 512 629 * Force the browser to load the element 513 630 * by requesting its position 514 631 */ 515 632 forceLoadElement = cackeyHandle.offsetTop; 516 633 517 634 console.log("[cackey] cackeyInit(): Completed. Returning."); 635 + 636 + return; 518 637 } 519 638 520 639 /* 521 640 * Initialize the CACKey Chrome Application 522 641 */ 523 642 function cackeyAppInit() { 643 + var oldOnPortDisconnectedFunction; 644 + var oldPCSCInitializationCallback; 645 + 524 646 /* 525 647 * Create a handler for starting the application UI 526 648 */ 527 649 chrome.app.runtime.onLaunched.addListener(function() { 528 650 chrome.app.window.create('ui.html', { 529 651 "id": "cackeyUI", 530 652 "focused": true, ................................................................................ 532 654 "width": 350, 533 655 "minWidth": 350, 534 656 "height": 135, 535 657 "minHeight": 135 536 658 } 537 659 }); 538 660 }); 661 + 662 + /* 663 + * Register a handler for dealing with the PCSC port being disconnected 664 + */ 665 + oldOnPortDisconnectedFunction = GoogleSmartCard.Pcsc.prototype.onPortDisconnected_; 666 + GoogleSmartCard.Pcsc.prototype.onPortDisconnected_ = function() { 667 + oldOnPortDisconnectedFunction.apply(this); 668 + 669 + cackeyRestart(); 670 + 671 + return; 672 + }; 673 + 674 + /* 675 + * Register a handler for dealing with the PCSC port being available 676 + */ 677 + oldPCSCInitializationCallback = GoogleSmartCard.PcscNacl.prototype.pcscInitializationCallback_; 678 + GoogleSmartCard.PcscNacl.prototype.pcscInitializationCallback_ = function(requestId, instanceId, instance, error) { 679 + oldPCSCInitializationCallback.apply(this, [requestId, instanceId, instance, error]); 680 + 681 + cackeyInitPCSCCompleted(); 682 + 683 + return; 684 + }; 685 + 686 + return; 539 687 } 540 688 541 689 /* Initialize CACKey */ 542 690 cackeyAppInit(); 543 691 cackeyInit();