Disable nACL for all architectures
[platform/framework/web/crosswalk.git] / src / xwalk / runtime / extension / screen_orientation_api.js
1 // Copyright (c) 2013 Intel Corporation. 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 var internal = requireNative('internal');
6 internal.setupInternalExtension(extension);
7
8 // These constants must correspond with C++ side:
9 // xwalk/runtime/browser/ui/screen_orientation.h
10 var PORTRAIT_PRIMARY    = 1 << 0;
11 var LANDSCAPE_PRIMARY   = 1 << 1;
12 var PORTRAIT_SECONDARY  = 1 << 2;
13 var LANDSCAPE_SECONDARY = 1 << 3;
14 var PORTRAIT            = PORTRAIT_PRIMARY | PORTRAIT_SECONDARY;
15 var LANDSCAPE           = LANDSCAPE_PRIMARY | LANDSCAPE_SECONDARY;
16 var ANY                 = PORTRAIT | LANDSCAPE;
17
18 // Values that can be set externally.
19 var uaDefault = uaDefault || ANY;
20 var isAndroid = isAndroid || false;
21
22 // Store the real Screen object.
23 var realScreen = window.screen;
24
25 function cloneProperties(target, source) {
26   var props = Object.getOwnPropertyNames(source);
27   props.forEach(function(item) {
28     target[item] = source[item];
29   });
30 }
31
32 // Create replacement Screen and make it an EventTarget.
33 function Screen() { cloneProperties(this, realScreen); };
34 Screen.prototype = Object.create(EventTarget.prototype);
35 Screen.prototype.constructor = Screen;
36
37 // Replace it.
38 window.screen = new Screen();
39
40 function postMessage(command, value) {
41   // Currently, internal.postMessage can't work on Android.
42   // https://crosswalk-project.org/jira/browse/XWALK-855
43   if (isAndroid) {
44     var message = JSON.stringify({
45       cmd: command,
46       value: value.toString()
47     });
48     extension.postMessage(message);
49   } else {
50     internal.postMessage(command, value, null);
51   }
52 }
53
54 window.screen.lockOrientation = function(orientations) {
55   if (!Array.isArray(orientations)) {
56     if (typeof orientations != 'string')
57       return false;
58     orientations = [orientations];
59   }
60
61   var value = 0;
62   for (var i = 0; i < orientations.length; ++i) {
63     switch (orientations[i]) {
64       case 'portrait-primary':
65         value |= PORTRAIT_PRIMARY;
66         break;
67       case 'portrait-secondary':
68         value |= PORTRAIT_SECONDARY;
69         break;
70       case 'landscape-primary':
71         value |= LANDSCAPE_PRIMARY;
72         break;
73       case 'landscape-secondary':
74         value |= LANDSCAPE_SECONDARY;
75         break;
76       case 'portrait':
77         value |= PORTRAIT;
78         break;
79       case 'landscape':
80         value |= LANDSCAPE;
81         break;
82       default:
83         console.error('Invalid screen orientation');
84         return false;
85     }
86     // If the orientations aren't all part of the default allowed
87     // orientations, the steps must stop here and return false.
88     if ((uaDefault & value) != value)
89       return false;
90   }
91   postMessage('lock', [value]);
92   return true;
93 };
94
95 window.screen.unlockOrientation = function() {
96   postMessage('lock', [uaDefault]);
97 };
98
99 // Create a HTMLUnknownElement and do not attach it to the DOM.
100 var dispatcher = document.createElement('xwalk-EventDispatcher');
101
102 // Implement EventTarget interface on object.
103 Object.defineProperty(window.screen, 'addEventListener', {
104   value: function(type, callback, capture) {
105     dispatcher.addEventListener(type, callback, capture);
106   }
107 });
108
109 Object.defineProperty(window.screen, 'removeEventListener', {
110   value: function(type, callback, capture) {
111     dispatcher.removeEventListener(type, callback, capture);
112   }
113 });
114
115 Object.defineProperty(window.screen, 'dispatchEvent', {
116   value: function(e) {
117     dispatcher.dispatchEvent(e);
118   }
119 });
120
121 var orientationchangeCallback = null;
122 var orientationchangeCallbackWrapper = null;
123
124 Object.defineProperty(window.screen, 'onorientationchange', {
125   configurable: false,
126   enumerable: true,
127   get: function() { return orientationchangeCallback; },
128   set: function(callback) {
129     // We must add the on* event as an event listener so that
130     // it is called at the right point between potential
131     // event listeners, but it cannot be the exact method
132     // as that would allow removeEventListener to remove it.
133
134     // Remove existing (wrapped) listener.
135     window.screen.removeEventListener('orientationchange',
136         orientationchangeCallbackWrapper);
137
138     // If valid, store and add a wrapped version as listener.
139     if (callback instanceof Function) {
140       orientationchangeCallback = callback;
141       orientationchangeCallbackWrapper = function() { callback(); };
142       window.screen.addEventListener('orientationchange',
143           orientationchangeCallbackWrapper);
144     }
145     // If not valid, reset to null.
146     else {
147       orientationchangeCallback = null;
148       orientationchangeCallbackWrapper = null;
149     }
150   }
151 });
152
153 function handleOrientationChange(newOrientation) {
154   switch (newOrientation) {
155     case PORTRAIT_PRIMARY:
156       orientationValue = 'portrait-primary';
157       break;
158     case PORTRAIT_SECONDARY:
159       orientationValue = 'portrait-secondary';
160       break;
161     case LANDSCAPE_PRIMARY:
162       orientationValue = 'landscape-primary';
163       break;
164     case LANDSCAPE_SECONDARY:
165       orientationValue = 'landscape-secondary';
166       break;
167     default:
168       console.error('Received unknown value for current orientation');
169       return;
170   }
171
172   // The first time the listener is called it is to set the current
173   // orientation, so do not dispatch the orientationchange in that case.
174   if (handleOrientationChange.shouldDispatchEvent) {
175     var event = new Event('orientationchange');
176     dispatcher.dispatchEvent(event);
177   }
178
179   handleOrientationChange.shouldDispatchEvent = true;
180 }
181
182 var orientationValue;
183
184 Object.defineProperty(window.screen, 'orientation', {
185   configurable: false,
186   enumerable: true,
187   get: function() {
188     if (typeof orientationValue == 'undefined') {
189       var msg = JSON.stringify({
190         cmd: 'GetScreenOrientation'
191       });
192       var newOrientation = extension.internal.sendSyncMessage(msg);
193       handleOrientationChange(newOrientation);
194     }
195     return orientationValue;
196   }
197 });
198
199 // FIXME: Extend message listener to handle screen changes.
200 extension.setMessageListener(handleOrientationChange);