Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / third_party / WebKit / Source / devtools / front_end / emulation / OverridesUI.js
blobf25a3ea627ead651c137448bb2fdccaac4915cba
1 // Copyright 2014 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.
5 WebInspector.OverridesUI = {}
7 /**
8  * @constructor
9  * @param {!Element} rotateButton
10  * @param {?function(!WebInspector.EmulatedDevice, !WebInspector.EmulatedDevice.Mode)} callback
11  */
12 WebInspector.DeviceSelect = function(rotateButton, callback)
14     this._callback = callback;
15     this._rotateButton = rotateButton;
16     this.element = createElement("p");
18     this._deviceSelectElement = this.element.createChild("select", "device-select");
19     this._deviceSelectElement.addEventListener("change", this._deviceSelected.bind(this), false);
21     var container = this.element.createChild("div", "mode-container");
22     container.appendChild(this._rotateButton);
23     this._rotateButton.addEventListener("click", this._rotateButtonClicked.bind(this), false);
24     this._rotateButton.title = WebInspector.UIString("Change orientation");
26     var modeSelectContainer = container.createChild("span", "mode-select");
27     this._modeSelectElement = modeSelectContainer.createChild("select");
28     this._modeSelectElement.addEventListener("change", this._modeSelected.bind(this), false);
29     this._modeLabelElement = modeSelectContainer.createChild("label");
30     this._modeLabelElement.addEventListener("click", this._rotateButtonClicked.bind(this), false);
31     this._modeLabelElement.title = WebInspector.UIString("Change orientation");
33     this._emulatedSettingChangedMuted = false;
34     this._lastOrientation = null;
36     WebInspector.overridesSupport.settings.emulateResolution.addChangeListener(this._emulatedSettingChanged, this);
37     WebInspector.overridesSupport.settings.deviceWidth.addChangeListener(this._emulatedSettingChanged, this);
38     WebInspector.overridesSupport.settings.deviceHeight.addChangeListener(this._emulatedSettingChanged, this);
39     WebInspector.overridesSupport.settings.deviceScaleFactor.addChangeListener(this._emulatedSettingChanged, this);
40     WebInspector.overridesSupport.settings.emulateMobile.addChangeListener(this._emulatedSettingChanged, this);
41     WebInspector.overridesSupport.settings.emulateTouch.addChangeListener(this._emulatedSettingChanged, this);
42     WebInspector.overridesSupport.settings.userAgent.addChangeListener(this._emulatedSettingChanged, this);
44     WebInspector.emulatedDevicesList.addEventListener(WebInspector.EmulatedDevicesList.Events.CustomDevicesUpdated, this._deviceListChanged, this);
45     WebInspector.emulatedDevicesList.addEventListener(WebInspector.EmulatedDevicesList.Events.StandardDevicesUpdated, this._deviceListChanged, this);
46     this._deviceListChanged();
49 WebInspector.DeviceSelect.prototype = {
50     _deviceListChanged: function()
51     {
52         this._deviceSelectElement.removeChildren();
54         var selectDeviceOption = new Option(WebInspector.UIString("<Select model>"), WebInspector.UIString("<Select model>"));
55         selectDeviceOption.device = null;
56         selectDeviceOption.lastSelectedIndex = 0;
57         selectDeviceOption.disabled = true;
58         this._deviceSelectElement.appendChild(selectDeviceOption);
60         this._addDeviceGroup(WebInspector.UIString("Custom"), WebInspector.emulatedDevicesList.custom());
61         this._addDeviceGroup(WebInspector.UIString("Devices"), WebInspector.emulatedDevicesList.standard());
62         this._emulatedSettingChanged();
63     },
65     /**
66      * @param {string} name
67      * @param {!Array.<!WebInspector.EmulatedDevice>} devices
68      */
69     _addDeviceGroup: function(name, devices)
70     {
71         devices = devices.filter(function (d) { return d.show(); });
72         if (!devices.length)
73             return;
74         devices.sort(WebInspector.EmulatedDevice.compareByTitle);
75         var groupElement = this._deviceSelectElement.createChild("optgroup");
76         groupElement.label = name;
77         for (var i = 0; i < devices.length; ++i) {
78             var option = new Option(devices[i].title, devices[i].title);
79             option.device = devices[i];
80             option.lastSelectedIndex = 0;
81             groupElement.appendChild(option);
82         }
83     },
85     _emulatedSettingChanged: function()
86     {
87         if (this._emulatedSettingChangedMuted)
88             return;
90         for (var i = 1; i < this._deviceSelectElement.options.length; ++i) {
91             var option = this._deviceSelectElement.options[i];
92             var device = /** @type {!WebInspector.EmulatedDevice} */ (option.device);
93             for (var j = 0; j < device.modes.length; j++) {
94                 if (WebInspector.overridesSupport.isEmulatingDevice(device.modeToOverridesDevice(device.modes[j]))) {
95                     this._select(device, device.modes[j]);
96                     return;
97                 }
98             }
99         }
101         this._select(null, null);
102     },
104     /**
105      * @param {?WebInspector.EmulatedDevice} device
106      * @param {?WebInspector.EmulatedDevice.Mode} mode
107      */
108     _select: function(device, mode)
109     {
110         for (var i = 0; i < this._deviceSelectElement.options.length; i++) {
111             if (this._deviceSelectElement.options[i].device === device)
112                 this._deviceSelectElement.selectedIndex = i;
113         }
114         this._updateModeSelect();
115         for (var i = 0; i < this._modeSelectElement.options.length; i++) {
116             if (this._modeSelectElement.options[i].mode === mode)
117                 this._modeSelectElement.selectedIndex = i;
118         }
119         this._updateModeControls();
120         this._saveLastSelectedIndex();
121         if (this._callback) {
122             var option = this._modeSelectElement.options[this._modeSelectElement.selectedIndex];
123             this._callback(option.device, option.mode);
124         }
125     },
127     _deviceSelected: function()
128     {
129         this._updateModeSelect();
130         this._modeSelected();
131     },
133     _updateModeSelect: function()
134     {
135         this._modeSelectElement.removeChildren();
136         var option = this._deviceSelectElement.options[this._deviceSelectElement.selectedIndex];
137         var device = /** @type {!WebInspector.EmulatedDevice} */ (option.device);
139         if (this._deviceSelectElement.selectedIndex === 0) {
140             this._addMode(device, null, "");
141         } else if (device.modes.length === 1) {
142             this._addMode(device, device.modes[0], WebInspector.UIString("Default"));
143         } else {
144             this._addOrientation(device, WebInspector.EmulatedDevice.Vertical, WebInspector.UIString("Portrait"));
145             this._addOrientation(device, WebInspector.EmulatedDevice.Horizontal, WebInspector.UIString("Landscape"));
146         }
147         this._updateRotateModes();
149         var index = option.lastSelectedIndex;
150         var modeOption = this._modeSelectElement.options[index];
151         if (modeOption.rotateIndex != -1) {
152             var rotateOption = this._modeSelectElement.options[modeOption.rotateIndex];
153             if (rotateOption.mode && rotateOption.mode.orientation === this._lastOrientation)
154                 index = modeOption.rotateIndex;
155         }
156         this._modeSelectElement.selectedIndex = index;
157         this._updateModeControls();
158     },
160     /**
161      * @param {!WebInspector.EmulatedDevice} device
162      * @param {string} orientation
163      * @param {string} title
164      */
165     _addOrientation: function(device, orientation, title)
166     {
167         var modes = device.modesForOrientation(orientation);
168         if (!modes.length)
169             return;
170         if (modes.length === 1) {
171             this._addMode(device, modes[0], title);
172         } else {
173             for (var index = 0; index < modes.length; index++)
174                 this._addMode(device, modes[index], title + " \u2013 " + modes[index].title);
175         }
176     },
178     /**
179      * @param {!WebInspector.EmulatedDevice} device
180      * @param {?WebInspector.EmulatedDevice.Mode} mode
181      * @param {string} title
182      */
183     _addMode: function(device, mode, title)
184     {
185         var option = new Option(title, title);
186         option.mode = mode;
187         option.device = device;
188         this._modeSelectElement.appendChild(option);
189     },
191     _updateRotateModes: function()
192     {
193         for (var i = 0; i < this._modeSelectElement.options.length; i++) {
194             var modeI = this._modeSelectElement.options[i].mode;
195             this._modeSelectElement.options[i].rotateIndex = -1;
196             for (var j = 0; j < this._modeSelectElement.options.length; j++) {
197                 var modeJ = this._modeSelectElement.options[j].mode;
198                 if (modeI && modeJ && modeI.orientation !== modeJ.orientation && modeI.title === modeJ.title)
199                     this._modeSelectElement.options[i].rotateIndex = j;
200             }
201         }
202     },
204     _updateModeControls: function()
205     {
206         this._modeLabelElement.textContent = this._modeSelectElement.options[this._modeSelectElement.selectedIndex].label;
208         if (this._modeSelectElement.options.length <= 1) {
209             this._modeSelectElement.classList.toggle("hidden", true);
210             this._modeLabelElement.classList.toggle("hidden", true);
211         } else {
212             var showLabel = this._modeSelectElement.options.length === 2 && this._modeSelectElement.options[0].rotateIndex === 1;
213             this._modeSelectElement.classList.toggle("hidden",  showLabel);
214             this._modeLabelElement.classList.toggle("hidden", !showLabel);
215         }
217         this._rotateButton.classList.toggle("hidden", this._modeSelectElement.options[this._modeSelectElement.selectedIndex].rotateIndex === -1);
218     },
220     _modeSelected: function()
221     {
222         this._saveLastSelectedIndex();
223         this._updateModeControls();
224         var option = this._modeSelectElement.options[this._modeSelectElement.selectedIndex];
225         if (this._callback)
226             this._callback(option.device, option.mode);
227         this._emulatedSettingChangedMuted = true;
228         WebInspector.overridesSupport.emulateDevice(option.device.modeToOverridesDevice(option.mode));
229         this._emulatedSettingChangedMuted = false;
230     },
232     _saveLastSelectedIndex: function()
233     {
234         this._deviceSelectElement.options[this._deviceSelectElement.selectedIndex].lastSelectedIndex = this._modeSelectElement.selectedIndex;
236         var option = this._modeSelectElement.options[this._modeSelectElement.selectedIndex];
237         if (option.mode && option.rotateIndex != -1)
238             this._lastOrientation = option.mode.orientation;
239     },
241     _rotateButtonClicked: function()
242     {
243         this._modeSelectElement.selectedIndex = this._modeSelectElement.options[this._modeSelectElement.selectedIndex].rotateIndex;
244         this._modeSelected();
245     }
250  * @return {{select: !Element, input: !Element}}
251  */
252 WebInspector.OverridesUI.createUserAgentSelectAndInput = function()
254     var userAgentSetting = WebInspector.overridesSupport.settings.userAgent;
255     const noOverride = {title: WebInspector.UIString("No override"), value: ""};
256     const customOverride = {title: WebInspector.UIString("Other"), value: "Other"};
257     var userAgents = [noOverride].concat(WebInspector.OverridesUI._userAgents).concat([customOverride]);
259     var userAgentSelectElement = createElement("select");
260     for (var i = 0; i < userAgents.length; ++i)
261         userAgentSelectElement.add(new Option(userAgents[i].title, userAgents[i].value));
262     userAgentSelectElement.selectedIndex = 0;
264     var otherUserAgentElement = createElement("input");
265     otherUserAgentElement.type = "text";
266     otherUserAgentElement.value = userAgentSetting.get();
267     otherUserAgentElement.title = userAgentSetting.get();
269     settingChanged();
270     userAgentSetting.addChangeListener(settingChanged);
271     userAgentSelectElement.addEventListener("change", userAgentSelected, false);
273     otherUserAgentElement.addEventListener("dblclick", textDoubleClicked, true);
274     otherUserAgentElement.addEventListener("blur", textChanged, false);
275     otherUserAgentElement.addEventListener("keydown", textKeyDown, false);
277     function userAgentSelected()
278     {
279         var value = userAgentSelectElement.options[userAgentSelectElement.selectedIndex].value;
280         if (value !== customOverride.value) {
281             userAgentSetting.removeChangeListener(settingChanged);
282             userAgentSetting.set(value);
283             userAgentSetting.addChangeListener(settingChanged);
284             otherUserAgentElement.value = value;
285             otherUserAgentElement.title = value;
286             otherUserAgentElement.readOnly = true;
287         } else {
288             otherUserAgentElement.readOnly = false;
289             otherUserAgentElement.focus();
290         }
291     }
293     function settingChanged()
294     {
295         var value = userAgentSetting.get();
296         var options = userAgentSelectElement.options;
297         var selectionRestored = false;
298         for (var i = 0; i < options.length; ++i) {
299             if (options[i].value === value) {
300                 userAgentSelectElement.selectedIndex = i;
301                 selectionRestored = true;
302                 break;
303             }
304         }
306         otherUserAgentElement.readOnly = selectionRestored;
307         if (!selectionRestored)
308             userAgentSelectElement.selectedIndex = options.length - 1;
310         if (otherUserAgentElement.value !== value) {
311             otherUserAgentElement.value = value;
312             otherUserAgentElement.title = value;
313         }
314     }
316     function textKeyDown(event)
317     {
318         if (isEnterKey(event))
319             textChanged();
320     }
322     function textDoubleClicked()
323     {
324         userAgentSelectElement.selectedIndex = userAgents.length - 1;
325         userAgentSelected();
326     }
328     function textChanged()
329     {
330         if (userAgentSetting.get() !== otherUserAgentElement.value)
331             userAgentSetting.set(otherUserAgentElement.value);
332     }
334     return { select: userAgentSelectElement, input: otherUserAgentElement };
337 /** @type {!Array.<{title: string, value: string}>} */
338 WebInspector.OverridesUI._userAgents = [
339     {title: "Android 4.0.2 \u2014 Galaxy Nexus", value: "Mozilla/5.0 (Linux; U; Android 4.0.2; en-us; Galaxy Nexus Build/ICL53F) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30"},
340     {title: "Android 2.3 \u2014 Nexus S", value: "Mozilla/5.0 (Linux; U; Android 2.3.6; en-us; Nexus S Build/GRK39F) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1"},
341     {title: "BlackBerry \u2014 BB10", value: "Mozilla/5.0 (BB10; Touch) AppleWebKit/537.1+ (KHTML, like Gecko) Version/10.0.0.1337 Mobile Safari/537.1+"},
342     {title: "BlackBerry \u2014 PlayBook 2.1", value: "Mozilla/5.0 (PlayBook; U; RIM Tablet OS 2.1.0; en-US) AppleWebKit/536.2+ (KHTML, like Gecko) Version/7.2.1.0 Safari/536.2+"},
343     {title: "BlackBerry \u2014 9900", value: "Mozilla/5.0 (BlackBerry; U; BlackBerry 9900; en-US) AppleWebKit/534.11+ (KHTML, like Gecko) Version/7.0.0.187 Mobile Safari/534.11+"},
344     {title: "Chrome 31 \u2014 Mac", value: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36"},
345     {title: "Chrome 31 \u2014 Windows", value: "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.16 Safari/537.36"},
346     {title: "Chrome \u2014 Android Tablet", value: "Mozilla/5.0 (Linux; Android 4.1.2; Nexus 7 Build/JZ054K) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.166 Safari/535.19"},
347     {title: "Chrome \u2014 Android Mobile", value: "Mozilla/5.0 (Linux; Android 4.0.4; Galaxy Nexus Build/IMM76B) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.133 Mobile Safari/535.19"},
348     {title: "Chrome \u2014 iPad", value: "Mozilla/5.0 (iPad; CPU OS 7_0 like Mac OS X) AppleWebKit/537.51.1 (KHTML, like Gecko) CriOS/30.0.1599.12 Mobile/11A465 Safari/8536.25"},
349     {title: "Chrome \u2014 iPhone", value: "Mozilla/5.0 (iPhone; CPU iPhone OS 7_0_2 like Mac OS X) AppleWebKit/537.51.1 (KHTML, like Gecko) CriOS/30.0.1599.12 Mobile/11A501 Safari/8536.25"},
350     {title: "Firefox 14 \u2014 Android Mobile", value: "Mozilla/5.0 (Android; Mobile; rv:14.0) Gecko/14.0 Firefox/14.0"},
351     {title: "Firefox 14 \u2014 Android Tablet", value: "Mozilla/5.0 (Android; Tablet; rv:14.0) Gecko/14.0 Firefox/14.0"},
352     {title: "Firefox 4 \u2014 Mac", value: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:2.0.1) Gecko/20100101 Firefox/4.0.1"},
353     {title: "Firefox 4 \u2014 Windows", value: "Mozilla/5.0 (Windows NT 6.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1"},
354     {title: "Firefox 7 \u2014 Mac", value: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1"},
355     {title: "Firefox 7 \u2014 Windows", value: "Mozilla/5.0 (Windows NT 6.1; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1"},
356     {title: "Googlebot", value: "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"},
357     {title: "Googlebot Smartphone", value: "Mozilla/5.0 (iPhone; CPU iPhone OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A5376e Safari/8536.25 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"},
358     {title: "Internet Explorer 10", value: "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Trident/6.0)"},
359     {title: "Internet Explorer 7", value: "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)"},
360     {title: "Internet Explorer 8", value: "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0)"},
361     {title: "Internet Explorer 9", value: "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)"},
362     {title: "iPad \u2014 iOS 8", value: "Mozilla/5.0 (iPad; CPU OS 8_0 like Mac OS X) AppleWebKit/600.1.3 (KHTML, like Gecko) Version/8.0 Mobile/12A4345d Safari/600.1.4"},
363     {title: "iPad \u2014 iOS 7", value: "Mozilla/5.0 (iPad; CPU OS 7_0_2 like Mac OS X) AppleWebKit/537.51.1 (KHTML, like Gecko) Version/7.0 Mobile/11A501 Safari/9537.53"},
364     {title: "iPad \u2014 iOS 6", value: "Mozilla/5.0 (iPad; CPU OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A5376e Safari/8536.25"},
365     {title: "iPhone \u2014 iOS 8", value: "Mozilla/5.0 (iPhone; CPU iPhone OS 8_0 like Mac OS X) AppleWebKit/600.1.3 (KHTML, like Gecko) Version/8.0 Mobile/12A4345d Safari/600.1.4"},
366     {title: "iPhone \u2014 iOS 7", value: "Mozilla/5.0 (iPhone; CPU iPhone OS 7_0_2 like Mac OS X) AppleWebKit/537.51.1 (KHTML, like Gecko) Version/7.0 Mobile/11A4449d Safari/9537.53"},
367     {title: "iPhone \u2014 iOS 6", value: "Mozilla/5.0 (iPhone; CPU iPhone OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A5376e Safari/8536.25"},
368     {title: "MeeGo \u2014 Nokia N9", value: "Mozilla/5.0 (MeeGo; NokiaN9) AppleWebKit/534.13 (KHTML, like Gecko) NokiaBrowser/8.5.0 Mobile Safari/534.13"},
369     {title: "Opera 18 \u2014 Mac", value: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36 OPR/18.0.1284.68"},
370     {title: "Opera 18 \u2014 Windows", value: "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36 OPR/18.0.1284.68"},
371     {title: "Opera 12 \u2014 Mac", value: "Opera/9.80 (Macintosh; Intel Mac OS X 10.9.1) Presto/2.12.388 Version/12.16"},
372     {title: "Opera 12 \u2014 Windows", value: "Opera/9.80 (Windows NT 6.1) Presto/2.12.388 Version/12.16"},
373     {title: "Silk \u2014 Kindle Fire (Desktop view)", value: "Mozilla/5.0 (Linux; U; en-us; KFTHWI Build/JDQ39) AppleWebKit/535.19 (KHTML, like Gecko) Silk/3.13 Safari/535.19 Silk-Accelerated=true"},
374     {title: "Silk \u2014 Kindle Fire (Mobile view)", value: "Mozilla/5.0 (Linux; U; Android 4.2.2; en-us; KFTHWI Build/JDQ39) AppleWebKit/535.19 (KHTML, like Gecko) Silk/3.13 Mobile Safari/535.19 Silk-Accelerated=true"}