Source: js/activity_window_manager.js

  1. /* global Service */
  2. 'use strict';
  3. (function(exports) {
  4. /**
  5. * ActivityWindowManager manages the activity window instances.
  6. *
  7. * Currently it's only responsible to kill an existing
  8. * activity window if the next creating instance has the same
  9. * manifestURL + pageURL.
  10. *
  11. * @class ActivityWindowManager
  12. */
  13. function ActivityWindowManager() {
  14. }
  15. ActivityWindowManager.prototype = {
  16. /**
  17. * The list of all current running activity window instances.
  18. * @access private
  19. * @type {Array}
  20. * @memberof ActivityWindowManager.prototype
  21. */
  22. _activities: [],
  23. /**
  24. * Register all event handlers.
  25. * @memberof ActivityWindowManager.prototype
  26. */
  27. start: function acwf_start() {
  28. if (this._started) {
  29. return;
  30. }
  31. this._started = true;
  32. this.activityPool = new Map();
  33. window.addEventListener('activityopened', this);
  34. window.addEventListener('popupopened', this);
  35. window.addEventListener('appopened', this);
  36. window.addEventListener('activityrequesting', this);
  37. window.addEventListener('activitycreated', this);
  38. window.addEventListener('activityterminated', this);
  39. },
  40. /**
  41. * Unregister all event handlers.
  42. * @memberof ActivityWindowManager.prototype
  43. */
  44. stop: function acwf_stop() {
  45. if (!this._started) {
  46. return;
  47. }
  48. this._started = false;
  49. this.activityPool = null;
  50. window.removeEventListener('activityopened', this);
  51. window.removeEventListener('popupopened', this);
  52. window.removeEventListener('appopened', this);
  53. window.removeEventListener('activityrequesting', this);
  54. window.removeEventListener('activitycreated', this);
  55. window.removeEventListener('activityterminated', this);
  56. },
  57. /**
  58. * Put all window ID which is involved in an activity here.
  59. * XXX: This is a workaround of bug 931339.
  60. * @type {Map}
  61. */
  62. activityPool: null,
  63. /**
  64. * Activity Config
  65. * @typedef {Object} ActivityConfig
  66. * @property {String} manifestURL The manifestURL of the activity
  67. * @property {String} url The URL of the activity handling page
  68. * @property {Boolean} isActivity
  69. * @property {Boolean} inline The disposition of the activty is inline
  70. * or not
  71. */
  72. handleEvent: function acwf_handleEvent(evt) {
  73. switch (evt.type) {
  74. // XXX: Workaround of bug 931339.
  75. // We are maintaining only one chain of activities here
  76. // in this.activityPool.
  77. // If the next coming activity request does not belong
  78. // to the previous pool,
  79. // kill all the background inline activities.
  80. case 'popupopened':
  81. case 'activityopened':
  82. case 'appopened':
  83. var app = evt.detail;
  84. var parent = app.callerWindow ||
  85. app.bottomWindow ||
  86. app.previousWindow;
  87. if (parent && this.activityPool.has(parent.instanceID)) {
  88. // We don't really care about the instance context,
  89. // so we set the value to a boolean.
  90. this.activityPool.set(app.instanceID, true);
  91. }
  92. break;
  93. case 'popupterminated':
  94. case 'appterminated':
  95. this.activityPool.delete(app.instanceID);
  96. break;
  97. case 'activityrequesting':
  98. // The request may come from the top most window
  99. // or the system app, but we don't care here.
  100. var caller = Service.query('getTopMostWindow');
  101. if (!this.activityPool.size) {
  102. this.activityPool.set(caller.instanceID, true);
  103. } else {
  104. if (!this.activityPool.has(caller.instanceID)) {
  105. // A new request from a new chain,
  106. // kill all the background.
  107. this._activities.forEach(function iterator(activity, index) {
  108. if (!activity.getBottomMostWindow().isActive() ||
  109. !activity.isActive()) {
  110. activity.kill();
  111. }
  112. }, this);
  113. this.activityPool.clear();
  114. this.activityPool.set(caller.instanceID, true);
  115. }
  116. }
  117. break;
  118. case 'activityterminated':
  119. this._activities.some(function iterator(activity, index) {
  120. if (activity.instanceID === evt.detail.instanceID) {
  121. this._activities.splice(index, 1);
  122. return true;
  123. }
  124. }, this);
  125. this.activityPool.delete(evt.detail.instanceID);
  126. break;
  127. case 'activitycreated':
  128. this._activities.push(evt.detail);
  129. break;
  130. }
  131. }
  132. };
  133. exports.ActivityWindowManager = ActivityWindowManager;
  134. }(window));