home *** CD-ROM | disk | FTP | other *** search
/ Freelog 115 / FreelogNo115-MaiJuin2013.iso / Internet / AvantBrowser / asetup.exe / _data / webkit / chrome.dll / 0 / BINDATA / 534 < prev    next >
Encoding:
Text File  |  2013-04-03  |  45.7 KB  |  1,383 lines

  1. // Copyright (c) 2012 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4.  
  5. // Copyright (c) 2012 The Chromium Authors. All rights reserved.
  6. // Use of this source code is governed by a BSD-style license that can be
  7. // found in the LICENSE file.
  8.  
  9. /**
  10.  * @fileoverview A collection of utility methods for UberPage and its contained
  11.  *     pages.
  12.  */
  13.  
  14. cr.define('uber', function() {
  15.  
  16.   /**
  17.    * Fixed position header elements on the page to be shifted by handleScroll.
  18.    * @type {NodeList}
  19.    */
  20.   var headerElements;
  21.  
  22.   /**
  23.    * This should be called by uber content pages when DOM content has loaded.
  24.    */
  25.   function onContentFrameLoaded() {
  26.     headerElements = document.getElementsByTagName('header');
  27.     document.addEventListener('scroll', handleScroll);
  28.  
  29.     // Trigger the scroll handler to tell the navigation if our page started
  30.     // with some scroll (happens when you use tab restore).
  31.     handleScroll();
  32.  
  33.     window.addEventListener('message', handleWindowMessage);
  34.   }
  35.  
  36.   /**
  37.    * Handles scroll events on the document. This adjusts the position of all
  38.    * headers and updates the parent frame when the page is scrolled.
  39.    * @private
  40.    */
  41.   function handleScroll() {
  42.     var offset = document.body.scrollLeft * -1;
  43.     for (var i = 0; i < headerElements.length; i++)
  44.       headerElements[i].style.webkitTransform = 'translateX(' + offset + 'px)';
  45.  
  46.     invokeMethodOnParent('adjustToScroll', document.body.scrollLeft);
  47.   };
  48.  
  49.   /**
  50.    * Handles 'message' events on window.
  51.    * @param {Event} e The message event.
  52.    */
  53.   function handleWindowMessage(e) {
  54.     if (e.data.method === 'frameSelected')
  55.       handleFrameSelected();
  56.     else if (e.data.method === 'mouseWheel')
  57.       handleMouseWheel(e.data.params);
  58.   }
  59.  
  60.   /**
  61.    * This is called when a user selects this frame via the navigation bar
  62.    * frame (and is triggered via postMessage() from the uber page).
  63.    * @private
  64.    */
  65.   function handleFrameSelected() {
  66.     document.body.scrollLeft = 0;
  67.   }
  68.  
  69.   /**
  70.    * Called when a user mouse wheels (or trackpad scrolls) over the nav frame.
  71.    * The wheel event is forwarded here and we scroll the body.
  72.    * There's no way to figure out the actual scroll amount for a given delta.
  73.    * It differs for every platform and even initWebKitWheelEvent takes a
  74.    * pixel amount instead of a wheel delta. So we just choose something
  75.    * reasonable and hope no one notices the difference.
  76.    * @param {Object} params A structure that holds wheel deltas in X and Y.
  77.    */
  78.   function handleMouseWheel(params) {
  79.     document.body.scrollTop -= params.deltaY * 49 / 120;
  80.     document.body.scrollLeft -= params.deltaX * 49 / 120;
  81.   }
  82.  
  83.   /**
  84.    * Invokes a method on the parent window (UberPage). This is a convenience
  85.    * method for API calls into the uber page.
  86.    * @param {String} method The name of the method to invoke.
  87.    * @param {Object=} opt_params Optional property bag of parameters to pass to
  88.    *     the invoked method.
  89.    * @private
  90.    */
  91.   function invokeMethodOnParent(method, opt_params) {
  92.     if (window.location == window.parent.location)
  93.       return;
  94.  
  95.     invokeMethodOnWindow(window.parent, method, opt_params, 'chrome://chrome');
  96.   }
  97.  
  98.   /**
  99.    * Invokes a method on the target window.
  100.    * @param {String} method The name of the method to invoke.
  101.    * @param {Object=} opt_params Optional property bag of parameters to pass to
  102.    *     the invoked method.
  103.    * @param {String=} opt_url The origin of the target window.
  104.    * @private
  105.    */
  106.   function invokeMethodOnWindow(targetWindow, method, opt_params, opt_url) {
  107.     var data = {method: method, params: opt_params};
  108.     targetWindow.postMessage(data, opt_url ? opt_url : '*');
  109.   }
  110.  
  111.   return {
  112.     invokeMethodOnParent: invokeMethodOnParent,
  113.     invokeMethodOnWindow: invokeMethodOnWindow,
  114.     onContentFrameLoaded: onContentFrameLoaded,
  115.   };
  116. });
  117.  
  118. // Copyright (c) 2012 The Chromium Authors. All rights reserved.
  119. // Use of this source code is governed by a BSD-style license that can be
  120. // found in the LICENSE file.
  121.  
  122. // Copyright (c) 2012 The Chromium Authors. All rights reserved.
  123. // Use of this source code is governed by a BSD-style license that can be
  124. // found in the LICENSE file.
  125.  
  126. cr.define('options', function() {
  127.   'use strict';
  128.  
  129.   /**
  130.    * Creates a new list of extension commands.
  131.    * @param {Object=} opt_propertyBag Optional properties.
  132.    * @constructor
  133.    * @extends {cr.ui.div}
  134.    */
  135.   var ExtensionCommandList = cr.ui.define('div');
  136.  
  137.   /**
  138.    * Returns whether the passed in |keyCode| is a valid extension command
  139.    * char or not. This is restricted to A-Z and 0-9 (ignoring modifiers) at
  140.    * the moment.
  141.    * @param {int} keyCode The keycode to consider.
  142.    * @return {boolean} Returns whether the char is valid.
  143.    */
  144.   function validChar(keyCode) {
  145.     return (keyCode >= 'A'.charCodeAt(0) && keyCode <= 'Z'.charCodeAt(0)) ||
  146.            (keyCode >= '0'.charCodeAt(0) && keyCode <= '9'.charCodeAt(0));
  147.   }
  148.  
  149.   /**
  150.    * Convert a keystroke event to string form, while taking into account
  151.    * (ignoring) invalid extension commands.
  152.    * @param {Event} event The keyboard event to convert.
  153.    * @return {string} The keystroke as a string.
  154.    */
  155.   function keystrokeToString(event) {
  156.     var output = '';
  157.     if (cr.isMac && event.metaKey)
  158.       output = 'Command+';
  159.     if (event.ctrlKey)
  160.       output = 'Ctrl+';
  161.     if (!event.ctrlKey && event.altKey)
  162.       output += 'Alt+';
  163.     if (event.shiftKey)
  164.       output += 'Shift+';
  165.     if (validChar(event.keyCode))
  166.       output += String.fromCharCode('A'.charCodeAt(0) + event.keyCode - 65);
  167.     return output;
  168.   }
  169.  
  170.   ExtensionCommandList.prototype = {
  171.     __proto__: HTMLDivElement.prototype,
  172.  
  173.     /**
  174.      * While capturing, this records the current (last) keyboard event generated
  175.      * by the user. Will be |null| after capture and during capture when no
  176.      * keyboard event has been generated.
  177.      * @type: {keyboard event}.
  178.      * @private
  179.      */
  180.     currentKeyEvent_: null,
  181.  
  182.     /**
  183.      * While capturing, this keeps track of the previous selection so we can
  184.      * revert back to if no valid assignment is made during capture.
  185.      * @type: {string}.
  186.      * @private
  187.      */
  188.     oldValue_: '',
  189.  
  190.     /**
  191.      * While capturing, this keeps track of which element the user asked to
  192.      * change.
  193.      * @type: {HTMLElement}.
  194.      * @private
  195.      */
  196.     capturingElement_: null,
  197.  
  198.     /** @override */
  199.     decorate: function() {
  200.       this.textContent = '';
  201.  
  202.       // Iterate over the extension data and add each item to the list.
  203.       this.data_.commands.forEach(this.createNodeForExtension_.bind(this));
  204.     },
  205.  
  206.     /**
  207.      * Synthesizes and initializes an HTML element for the extension command
  208.      * metadata given in |extension|.
  209.      * @param {Object} extension A dictionary of extension metadata.
  210.      * @private
  211.      */
  212.     createNodeForExtension_: function(extension) {
  213.       var template = $('template-collection-extension-commands').querySelector(
  214.           '.extension-command-list-extension-item-wrapper');
  215.       var node = template.cloneNode(true);
  216.  
  217.       var title = node.querySelector('.extension-title');
  218.       title.textContent = extension.name;
  219.  
  220.       this.appendChild(node);
  221.  
  222.       // Iterate over the commands data within the extension and add each item
  223.       // to the list.
  224.       extension.commands.forEach(this.createNodeForCommand_.bind(this));
  225.     },
  226.  
  227.     /**
  228.      * Synthesizes and initializes an HTML element for the extension command
  229.      * metadata given in |command|.
  230.      * @param {Object} command A dictionary of extension command metadata.
  231.      * @private
  232.      */
  233.     createNodeForCommand_: function(command) {
  234.       var template = $('template-collection-extension-commands').querySelector(
  235.           '.extension-command-list-command-item-wrapper');
  236.       var node = template.cloneNode(true);
  237.       node.id = this.createElementId_(
  238.           'command', command.extension_id, command.command_name);
  239.  
  240.       var description = node.querySelector('.command-description');
  241.       description.textContent = command.description;
  242.  
  243.       var shortcutNode = node.querySelector('.command-shortcut-text');
  244.       shortcutNode.addEventListener('mouseup',
  245.                                     this.startCapture_.bind(this));
  246.       shortcutNode.addEventListener('blur', this.endCapture_.bind(this));
  247.       shortcutNode.addEventListener('keydown',
  248.                                     this.handleKeyDown_.bind(this));
  249.       shortcutNode.addEventListener('keyup', this.handleKeyUp_.bind(this));
  250.       if (!command.active) {
  251.         shortcutNode.textContent =
  252.             loadTimeData.getString('extensionCommandsInactive');
  253.  
  254.         var commandShortcut = node.querySelector('.command-shortcut');
  255.         commandShortcut.classList.add('inactive-keybinding');
  256.       } else {
  257.         shortcutNode.textContent = command.keybinding;
  258.       }
  259.  
  260.       var commandClear = node.querySelector('.command-clear');
  261.       commandClear.id = this.createElementId_(
  262.           'clear', command.extension_id, command.command_name);
  263.       commandClear.title = loadTimeData.getString('extensionCommandsDelete');
  264.       commandClear.addEventListener('click', this.handleClear_.bind(this));
  265.  
  266.       this.appendChild(node);
  267.     },
  268.  
  269.     /**
  270.      * Starts keystroke capture to determine which key to use for a particular
  271.      * extension command.
  272.      * @param {Event} event The keyboard event to consider.
  273.      * @private
  274.      */
  275.     startCapture_: function(event) {
  276.       if (this.capturingElement_)
  277.         return;  // Already capturing.
  278.  
  279.       chrome.send('setShortcutHandlingSuspended', [true]);
  280.  
  281.       var shortcutNode = event.target;
  282.       this.oldValue_ = shortcutNode.textContent;
  283.       shortcutNode.textContent =
  284.           loadTimeData.getString('extensionCommandsStartTyping');
  285.       shortcutNode.parentElement.classList.add('capturing');
  286.  
  287.       var commandClear =
  288.           shortcutNode.parentElement.querySelector('.command-clear');
  289.       commandClear.hidden = true;
  290.  
  291.       this.capturingElement_ = event.target;
  292.     },
  293.  
  294.     /**
  295.      * Ends keystroke capture and either restores the old value or (if valid
  296.      * value) sets the new value as active..
  297.      * @param {Event} event The keyboard event to consider.
  298.      * @private
  299.      */
  300.     endCapture_: function(event) {
  301.       if (!this.capturingElement_)
  302.         return;  // Not capturing.
  303.  
  304.       chrome.send('setShortcutHandlingSuspended', [false]);
  305.  
  306.       var shortcutNode = this.capturingElement_;
  307.       var commandShortcut = shortcutNode.parentElement;
  308.  
  309.       commandShortcut.classList.remove('capturing');
  310.       commandShortcut.classList.remove('contains-chars');
  311.  
  312.       // When the capture ends, the user may have not given a complete and valid
  313.       // input (or even no input at all). Only a valid key event followed by a
  314.       // valid key combination will cause a shortcut selection to be activated.
  315.       // If no valid selection was made, howver, revert back to what the textbox
  316.       // had before to indicate that the shortcut registration was cancelled.
  317.       if (!this.currentKeyEvent_ || !validChar(this.currentKeyEvent_.keyCode))
  318.         shortcutNode.textContent = this.oldValue_;
  319.  
  320.       var commandClear = commandShortcut.querySelector('.command-clear');
  321.       if (this.oldValue_ == '') {
  322.         commandShortcut.classList.remove('clearable');
  323.         commandClear.hidden = true;
  324.       } else {
  325.         commandShortcut.classList.add('clearable');
  326.         commandClear.hidden = false;
  327.       }
  328.  
  329.       this.oldValue_ = '';
  330.       this.capturingElement_ = null;
  331.       this.currentKeyEvent_ = null;
  332.     },
  333.  
  334.     /**
  335.      * The KeyDown handler.
  336.      * @param {Event} event The keyboard event to consider.
  337.      * @private
  338.      */
  339.     handleKeyDown_: function(event) {
  340.       if (!this.capturingElement_)
  341.         this.startCapture_(event);
  342.  
  343.       this.handleKey_(event);
  344.     },
  345.  
  346.     /**
  347.      * The KeyUp handler.
  348.      * @param {Event} event The keyboard event to consider.
  349.      * @private
  350.      */
  351.     handleKeyUp_: function(event) {
  352.       // We want to make it easy to change from Ctrl+Shift+ to just Ctrl+ by
  353.       // releasing Shift, but we also don't want it to be easy to lose for
  354.       // example Ctrl+Shift+F to Ctrl+ just because you didn't release Ctrl
  355.       // as fast as the other two keys. Therefore, we process KeyUp until you
  356.       // have a valid combination and then stop processing it (meaning that once
  357.       // you have a valid combination, we won't change it until the next
  358.       // KeyDown message arrives).
  359.       if (!this.currentKeyEvent_ || !validChar(this.currentKeyEvent_.keyCode)) {
  360.         if (!event.ctrlKey && !event.altKey) {
  361.           // If neither Ctrl nor Alt is pressed then it is not a valid shortcut.
  362.           // That means we're back at the starting point so we should restart
  363.           // capture.
  364.           this.endCapture_(event);
  365.           this.startCapture_(event);
  366.         } else {
  367.           this.handleKey_(event);
  368.         }
  369.       }
  370.     },
  371.  
  372.     /**
  373.      * A general key handler (used for both KeyDown and KeyUp).
  374.      * @param {Event} event The keyboard event to consider.
  375.      * @private
  376.      */
  377.     handleKey_: function(event) {
  378.       // While capturing, we prevent all events from bubbling, to prevent
  379.       // shortcuts lacking the right modifier (F3 for example) from activating
  380.       // and ending capture prematurely.
  381.       event.preventDefault();
  382.       event.stopPropagation();
  383.  
  384.       if (!event.ctrlKey && !event.altKey && (!cr.isMac || !event.metaKey))
  385.         return;  // Ctrl or Alt is a must (or Cmd on Mac).
  386.  
  387.       var shortcutNode = this.capturingElement_;
  388.       var keystroke = keystrokeToString(event);
  389.       shortcutNode.textContent = keystroke;
  390.       event.target.classList.add('contains-chars');
  391.  
  392.       if (validChar(event.keyCode)) {
  393.         var node = event.target;
  394.         while (node && !node.id)
  395.           node = node.parentElement;
  396.  
  397.         this.oldValue_ = keystroke;  // Forget what the old value was.
  398.         var parsed = this.parseElementId_('command', node.id);
  399.         chrome.send('setExtensionCommandShortcut',
  400.                     [parsed.extensionId, parsed.commandName, keystroke]);
  401.         this.endCapture_(event);
  402.       }
  403.  
  404.       this.currentKeyEvent_ = event;
  405.     },
  406.  
  407.     /**
  408.      * A handler for the delete command button.
  409.      * @param {Event} event The mouse event to consider.
  410.      * @private
  411.      */
  412.     handleClear_: function(event) {
  413.       var parsed = this.parseElementId_('clear', event.target.id);
  414.       chrome.send('setExtensionCommandShortcut',
  415.           [parsed.extensionId, parsed.commandName, '']);
  416.     },
  417.  
  418.     /**
  419.      * A utility function to create a unique element id based on a namespace,
  420.      * extension id and a command name.
  421.      * @param {string} namespace   The namespace to prepend the id with.
  422.      * @param {string} extensionId The extension ID to use in the id.
  423.      * @param {string} commandName The command name to append the id with.
  424.      * @private
  425.      */
  426.     createElementId_: function(namespace, extensionId, commandName) {
  427.       return namespace + '-' + extensionId + '-' + commandName;
  428.     },
  429.  
  430.     /**
  431.      * A utility function to parse a unique element id based on a namespace,
  432.      * extension id and a command name.
  433.      * @param {string} namespace   The namespace to prepend the id with.
  434.      * @param {string} id          The id to parse.
  435.      * @return {object} The parsed id, as an object with two members:
  436.      *                  extensionID and commandName.
  437.      * @private
  438.      */
  439.     parseElementId_: function(namespace, id) {
  440.       var kExtensionIdLength = 32;
  441.       return {
  442.         extensionId: id.substring(namespace.length + 1,
  443.                                   namespace.length + 1 + kExtensionIdLength),
  444.         commandName: id.substring(namespace.length + 1 + kExtensionIdLength + 1)
  445.       };
  446.     },
  447.   };
  448.  
  449.   return {
  450.     ExtensionCommandList: ExtensionCommandList
  451.   };
  452. });
  453.  
  454.  
  455. cr.define('extensions', function() {
  456.   'use strict';
  457.  
  458.   // The Extension Commands list object that will be used to show the commands
  459.   // on the page.
  460.   var ExtensionCommandList = options.ExtensionCommandList;
  461.  
  462.   /**
  463.    * ExtensionCommandsOverlay class
  464.    * Encapsulated handling of the 'Extension Commands' overlay page.
  465.    * @constructor
  466.    */
  467.   function ExtensionCommandsOverlay() {
  468.   }
  469.  
  470.   cr.addSingletonGetter(ExtensionCommandsOverlay);
  471.  
  472.   ExtensionCommandsOverlay.prototype = {
  473.     /**
  474.      * Initialize the page.
  475.      */
  476.     initializePage: function() {
  477.       var overlay = $('overlay');
  478.       cr.ui.overlay.setupOverlay(overlay);
  479.       overlay.addEventListener('cancelOverlay', this.handleDismiss_.bind(this));
  480.  
  481.       $('extensionCommandsDismiss').addEventListener('click',
  482.           this.handleDismiss_.bind(this));
  483.  
  484.       // This will request the data to show on the page and will get a response
  485.       // back in returnExtensionsData.
  486.       chrome.send('extensionCommandsRequestExtensionsData');
  487.     },
  488.  
  489.     /**
  490.      * Handles a click on the dismiss button.
  491.      * @param {Event} e The click event.
  492.      */
  493.     handleDismiss_: function(e) {
  494.       ExtensionSettings.showOverlay(null);
  495.     },
  496.   };
  497.  
  498.   /**
  499.    * Called by the dom_ui_ to re-populate the page with data representing
  500.    * the current state of extension commands.
  501.    */
  502.   ExtensionCommandsOverlay.returnExtensionsData = function(extensionsData) {
  503.     ExtensionCommandList.prototype.data_ = extensionsData;
  504.     var extensionCommandList = $('extension-command-list');
  505.     ExtensionCommandList.decorate(extensionCommandList);
  506.  
  507.     // Make sure the config link is visible, since there are commands to show
  508.     // and potentially configure.
  509.     document.querySelector('.extension-commands-config').hidden =
  510.         extensionsData.commands.length == 0;
  511.  
  512.     $('no-commands').hidden = extensionsData.commands.length > 0;
  513.     var list = $('extension-command-list');
  514.     if (extensionsData.commands.length == 0)
  515.       list.classList.add('empty-extension-commands-list');
  516.     else
  517.       list.classList.remove('empty-extension-commands-list');
  518.   }
  519.  
  520.   // Export
  521.   return {
  522.     ExtensionCommandsOverlay: ExtensionCommandsOverlay
  523.   };
  524. });
  525.  
  526. // Update the C++ call so this isn't necessary.
  527. var ExtensionCommandsOverlay = extensions.ExtensionCommandsOverlay;
  528.  
  529. // Copyright (c) 2012 The Chromium Authors. All rights reserved.
  530. // Use of this source code is governed by a BSD-style license that can be
  531. // found in the LICENSE file.
  532.  
  533. cr.define('extensions', function() {
  534.   var FocusManager = cr.ui.FocusManager;
  535.  
  536.   function ExtensionFocusManager() {
  537.   }
  538.  
  539.   cr.addSingletonGetter(ExtensionFocusManager);
  540.  
  541.   ExtensionFocusManager.prototype = {
  542.     __proto__: FocusManager.prototype,
  543.  
  544.     /** @override */
  545.     getFocusParent: function() {
  546.       var overlay = extensions.ExtensionSettings.getCurrentOverlay();
  547.       return overlay || $('extension-settings');
  548.     },
  549.   };
  550.  
  551.   return {
  552.     ExtensionFocusManager: ExtensionFocusManager,
  553.   };
  554. });
  555.  
  556. // Copyright (c) 2012 The Chromium Authors. All rights reserved.
  557. // Use of this source code is governed by a BSD-style license that can be
  558. // found in the LICENSE file.
  559.  
  560. cr.define('options', function() {
  561.   'use strict';
  562.  
  563.   /**
  564.    * A lookup helper function to find the first node that has an id (starting
  565.    * at |node| and going up the parent chain).
  566.    * @param {Element} node The node to start looking at.
  567.    */
  568.   function findIdNode(node) {
  569.     while (node && !node.id) {
  570.       node = node.parentNode;
  571.     }
  572.     return node;
  573.   }
  574.  
  575.   /**
  576.    * Creates a new list of extensions.
  577.    * @param {Object=} opt_propertyBag Optional properties.
  578.    * @constructor
  579.    * @extends {cr.ui.div}
  580.    */
  581.   var ExtensionsList = cr.ui.define('div');
  582.  
  583.   /**
  584.    * @type {Object.<string, boolean>} A map from extension id to a boolean
  585.    *     indicating whether the incognito warning is showing. This persists
  586.    *     between calls to decorate.
  587.    */
  588.   var butterBarVisibility = {};
  589.  
  590.   ExtensionsList.prototype = {
  591.     __proto__: HTMLDivElement.prototype,
  592.  
  593.     /** @override */
  594.     decorate: function() {
  595.       this.textContent = '';
  596.  
  597.       this.showExtensionNodes_();
  598.     },
  599.  
  600.     getIdQueryParam_: function() {
  601.       return parseQueryParams(document.location)['id'];
  602.     },
  603.  
  604.     /**
  605.      * Creates all extension items from scratch.
  606.      * @private
  607.      */
  608.     showExtensionNodes_: function() {
  609.       // Iterate over the extension data and add each item to the list.
  610.       this.data_.extensions.forEach(this.createNode_, this);
  611.  
  612.       var id_to_highlight = this.getIdQueryParam_();
  613.       if (id_to_highlight) {
  614.         // Scroll offset should be calculated slightly higher than the actual
  615.         // offset of the element being scrolled to, so that it ends up not all
  616.         // the way at the top. That way it is clear that there are more elements
  617.         // above the element being scrolled to.
  618.         var scroll_fudge = 1.2;
  619.         var offset = $(id_to_highlight).offsetTop -
  620.                      (scroll_fudge * $(id_to_highlight).clientHeight);
  621.         var wrapper = this.parentNode;
  622.         var list = wrapper.parentNode;
  623.         list.scrollTop = offset;
  624.       }
  625.  
  626.       if (this.data_.extensions.length == 0)
  627.         this.classList.add('empty-extension-list');
  628.       else
  629.         this.classList.remove('empty-extension-list');
  630.     },
  631.  
  632.     /**
  633.      * Synthesizes and initializes an HTML element for the extension metadata
  634.      * given in |extension|.
  635.      * @param {Object} extension A dictionary of extension metadata.
  636.      * @private
  637.      */
  638.     createNode_: function(extension) {
  639.       var template = $('template-collection').querySelector(
  640.           '.extension-list-item-wrapper');
  641.       var node = template.cloneNode(true);
  642.       node.id = extension.id;
  643.  
  644.       if (!extension.enabled || extension.terminated)
  645.         node.classList.add('inactive-extension');
  646.  
  647.       if (!extension.userModifiable)
  648.         node.classList.add('may-not-disable');
  649.  
  650.       var id_to_highlight = this.getIdQueryParam_();
  651.       if (node.id == id_to_highlight)
  652.         node.classList.add('extension-highlight');
  653.  
  654.       var item = node.querySelector('.extension-list-item');
  655.       item.style.backgroundImage = 'url(' + extension.icon + ')';
  656.  
  657.       var title = node.querySelector('.extension-title');
  658.       title.textContent = extension.name;
  659.  
  660.       var version = node.querySelector('.extension-version');
  661.       version.textContent = extension.version;
  662.  
  663.       var disableReason = node.querySelector('.extension-disable-reason');
  664.       disableReason.textContent = extension.disableReason;
  665.  
  666.       var locationText = node.querySelector('.location-text');
  667.       locationText.textContent = extension.locationText;
  668.  
  669.       var description = node.querySelector('.extension-description span');
  670.       description.textContent = extension.description;
  671.  
  672.       // The 'Show Browser Action' button.
  673.       if (extension.enable_show_button) {
  674.         var showButton = node.querySelector('.show-button');
  675.         showButton.addEventListener('click', function(e) {
  676.           chrome.send('extensionSettingsShowButton', [extension.id]);
  677.         });
  678.         showButton.hidden = false;
  679.       }
  680.  
  681.       // The 'allow in incognito' checkbox.
  682.       var incognito = node.querySelector('.incognito-control input');
  683.       incognito.disabled = !extension.incognitoCanBeEnabled;
  684.       incognito.checked = extension.enabledIncognito;
  685.       if (!incognito.disabled) {
  686.         incognito.addEventListener('change', function(e) {
  687.           var checked = e.target.checked;
  688.           butterBarVisibility[extension.id] = checked;
  689.           butterBar.hidden = !checked || extension.is_hosted_app;
  690.           chrome.send('extensionSettingsEnableIncognito',
  691.                       [extension.id, String(checked)]);
  692.         });
  693.       }
  694.       var butterBar = node.querySelector('.butter-bar');
  695.       butterBar.hidden = !butterBarVisibility[extension.id];
  696.  
  697.       // The 'allow file:// access' checkbox.
  698.       if (extension.wantsFileAccess) {
  699.         var fileAccess = node.querySelector('.file-access-control');
  700.         fileAccess.addEventListener('click', function(e) {
  701.           chrome.send('extensionSettingsAllowFileAccess',
  702.                       [extension.id, String(e.target.checked)]);
  703.         });
  704.         fileAccess.querySelector('input').checked = extension.allowFileAccess;
  705.         fileAccess.hidden = false;
  706.       }
  707.  
  708.       // The 'Options' checkbox.
  709.       if (extension.enabled && extension.optionsUrl) {
  710.         var options = node.querySelector('.options-link');
  711.         options.addEventListener('click', function(e) {
  712.           chrome.send('extensionSettingsOptions', [extension.id]);
  713.           e.preventDefault();
  714.         });
  715.         options.hidden = false;
  716.       }
  717.  
  718.       if (extension.allow_activity) {
  719.         var activity = node.querySelector('.activity-link');
  720.         activity.addEventListener('click', function(e) {
  721.           chrome.send('navigateToUrl', [
  722.             'chrome://extension-activity?extensionId=' + extension.id,
  723.             '_blank',
  724.             e.button,
  725.             e.altKey,
  726.             e.ctrlKey,
  727.             e.metaKey,
  728.             e.shiftKey
  729.           ]);
  730.           e.preventDefault();
  731.         });
  732.         activity.hidden = false;
  733.       }
  734.  
  735.       // The 'View in Web Store/View Web Site' link.
  736.       if (extension.homepageUrl) {
  737.         var siteLink = node.querySelector('.site-link');
  738.         siteLink.href = extension.homepageUrl;
  739.         siteLink.textContent = loadTimeData.getString(
  740.                 extension.homepageProvided ? 'extensionSettingsVisitWebsite' :
  741.                                              'extensionSettingsVisitWebStore');
  742.         siteLink.hidden = false;
  743.       }
  744.  
  745.       if (extension.allow_reload) {
  746.         // The 'Reload' link.
  747.         var reload = node.querySelector('.reload-link');
  748.         reload.addEventListener('click', function(e) {
  749.           chrome.send('extensionSettingsReload', [extension.id]);
  750.         });
  751.         reload.hidden = false;
  752.  
  753.         if (extension.is_platform_app) {
  754.           // The 'Launch' link.
  755.           var launch = node.querySelector('.launch-link');
  756.           launch.addEventListener('click', function(e) {
  757.             chrome.send('extensionSettingsLaunch', [extension.id]);
  758.           });
  759.           launch.hidden = false;
  760.  
  761.           // The 'Restart' link.
  762.           var restart = node.querySelector('.restart-link');
  763.           restart.addEventListener('click', function(e) {
  764.             chrome.send('extensionSettingsRestart', [extension.id]);
  765.           });
  766.           restart.hidden = false;
  767.         }
  768.       }
  769.  
  770.       if (!extension.terminated) {
  771.         // The 'Enabled' checkbox.
  772.         var enable = node.querySelector('.enable-checkbox');
  773.         enable.hidden = false;
  774.         enable.querySelector('input').disabled = !extension.userModifiable;
  775.  
  776.         if (extension.userModifiable) {
  777.           enable.addEventListener('click', function(e) {
  778.             chrome.send('extensionSettingsEnable',
  779.                         [extension.id, e.target.checked ? 'true' : 'false']);
  780.  
  781.             // This may seem counter-intuitive (to not set/clear the checkmark)
  782.             // but this page will be updated asynchronously if the extension
  783.             // becomes enabled/disabled. It also might not become enabled or
  784.             // disabled, because the user might e.g. get prompted when enabling
  785.             // and choose not to.
  786.             e.preventDefault();
  787.           });
  788.         }
  789.  
  790.         enable.querySelector('input').checked = extension.enabled;
  791.       } else {
  792.         var terminated_reload = node.querySelector('.terminated-reload-link');
  793.         terminated_reload.hidden = false;
  794.         terminated_reload.addEventListener('click', function(e) {
  795.           chrome.send('extensionSettingsReload', [extension.id]);
  796.         });
  797.       }
  798.  
  799.       // 'Remove' button.
  800.       var trashTemplate = $('template-collection').querySelector('.trash');
  801.       var trash = trashTemplate.cloneNode(true);
  802.       trash.title = loadTimeData.getString('extensionUninstall');
  803.       trash.addEventListener('click', function(e) {
  804.         chrome.send('extensionSettingsUninstall', [extension.id]);
  805.       });
  806.       node.querySelector('.enable-controls').appendChild(trash);
  807.  
  808.       // Developer mode ////////////////////////////////////////////////////////
  809.  
  810.       // First we have the id.
  811.       var idLabel = node.querySelector('.extension-id');
  812.       idLabel.textContent = ' ' + extension.id;
  813.  
  814.       // Then the path, if provided by unpacked extension.
  815.       if (extension.isUnpacked) {
  816.         var loadPath = node.querySelector('.load-path');
  817.         loadPath.hidden = false;
  818.         loadPath.querySelector('span:nth-of-type(2)').textContent =
  819.             ' ' + extension.path;
  820.       }
  821.  
  822.       // Then the 'managed, cannot uninstall/disable' message.
  823.       if (!extension.userModifiable)
  824.         node.querySelector('.managed-message').hidden = false;
  825.  
  826.       // Then active views.
  827.       if (extension.views.length > 0) {
  828.         var activeViews = node.querySelector('.active-views');
  829.         activeViews.hidden = false;
  830.         var link = activeViews.querySelector('a');
  831.  
  832.         extension.views.forEach(function(view, i) {
  833.           var label = view.path +
  834.               (view.incognito ?
  835.                   ' ' + loadTimeData.getString('viewIncognito') : '') +
  836.               (view.renderProcessId == -1 ?
  837.                   ' ' + loadTimeData.getString('viewInactive') : '');
  838.           link.textContent = label;
  839.           link.addEventListener('click', function(e) {
  840.             // TODO(estade): remove conversion to string?
  841.             chrome.send('extensionSettingsInspect', [
  842.               String(extension.id),
  843.               String(view.renderProcessId),
  844.               String(view.renderViewId),
  845.               view.incognito
  846.             ]);
  847.           });
  848.  
  849.           if (i < extension.views.length - 1) {
  850.             link = link.cloneNode(true);
  851.             activeViews.appendChild(link);
  852.           }
  853.         });
  854.       }
  855.  
  856.       // The extension warnings (describing runtime issues).
  857.       if (extension.warnings) {
  858.         var panel = node.querySelector('.extension-warnings');
  859.         panel.hidden = false;
  860.         var list = panel.querySelector('ul');
  861.         extension.warnings.forEach(function(warning) {
  862.           list.appendChild(document.createElement('li')).innerText = warning;
  863.         });
  864.       }
  865.  
  866.       // The install warnings.
  867.       if (extension.installWarnings) {
  868.         var panel = node.querySelector('.install-warnings');
  869.         panel.hidden = false;
  870.         var list = panel.querySelector('ul');
  871.         extension.installWarnings.forEach(function(warning) {
  872.           var li = document.createElement('li');
  873.           li[warning.isHTML ? 'innerHTML' : 'innerText'] = warning.message;
  874.           list.appendChild(li);
  875.         });
  876.       }
  877.  
  878.       this.appendChild(node);
  879.     }
  880.   };
  881.  
  882.   return {
  883.     ExtensionsList: ExtensionsList
  884.   };
  885. });
  886.  
  887. // Copyright (c) 2012 The Chromium Authors. All rights reserved.
  888. // Use of this source code is governed by a BSD-style license that can be
  889. // found in the LICENSE file.
  890.  
  891. cr.define('extensions', function() {
  892.   /**
  893.    * PackExtensionOverlay class
  894.    * Encapsulated handling of the 'Pack Extension' overlay page.
  895.    * @constructor
  896.    */
  897.   function PackExtensionOverlay() {
  898.   }
  899.  
  900.   cr.addSingletonGetter(PackExtensionOverlay);
  901.  
  902.   PackExtensionOverlay.prototype = {
  903.     /**
  904.      * Initialize the page.
  905.      */
  906.     initializePage: function() {
  907.       var overlay = $('overlay');
  908.       cr.ui.overlay.setupOverlay(overlay);
  909.       overlay.addEventListener('cancelOverlay', this.handleDismiss_.bind(this));
  910.  
  911.       $('packExtensionDismiss').addEventListener('click',
  912.           this.handleDismiss_.bind(this));
  913.       $('packExtensionCommit').addEventListener('click',
  914.           this.handleCommit_.bind(this));
  915.       $('browseExtensionDir').addEventListener('click',
  916.           this.handleBrowseExtensionDir_.bind(this));
  917.       $('browsePrivateKey').addEventListener('click',
  918.           this.handleBrowsePrivateKey_.bind(this));
  919.     },
  920.  
  921.     /**
  922.      * Handles a click on the dismiss button.
  923.      * @param {Event} e The click event.
  924.      */
  925.     handleDismiss_: function(e) {
  926.       ExtensionSettings.showOverlay(null);
  927.     },
  928.  
  929.     /**
  930.      * Handles a click on the pack button.
  931.      * @param {Event} e The click event.
  932.      */
  933.     handleCommit_: function(e) {
  934.       var extensionPath = $('extensionRootDir').value;
  935.       var privateKeyPath = $('extensionPrivateKey').value;
  936.       chrome.send('pack', [extensionPath, privateKeyPath, 0]);
  937.     },
  938.  
  939.     /**
  940.      * Utility function which asks the C++ to show a platform-specific file
  941.      * select dialog, and fire |callback| with the |filePath| that resulted.
  942.      * |selectType| can be either 'file' or 'folder'. |operation| can be 'load'
  943.      * or 'pem' which are signals to the C++ to do some operation-specific
  944.      * configuration.
  945.      * @private
  946.      */
  947.     showFileDialog_: function(selectType, operation, callback) {
  948.       handleFilePathSelected = function(filePath) {
  949.         callback(filePath);
  950.         handleFilePathSelected = function() {};
  951.       };
  952.  
  953.       chrome.send('packExtensionSelectFilePath', [selectType, operation]);
  954.     },
  955.  
  956.     /**
  957.      * Handles the showing of the extension directory browser.
  958.      * @param {Event} e Change event.
  959.      * @private
  960.      */
  961.     handleBrowseExtensionDir_: function(e) {
  962.       this.showFileDialog_('folder', 'load', function(filePath) {
  963.         $('extensionRootDir').value = filePath;
  964.       });
  965.     },
  966.  
  967.     /**
  968.      * Handles the showing of the extension private key file.
  969.      * @param {Event} e Change event.
  970.      * @private
  971.      */
  972.     handleBrowsePrivateKey_: function(e) {
  973.       this.showFileDialog_('file', 'pem', function(filePath) {
  974.         $('extensionPrivateKey').value = filePath;
  975.       });
  976.     },
  977.   };
  978.  
  979.   /**
  980.    * Wrap up the pack process by showing the success |message| and closing
  981.    * the overlay.
  982.    * @param {String} message The message to show to the user.
  983.    */
  984.   PackExtensionOverlay.showSuccessMessage = function(message) {
  985.     alertOverlay.setValues(
  986.         loadTimeData.getString('packExtensionOverlay'),
  987.         message,
  988.         loadTimeData.getString('ok'),
  989.         '',
  990.         function() {
  991.           ExtensionSettings.showOverlay(null);
  992.         },
  993.         null);
  994.     ExtensionSettings.showOverlay($('alertOverlay'));
  995.   };
  996.  
  997.   /**
  998.    * Post an alert overlay showing |message|, and upon acknowledgement, close
  999.    * the alert overlay and return to showing the PackExtensionOverlay.
  1000.    */
  1001.   PackExtensionOverlay.showError = function(message) {
  1002.     alertOverlay.setValues(
  1003.         loadTimeData.getString('packExtensionErrorTitle'),
  1004.         message,
  1005.         loadTimeData.getString('ok'),
  1006.         '',
  1007.         function() {
  1008.           ExtensionSettings.showOverlay($('packExtensionOverlay'));
  1009.         },
  1010.         null);
  1011.     ExtensionSettings.showOverlay($('alertOverlay'));
  1012.   };
  1013.  
  1014.   // Export
  1015.   return {
  1016.     PackExtensionOverlay: PackExtensionOverlay
  1017.   };
  1018. });
  1019.  
  1020. // Update the C++ call so this isn't necessary.
  1021. var PackExtensionOverlay = extensions.PackExtensionOverlay;
  1022.  
  1023.  
  1024. // Used for observing function of the backend datasource for this page by
  1025. // tests.
  1026. var webui_responded_ = false;
  1027.  
  1028. cr.define('extensions', function() {
  1029.   var ExtensionsList = options.ExtensionsList;
  1030.  
  1031.   // Implements the DragWrapper handler interface.
  1032.   var dragWrapperHandler = {
  1033.     // @inheritdoc
  1034.     shouldAcceptDrag: function(e) {
  1035.       // We can't access filenames during the 'dragenter' event, so we have to
  1036.       // wait until 'drop' to decide whether to do something with the file or
  1037.       // not.
  1038.       // See: http://www.w3.org/TR/2011/WD-html5-20110113/dnd.html#concept-dnd-p
  1039.       return e.dataTransfer.types.indexOf('Files') > -1;
  1040.     },
  1041.     // @inheritdoc
  1042.     doDragEnter: function() {
  1043.       chrome.send('startDrag');
  1044.       ExtensionSettings.showOverlay(null);
  1045.       ExtensionSettings.showOverlay($('dropTargetOverlay'));
  1046.     },
  1047.     // @inheritdoc
  1048.     doDragLeave: function() {
  1049.       ExtensionSettings.showOverlay(null);
  1050.       chrome.send('stopDrag');
  1051.     },
  1052.     // @inheritdoc
  1053.     doDragOver: function(e) {
  1054.       e.preventDefault();
  1055.     },
  1056.     // @inheritdoc
  1057.     doDrop: function(e) {
  1058.       // Only process files that look like extensions. Other files should
  1059.       // navigate the browser normally.
  1060.       if (!e.dataTransfer.files.length ||
  1061.           !/\.(crx|user\.js)$/.test(e.dataTransfer.files[0].name)) {
  1062.         return;
  1063.       }
  1064.  
  1065.       chrome.send('installDroppedFile');
  1066.       ExtensionSettings.showOverlay(null);
  1067.       e.preventDefault();
  1068.     }
  1069.   };
  1070.  
  1071.   /**
  1072.    * ExtensionSettings class
  1073.    * @class
  1074.    */
  1075.   function ExtensionSettings() {}
  1076.  
  1077.   cr.addSingletonGetter(ExtensionSettings);
  1078.  
  1079.   ExtensionSettings.prototype = {
  1080.     __proto__: HTMLDivElement.prototype,
  1081.  
  1082.     /**
  1083.      * Perform initial setup.
  1084.      */
  1085.     initialize: function() {
  1086.       uber.onContentFrameLoaded();
  1087.  
  1088.       measureCheckboxStrings();
  1089.  
  1090.       // Set the title.
  1091.       var title = loadTimeData.getString('extensionSettings');
  1092.       uber.invokeMethodOnParent('setTitle', {title: title});
  1093.  
  1094.       // This will request the data to show on the page and will get a response
  1095.       // back in returnExtensionsData.
  1096.       chrome.send('extensionSettingsRequestExtensionsData');
  1097.  
  1098.       $('toggle-dev-on').addEventListener('change',
  1099.           this.handleToggleDevMode_.bind(this));
  1100.       $('dev-controls').addEventListener('webkitTransitionEnd',
  1101.           this.handleDevControlsTransitionEnd_.bind(this));
  1102.  
  1103.       // Set up the three dev mode buttons (load unpacked, pack and update).
  1104.       $('load-unpacked').addEventListener('click',
  1105.           this.handleLoadUnpackedExtension_.bind(this));
  1106.       $('pack-extension').addEventListener('click',
  1107.           this.handlePackExtension_.bind(this));
  1108.       $('update-extensions-now').addEventListener('click',
  1109.           this.handleUpdateExtensionNow_.bind(this));
  1110.  
  1111.       if (!loadTimeData.getBoolean('offStoreInstallEnabled')) {
  1112.         this.dragWrapper_ = new cr.ui.DragWrapper(document.documentElement,
  1113.                                                   dragWrapperHandler);
  1114.       }
  1115.  
  1116.       var packExtensionOverlay = extensions.PackExtensionOverlay.getInstance();
  1117.       packExtensionOverlay.initializePage();
  1118.  
  1119.       // Hook up the configure commands link to the overlay.
  1120.       var link = document.querySelector('.extension-commands-config');
  1121.       link.addEventListener('click',
  1122.           this.handleExtensionCommandsConfig_.bind(this));
  1123.  
  1124.       // Initialize the Commands overlay.
  1125.       var extensionCommandsOverlay =
  1126.           extensions.ExtensionCommandsOverlay.getInstance();
  1127.       extensionCommandsOverlay.initializePage();
  1128.  
  1129.       cr.ui.overlay.setupOverlay($('dropTargetOverlay'));
  1130.  
  1131.       extensions.ExtensionFocusManager.getInstance().initialize();
  1132.  
  1133.       var path = document.location.pathname;
  1134.       if (path.length > 1) {
  1135.         // Skip starting slash and remove trailing slash (if any).
  1136.         var overlayName = path.slice(1).replace(/\/$/, '');
  1137.         if (overlayName == 'configureCommands')
  1138.           this.showExtensionCommandsConfigUi_();
  1139.       }
  1140.  
  1141.       preventDefaultOnPoundLinkClicks();  // From shared/js/util.js.
  1142.     },
  1143.  
  1144.     /**
  1145.      * Handles the Load Unpacked Extension button.
  1146.      * @param {Event} e Change event.
  1147.      * @private
  1148.      */
  1149.     handleLoadUnpackedExtension_: function(e) {
  1150.       chrome.send('extensionSettingsLoadUnpackedExtension');
  1151.  
  1152.       // TODO(jhawkins): Refactor metrics support out of options and use it
  1153.       // in extensions.html.
  1154.       chrome.send('coreOptionsUserMetricsAction',
  1155.                   ['Options_LoadUnpackedExtension']);
  1156.     },
  1157.  
  1158.     /**
  1159.      * Handles the Pack Extension button.
  1160.      * @param {Event} e Change event.
  1161.      * @private
  1162.      */
  1163.     handlePackExtension_: function(e) {
  1164.       ExtensionSettings.showOverlay($('packExtensionOverlay'));
  1165.       chrome.send('coreOptionsUserMetricsAction', ['Options_PackExtension']);
  1166.     },
  1167.  
  1168.     /**
  1169.      * Shows the Extension Commands configuration UI.
  1170.      * @param {Event} e Change event.
  1171.      * @private
  1172.      */
  1173.     showExtensionCommandsConfigUi_: function(e) {
  1174.       ExtensionSettings.showOverlay($('extensionCommandsOverlay'));
  1175.       chrome.send('coreOptionsUserMetricsAction',
  1176.                   ['Options_ExtensionCommands']);
  1177.     },
  1178.  
  1179.     /**
  1180.      * Handles the Configure (Extension) Commands link.
  1181.      * @param {Event} e Change event.
  1182.      * @private
  1183.      */
  1184.     handleExtensionCommandsConfig_: function(e) {
  1185.       this.showExtensionCommandsConfigUi_();
  1186.     },
  1187.  
  1188.     /**
  1189.      * Handles the Update Extension Now button.
  1190.      * @param {Event} e Change event.
  1191.      * @private
  1192.      */
  1193.     handleUpdateExtensionNow_: function(e) {
  1194.       chrome.send('extensionSettingsAutoupdate');
  1195.     },
  1196.  
  1197.     /**
  1198.      * Handles the Toggle Dev Mode button.
  1199.      * @param {Event} e Change event.
  1200.      * @private
  1201.      */
  1202.     handleToggleDevMode_: function(e) {
  1203.       if ($('toggle-dev-on').checked) {
  1204.         $('dev-controls').hidden = false;
  1205.         window.setTimeout(function() {
  1206.           $('extension-settings').classList.add('dev-mode');
  1207.         }, 0);
  1208.       } else {
  1209.         $('extension-settings').classList.remove('dev-mode');
  1210.       }
  1211.  
  1212.       chrome.send('extensionSettingsToggleDeveloperMode');
  1213.     },
  1214.  
  1215.     /**
  1216.      * Called when a transition has ended for #dev-controls.
  1217.      * @param {Event} e webkitTransitionEnd event.
  1218.      * @private
  1219.      */
  1220.     handleDevControlsTransitionEnd_: function(e) {
  1221.       if (e.propertyName == 'height' &&
  1222.           !$('extension-settings').classList.contains('dev-mode')) {
  1223.         $('dev-controls').hidden = true;
  1224.       }
  1225.     },
  1226.   };
  1227.  
  1228.   /**
  1229.    * Called by the dom_ui_ to re-populate the page with data representing
  1230.    * the current state of installed extensions.
  1231.    */
  1232.   ExtensionSettings.returnExtensionsData = function(extensionsData) {
  1233.     // We can get called many times in short order, thus we need to
  1234.     // be careful to remove the 'finished loading' timeout.
  1235.     if (this.loadingTimeout_)
  1236.       window.clearTimeout(this.loadingTimeout_);
  1237.     document.documentElement.classList.add('loading');
  1238.     this.loadingTimeout_ = window.setTimeout(function() {
  1239.       document.documentElement.classList.remove('loading');
  1240.     }, 0);
  1241.  
  1242.     webui_responded_ = true;
  1243.  
  1244.     if (extensionsData.extensions.length > 0) {
  1245.       // Enforce order specified in the data or (if equal) then sort by
  1246.       // extension name (case-insensitive).
  1247.       extensionsData.extensions.sort(function(a, b) {
  1248.         if (a.order == b.order) {
  1249.           a = a.name.toLowerCase();
  1250.           b = b.name.toLowerCase();
  1251.           return a < b ? -1 : (a > b ? 1 : 0);
  1252.         } else {
  1253.           return a.order < b.order ? -1 : 1;
  1254.         }
  1255.       });
  1256.     }
  1257.  
  1258.     var pageDiv = $('extension-settings');
  1259.     var marginTop = 0;
  1260.     if (extensionsData.managedMode) {
  1261.       pageDiv.classList.add('showing-banner');
  1262.       pageDiv.classList.add('managed-mode');
  1263.       $('toggle-dev-on').disabled = true;
  1264.       marginTop += 45;
  1265.     } else {
  1266.       pageDiv.classList.remove('showing-banner');
  1267.       pageDiv.classList.remove('managed-mode');
  1268.       $('toggle-dev-on').disabled = false;
  1269.     }
  1270.  
  1271.     if (extensionsData.showDisabledExtensionsWarning) {
  1272.       pageDiv.classList.add('showing-banner');
  1273.       pageDiv.classList.add('sideload-wipeout');
  1274.       marginTop += 60;
  1275.     }
  1276.     pageDiv.style.marginTop = marginTop + 'px';
  1277.  
  1278.     if (extensionsData.developerMode && !extensionsData.managedMode) {
  1279.       pageDiv.classList.add('dev-mode');
  1280.       $('toggle-dev-on').checked = true;
  1281.       $('dev-controls').hidden = false;
  1282.     } else {
  1283.       pageDiv.classList.remove('dev-mode');
  1284.       $('toggle-dev-on').checked = false;
  1285.     }
  1286.  
  1287.     $('load-unpacked').disabled = extensionsData.loadUnpackedDisabled;
  1288.  
  1289.     ExtensionsList.prototype.data_ = extensionsData;
  1290.     var extensionList = $('extension-settings-list');
  1291.     ExtensionsList.decorate(extensionList);
  1292.   }
  1293.  
  1294.   // Indicate that warning |message| has occured for pack of |crx_path| and
  1295.   // |pem_path| files.  Ask if user wants override the warning.  Send
  1296.   // |overrideFlags| to repeated 'pack' call to accomplish the override.
  1297.   ExtensionSettings.askToOverrideWarning =
  1298.       function(message, crx_path, pem_path, overrideFlags) {
  1299.     var closeAlert = function() {
  1300.       ExtensionSettings.showOverlay(null);
  1301.     };
  1302.  
  1303.     alertOverlay.setValues(
  1304.         loadTimeData.getString('packExtensionWarningTitle'),
  1305.         message,
  1306.         loadTimeData.getString('packExtensionProceedAnyway'),
  1307.         loadTimeData.getString('cancel'),
  1308.         function() {
  1309.           chrome.send('pack', [crx_path, pem_path, overrideFlags]);
  1310.           closeAlert();
  1311.         },
  1312.         closeAlert);
  1313.     ExtensionSettings.showOverlay($('alertOverlay'));
  1314.   }
  1315.  
  1316.   /**
  1317.    * Returns the current overlay or null if one does not exist.
  1318.    * @return {Element} The overlay element.
  1319.    */
  1320.   ExtensionSettings.getCurrentOverlay = function() {
  1321.     return document.querySelector('#overlay .page.showing');
  1322.   }
  1323.  
  1324.   /**
  1325.    * Sets the given overlay to show. This hides whatever overlay is currently
  1326.    * showing, if any.
  1327.    * @param {HTMLElement} node The overlay page to show. If falsey, all overlays
  1328.    *     are hidden.
  1329.    */
  1330.   ExtensionSettings.showOverlay = function(node) {
  1331.     var currentlyShowingOverlay = ExtensionSettings.getCurrentOverlay();
  1332.     if (currentlyShowingOverlay)
  1333.       currentlyShowingOverlay.classList.remove('showing');
  1334.  
  1335.     if (node)
  1336.       node.classList.add('showing');
  1337.     overlay.hidden = !node;
  1338.     uber.invokeMethodOnParent(node ? 'beginInterceptingEvents' :
  1339.                                      'stopInterceptingEvents');
  1340.   }
  1341.  
  1342.   /**
  1343.    * Utility function to find the width of various UI strings and synchronize
  1344.    * the width of relevant spans. This is crucial for making sure the
  1345.    * Enable/Enabled checkboxes align, as well as the Developer Mode checkbox.
  1346.    */
  1347.   function measureCheckboxStrings() {
  1348.     var trashWidth = 30;
  1349.     var measuringDiv = $('font-measuring-div');
  1350.     measuringDiv.textContent =
  1351.         loadTimeData.getString('extensionSettingsEnabled');
  1352.     var pxWidth = measuringDiv.clientWidth + trashWidth;
  1353.     measuringDiv.textContent =
  1354.         loadTimeData.getString('extensionSettingsEnable');
  1355.     pxWidth = Math.max(measuringDiv.clientWidth + trashWidth, pxWidth);
  1356.     measuringDiv.textContent =
  1357.         loadTimeData.getString('extensionSettingsDeveloperMode');
  1358.     pxWidth = Math.max(measuringDiv.clientWidth, pxWidth);
  1359.  
  1360.     var style = document.createElement('style');
  1361.     style.type = 'text/css';
  1362.     style.textContent =
  1363.         '.enable-checkbox-text {' +
  1364.         '  min-width: ' + (pxWidth - trashWidth) + 'px;' +
  1365.         '}' +
  1366.         '#dev-toggle span {' +
  1367.         '  min-width: ' + pxWidth + 'px;' +
  1368.         '}';
  1369.     document.querySelector('head').appendChild(style);
  1370.   }
  1371.  
  1372.   // Export
  1373.   return {
  1374.     ExtensionSettings: ExtensionSettings
  1375.   };
  1376. });
  1377.  
  1378. var ExtensionSettings = extensions.ExtensionSettings;
  1379.  
  1380. window.addEventListener('load', function(e) {
  1381.   ExtensionSettings.getInstance().initialize();
  1382. });
  1383.