Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
seleniumhq
GitHub Repository: seleniumhq/selenium
Path: blob/trunk/third_party/closure/goog/datasource/jsxmlhttpdatasource.js
2868 views
1
// Copyright 2006 The Closure Library Authors. All Rights Reserved.
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
// http://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS-IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
15
/**
16
* @fileoverview
17
* DataSource implementation that uses XMLHttpRequest as transport, with
18
* response as valid JSON.
19
*
20
* Response can have unexecutable starting/ending text to prevent inclusion
21
* using <script src="...">
22
*
23
*/
24
25
26
goog.provide('goog.ds.JsXmlHttpDataSource');
27
28
goog.require('goog.Uri');
29
goog.require('goog.ds.DataManager');
30
goog.require('goog.ds.FastDataNode');
31
goog.require('goog.ds.LoadState');
32
goog.require('goog.ds.logger');
33
goog.require('goog.events');
34
goog.require('goog.json');
35
goog.require('goog.log');
36
goog.require('goog.net.EventType');
37
goog.require('goog.net.XhrIo');
38
39
40
41
/**
42
* Similar to JsonDataSource, with using XMLHttpRequest for transport
43
* Currently requires the result be a valid JSON.
44
*
45
* @param {(string|goog.Uri)} uri URI for the request.
46
* @param {string} name Name of the datasource.
47
* @param {string=} opt_startText Text to expect/strip before JS response.
48
* @param {string=} opt_endText Text to expect/strip after JS response.
49
* @param {boolean=} opt_usePost If true, use POST. Defaults to false (GET).
50
*
51
* @extends {goog.ds.FastDataNode}
52
* @constructor
53
* @final
54
*/
55
goog.ds.JsXmlHttpDataSource = function(
56
uri, name, opt_startText, opt_endText, opt_usePost) {
57
goog.ds.FastDataNode.call(this, {}, name, null);
58
if (uri) {
59
this.uri_ = new goog.Uri(uri);
60
this.xhr_ = new goog.net.XhrIo();
61
this.usePost_ = !!opt_usePost;
62
63
goog.events.listen(
64
this.xhr_, goog.net.EventType.COMPLETE, this.completed_, false, this);
65
} else {
66
this.uri_ = null;
67
}
68
this.startText_ = opt_startText;
69
this.endText_ = opt_endText;
70
};
71
goog.inherits(goog.ds.JsXmlHttpDataSource, goog.ds.FastDataNode);
72
73
74
/**
75
* Delimiter for start of JSON data in response.
76
* null = starts at first character of response
77
* @type {string|undefined}
78
* @private
79
*/
80
goog.ds.JsXmlHttpDataSource.prototype.startText_;
81
82
83
/**
84
* Delimiter for end of JSON data in response.
85
* null = ends at last character of response
86
* @type {string|undefined}
87
* @private
88
*/
89
goog.ds.JsXmlHttpDataSource.prototype.endText_;
90
91
92
/**
93
* Gets the state of the backing data for this node
94
* @return {goog.ds.LoadState} The state.
95
* @override
96
*/
97
goog.ds.JsXmlHttpDataSource.prototype.getLoadState = function() {
98
return this.loadState_;
99
};
100
101
102
/**
103
* Sets the request data. This can be used if it is required to
104
* send a specific body rather than build the body from the query
105
* parameters. Only used in POST requests.
106
* @param {string} data The data to send in the request body.
107
*/
108
goog.ds.JsXmlHttpDataSource.prototype.setQueryData = function(data) {
109
this.queryData_ = data;
110
};
111
112
113
/**
114
* Load or reload the backing data for this node.
115
* Fires the JsonDataSource
116
* @override
117
*/
118
goog.ds.JsXmlHttpDataSource.prototype.load = function() {
119
goog.log.info(
120
goog.ds.logger, 'Sending JS request for DataSource ' +
121
this.getDataName() + ' to ' + this.uri_);
122
123
if (this.uri_) {
124
if (this.usePost_) {
125
var queryData;
126
if (!this.queryData_) {
127
queryData = this.uri_.getQueryData().toString();
128
} else {
129
queryData = this.queryData_;
130
}
131
132
var uriNoQuery = this.uri_.clone();
133
uriNoQuery.setQueryData(null);
134
this.xhr_.send(String(uriNoQuery), 'POST', queryData);
135
} else {
136
this.xhr_.send(String(this.uri_));
137
}
138
} else {
139
this.loadState_ = goog.ds.LoadState.NOT_LOADED;
140
}
141
};
142
143
144
/**
145
* Called on successful request.
146
* @private
147
*/
148
goog.ds.JsXmlHttpDataSource.prototype.success_ = function() {
149
goog.ds.DataManager.getInstance().fireDataChange(this.getDataName());
150
};
151
152
153
/**
154
* Completed callback. Loads data if successful, otherwise sets
155
* state to FAILED
156
* @param {goog.events.Event} e Event object, Xhr is target.
157
* @private
158
*/
159
goog.ds.JsXmlHttpDataSource.prototype.completed_ = function(e) {
160
if (this.xhr_.isSuccess()) {
161
goog.log.info(
162
goog.ds.logger, 'Got data for DataSource ' + this.getDataName());
163
var text = this.xhr_.getResponseText();
164
165
// Look for start and end token and trim text
166
if (this.startText_) {
167
var startpos = text.indexOf(this.startText_);
168
text = text.substring(startpos + this.startText_.length);
169
}
170
if (this.endText_) {
171
var endpos = text.lastIndexOf(this.endText_);
172
text = text.substring(0, endpos);
173
}
174
175
// Parse result.
176
177
try {
178
var jsonObj = goog.json.parse(text);
179
this.extendWith(jsonObj);
180
this.loadState_ = goog.ds.LoadState.LOADED;
181
} catch (ex) {
182
// Invalid JSON.
183
this.loadState_ = goog.ds.LoadState.FAILED;
184
goog.log.error(goog.ds.logger, 'Failed to parse data: ' + ex.message);
185
}
186
187
// Call on a timer to avoid threading issues on IE.
188
goog.global.setTimeout(goog.bind(this.success_, this), 0);
189
} else {
190
goog.log.info(
191
goog.ds.logger,
192
'Data retrieve failed for DataSource ' + this.getDataName());
193
this.loadState_ = goog.ds.LoadState.FAILED;
194
}
195
};
196
197