Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / browser / resources / chromeos / login / oobe-screen.js
blobb79784d145b7d88f6ab35873cf221f894bd6b3c6
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 cr.define('login', function() {
6   /** @const */ var CALLBACK_USER_ACTED = 'userActed';
8   var OobeScreenBehavior = {
9     properties: {
10       /**
11        * Internal storage of |this.context|. Short name has been choosen for
12        * reason: such name doesn't take much space in HTML data bindings, which
13        * are used very often.
14        * C binded to the native part of the context, that means that all the
15        * changes in the native part appear in C automatically. Reverse is not
16        * true, you should use:
17        *    this.context.set(...);
18        *    this.context.commitContextChanges();
19        * to send updates to the native part.
20        * TODO(dzhioev): make binding two-way.
21        */
22       C: Object,
24       name: String
25     },
27     /**
28      * The login.Screen which is hosting |this|.
29      */
30     screen_: null,
32     /**
33      * Dictionary of context observers that are methods of |this| bound to
34      * |this|.
35      */
36     contextObservers_: null,
38     /**
39      * login.ScreenContext used for sharing data with native backend.
40      */
41     context: null,
43     /**
44      * Called when the screen is being registered.
45      */
46     initialize: function() {},
48     ready: function() {
49       if (this.decorate_) {
50         this.initialize();
51       } else {
52         this.ready_ = true;
53       }
54     },
56     userActed: function(e) {
57       this.send(CALLBACK_USER_ACTED,
58                 e.detail.sourceEvent.target.getAttribute('action'));
59     },
61     i18n: function(args) {
62       if (!(args instanceof Array))
63         args = [args];
64       args[0] = 'login_' + this.name + '_' + args[0];
65       return loadTimeData.getStringF.apply(loadTimeData, args);
66     },
68     /**
69      * Called by login.Screen when the screen is beeing registered.
70      */
71     decorate: function(screen) {
72       this.screen_ = screen;
73       this.context = screen.screenContext_;
74       this.C = this.context.storage_;
75       this.contextObservers_ = {};
76       var self = this;
77       if (this.ready_) {
78         this.initialize();
79       } else {
80         this.decorate_ = true;
81       }
82     },
84     /**
85      * Should be called for every context field which is used in Polymer
86      * declarative data bindings (e.g. {{C.fieldName}}).
87      */
88     registerBoundContextField: function(fieldName) {
89       this.addContextObserver(fieldName, this.onContextFieldChanged_);
90     },
92     onContextFieldChanged_: function(_, _, fieldName) {
93       this.notifyPath('C.' + fieldName, this.C[fieldName]);
94     },
96     /**
97      * @final
98      */
99     send: function() {
100       return this.sendImpl_.apply(this, arguments);
101     },
103     /**
104      * @final
105      */
106     addContextObserver: function() {
107       return this.addContextObserverImpl_.apply(this, arguments);
108     },
110     /**
111      * @final
112      */
113     removeContextObserver: function() {
114       return this.removeContextObserverImpl_.apply(this, arguments);
115     },
117     /**
118      * @final
119      */
120     commitContextChanges: function() {
121       return this.commitContextChangesImpl_.apply(this, arguments);
122     },
124     /**
125      * @override
126      * @final
127      */
128     querySelector: function() {
129       return this.querySelectorImpl_.apply(this, arguments);
130     },
132     /**
133      * @override
134      * @final
135      */
136     querySelectorAll: function() {
137       return this.querySelectorAllImpl_.apply(this, arguments);
138     },
140     /**
141      * See login.Screen.send.
142      * @private
143      */
144     sendImpl_: function() {
145       return this.screen_.send.apply(this.screen_, arguments);
146     },
148     /**
149      * Starts observation of property with |key| of the context attached to
150      * current screen. This method differs from "login.ScreenContext" in that
151      * it automatically detects if observer is method of |this| and make
152      * all needed actions to make it work correctly. So it's no need for client
153      * to bind methods to |this| and keep resulting callback for
154      * |removeObserver| call:
155      *
156      *   this.addContextObserver('key', this.onKeyChanged_);
157      *   ...
158      *   this.removeContextObserver('key', this.onKeyChanged_);
159      * @private
160      */
161     addContextObserverImpl_: function(key, observer) {
162       var realObserver = observer;
163       var propertyName = this.getPropertyNameOf_(observer);
164       if (propertyName) {
165         if (!this.contextObservers_.hasOwnProperty(propertyName))
166           this.contextObservers_[propertyName] = observer.bind(this);
167         realObserver = this.contextObservers_[propertyName];
168       }
169       this.context.addObserver(key, realObserver);
170     },
172     /**
173      * Removes |observer| from the list of context observers. Supports not only
174      * regular functions but also screen methods (see comment to
175      * |addContextObserver|).
176      * @private
177      */
178     removeContextObserverImpl_: function(observer) {
179       var realObserver = observer;
180       var propertyName = this.getPropertyNameOf_(observer);
181       if (propertyName) {
182         if (!this.contextObservers_.hasOwnProperty(propertyName))
183           return;
184         realObserver = this.contextObservers_[propertyName];
185         delete this.contextObservers_[propertyName];
186       }
187       this.context.removeObserver(realObserver);
188     },
190     /**
191      * See login.Screen.commitContextChanges.
192      * @private
193      */
194     commitContextChangesImpl_: function() {
195       return this.screen_.commitContextChanges.apply(this.screen_, arguments);
196     },
198     /**
199      * Calls |querySelector| method of the shadow dom and returns the result.
200      * @private
201      */
202     querySelectorImpl_: function(selector) {
203       return this.shadowRoot.querySelector(selector);
204     },
207     /**
208      * Calls standart |querySelectorAll| method of the shadow dom and returns
209      * the result converted to Array.
210      * @private
211      */
212     querySelectorAllImpl_: function(selector) {
213       var list = this.shadowRoot.querySelectorAll(selector);
214       return Array.prototype.slice.call(list);
215     },
217     /**
218      * If |value| is the value of some property of |this| returns property's
219      * name. Otherwise returns empty string.
220      * @private
221      */
222     getPropertyNameOf_: function(value) {
223       for (var key in this)
224         if (this[key] === value)
225           return key;
226       return '';
227     }
228   };
230   return {
231     OobeScreenBehavior: OobeScreenBehavior
232   };