Skip to content
This repository has been archived by the owner on Apr 12, 2024. It is now read-only.

ng-cookies #10530

Closed
wants to merge 12 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion angularFiles.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ var angularFiles = {
'src/ng/timeout.js',
'src/ng/urlUtils.js',
'src/ng/window.js',
'src/ng/cookieReader.js',

'src/ng/filter.js',
'src/ng/filter/filter.js',
Expand Down Expand Up @@ -89,7 +90,9 @@ var angularFiles = {
'src/ngAnimate/animate.js'
],
'ngCookies': [
'src/ngCookies/cookies.js'
'src/ngCookies/cookies.js',
'src/ngCookies/cookieStore.js',
'src/ngCookies/cookieWriter.js'
],
'ngMessages': [
'src/ngMessages/messages.js'
Expand Down
6 changes: 4 additions & 2 deletions src/AngularPublic.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,8 @@
$$RAFProvider,
$$AsyncCallbackProvider,
$WindowProvider,
$$jqLiteProvider
$$jqLiteProvider,
$$CookieReaderProvider
*/


Expand Down Expand Up @@ -238,7 +239,8 @@ function publishExternalAPI(angular) {
$window: $WindowProvider,
$$rAF: $$RAFProvider,
$$asyncCallback: $$AsyncCallbackProvider,
$$jqLite: $$jqLiteProvider
$$jqLite: $$jqLiteProvider,
$$cookieReader: $$CookieReaderProvider
});
}
]);
Expand Down
125 changes: 0 additions & 125 deletions src/ng/browser.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,56 +73,13 @@ function Browser(window, document, $log, $sniffer) {
* @param {function()} callback Function that will be called when no outstanding request
*/
self.notifyWhenNoOutstandingRequests = function(callback) {
// force browser to execute all pollFns - this is needed so that cookies and other pollers fire
// at some deterministic time in respect to the test runner's actions. Leaving things up to the
// regular poller would result in flaky tests.
forEach(pollFns, function(pollFn) { pollFn(); });

if (outstandingRequestCount === 0) {
callback();
} else {
outstandingRequestCallbacks.push(callback);
}
};

//////////////////////////////////////////////////////////////
// Poll Watcher API
//////////////////////////////////////////////////////////////
var pollFns = [],
pollTimeout;

/**
* @name $browser#addPollFn
*
* @param {function()} fn Poll function to add
*
* @description
* Adds a function to the list of functions that poller periodically executes,
* and starts polling if not started yet.
*
* @returns {function()} the added function
*/
self.addPollFn = function(fn) {
if (isUndefined(pollTimeout)) startPoller(100, setTimeout);
pollFns.push(fn);
return fn;
};

/**
* @param {number} interval How often should browser call poll functions (ms)
* @param {function()} setTimeout Reference to a real or fake `setTimeout` function.
*
* @description
* Configures the poller to run in the specified intervals, using the specified
* setTimeout fn and kicks it off.
*/
function startPoller(interval, setTimeout) {
(function check() {
forEach(pollFns, function(pollFn) { pollFn(); });
pollTimeout = setTimeout(check, interval);
})();
}

//////////////////////////////////////////////////////////////
// URL API
//////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -324,88 +281,6 @@ function Browser(window, document, $log, $sniffer) {
return href ? href.replace(/^(https?\:)?\/\/[^\/]*/, '') : '';
};

//////////////////////////////////////////////////////////////
// Cookies API
//////////////////////////////////////////////////////////////
var lastCookies = {};
var lastCookieString = '';
var cookiePath = self.baseHref();

function safeDecodeURIComponent(str) {
try {
return decodeURIComponent(str);
} catch (e) {
return str;
}
}

/**
* @name $browser#cookies
*
* @param {string=} name Cookie name
* @param {string=} value Cookie value
*
* @description
* The cookies method provides a 'private' low level access to browser cookies.
* It is not meant to be used directly, use the $cookie service instead.
*
* The return values vary depending on the arguments that the method was called with as follows:
*
* - cookies() -> hash of all cookies, this is NOT a copy of the internal state, so do not modify
* it
* - cookies(name, value) -> set name to value, if value is undefined delete the cookie
* - cookies(name) -> the same as (name, undefined) == DELETES (no one calls it right now that
* way)
*
* @returns {Object} Hash of all cookies (if called without any parameter)
*/
self.cookies = function(name, value) {
var cookieLength, cookieArray, cookie, i, index;

if (name) {
if (value === undefined) {
rawDocument.cookie = encodeURIComponent(name) + "=;path=" + cookiePath +
";expires=Thu, 01 Jan 1970 00:00:00 GMT";
} else {
if (isString(value)) {
cookieLength = (rawDocument.cookie = encodeURIComponent(name) + '=' + encodeURIComponent(value) +
';path=' + cookiePath).length + 1;

// per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum:
// - 300 cookies
// - 20 cookies per unique domain
// - 4096 bytes per cookie
if (cookieLength > 4096) {
$log.warn("Cookie '" + name +
"' possibly not set or overflowed because it was too large (" +
cookieLength + " > 4096 bytes)!");
}
}
}
} else {
if (rawDocument.cookie !== lastCookieString) {
lastCookieString = rawDocument.cookie;
cookieArray = lastCookieString.split("; ");
lastCookies = {};

for (i = 0; i < cookieArray.length; i++) {
cookie = cookieArray[i];
index = cookie.indexOf('=');
if (index > 0) { //ignore nameless cookies
name = safeDecodeURIComponent(cookie.substring(0, index));
// the first value that is seen for a cookie is the most
// specific one. values for the same cookie name that
// follow are for less specific paths.
if (lastCookies[name] === undefined) {
lastCookies[name] = safeDecodeURIComponent(cookie.substring(index + 1));
}
}
}
}
return lastCookies;
}
};


/**
* @name $browser#defer
Expand Down
55 changes: 55 additions & 0 deletions src/ng/cookieReader.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
'use strict';

/**
* @name $$cookieReader
* @requires $document
*
* @description
* This is a private service for reading cookies used by $http and ngCookies
*
* @return {Object} a key/value map of the current cookies
*/
function $$CookieReader($document) {
var rawDocument = $document[0];
var lastCookies = {};
var lastCookieString = '';

function safeDecodeURIComponent(str) {
try {
return decodeURIComponent(str);
} catch (e) {
return str;
}
}

return function() {
var cookieArray, cookie, i, index, name;

if (rawDocument.cookie !== lastCookieString) {
lastCookieString = rawDocument.cookie;
cookieArray = lastCookieString.split('; ');
lastCookies = {};

for (i = 0; i < cookieArray.length; i++) {
cookie = cookieArray[i];
index = cookie.indexOf('=');
if (index > 0) { //ignore nameless cookies
name = safeDecodeURIComponent(cookie.substring(0, index));
// the first value that is seen for a cookie is the most
// specific one. values for the same cookie name that
// follow are for less specific paths.
if (lastCookies[name] === undefined) {
lastCookies[name] = safeDecodeURIComponent(cookie.substring(index + 1));
}
}
}
}
return lastCookies;
};
}

$$CookieReader.$inject = ['$document'];

function $$CookieReaderProvider() {
this.$get = $$CookieReader;
}
6 changes: 3 additions & 3 deletions src/ng/http.js
Original file line number Diff line number Diff line change
Expand Up @@ -220,8 +220,8 @@ function $HttpProvider() {
**/
var interceptorFactories = this.interceptors = [];

this.$get = ['$httpBackend', '$browser', '$cacheFactory', '$rootScope', '$q', '$injector',
function($httpBackend, $browser, $cacheFactory, $rootScope, $q, $injector) {
this.$get = ['$httpBackend', '$$cookieReader', '$cacheFactory', '$rootScope', '$q', '$injector',
function($httpBackend, $$cookieReader, $cacheFactory, $rootScope, $q, $injector) {

var defaultCache = $cacheFactory('$http');

Expand Down Expand Up @@ -1066,7 +1066,7 @@ function $HttpProvider() {
// send the request to the backend
if (isUndefined(cachedResp)) {
var xsrfValue = urlIsSameOrigin(config.url)
? $browser.cookies()[config.xsrfCookieName || defaults.xsrfCookieName]
? $$cookieReader()[config.xsrfCookieName || defaults.xsrfCookieName]
: undefined;
if (xsrfValue) {
reqHeaders[(config.xsrfHeaderName || defaults.xsrfHeaderName)] = xsrfValue;
Expand Down
80 changes: 80 additions & 0 deletions src/ngCookies/cookieStore.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
'use strict';

angular.module('ngCookies').
/**
* @ngdoc service
* @name $cookieStore
* @requires $cookies
*
* @description
* Provides a key-value (string-object) storage, that is backed by session cookies.
* Objects put or retrieved from this storage are automatically serialized or
* deserialized by angular's toJson/fromJson.
*
* Requires the {@link ngCookies `ngCookies`} module to be installed.
*
* <div class="alert alert-error">
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you want to add @deprecated annotation to this service

* **Note:** The $cookieStore service is deprecated.
* Please use the {@link ngCookies.$cookies `$cookies`} service instead.
* </div>
*
* @example
*
* ```js
* angular.module('cookieStoreExample', ['ngCookies'])
* .controller('ExampleController', ['$cookieStore', function($cookieStore) {
* // Put cookie
* $cookieStore.put('myFavorite','oatmeal');
* // Get cookie
* var favoriteCookie = $cookieStore.get('myFavorite');
* // Removing a cookie
* $cookieStore.remove('myFavorite');
* }]);
* ```
*/
factory('$cookieStore', ['$cookies', function($cookies) {

return {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if we should write a deprecation message to the console when this service is instantiated?

/**
* @ngdoc method
* @name $cookieStore#get
*
* @description
* Returns the value of given cookie key
*
* @param {string} key Id to use for lookup.
* @returns {Object} Deserialized cookie value.
*/
get: function(key) {
return $cookies.getObject(key);
},

/**
* @ngdoc method
* @name $cookieStore#put
*
* @description
* Sets a value for given cookie key
*
* @param {string} key Id for the `value`.
* @param {Object} value Value to be stored.
*/
put: function(key, value) {
return $cookies.putObject(key, value);
},

/**
* @ngdoc method
* @name $cookieStore#remove
*
* @description
* Remove given cookie
*
* @param {string} key Id of the key-value pair to delete.
*/
remove: function(key) {
return $cookies.remove(key);
}
};

}]);
Loading