Skip to content

Commit 0165ae1

Browse files
lexsMartin Konicek
authored andcommitted
Support cookies on Android
Summary: This adds a persistent cookie store that shares cookies with WebView. Add a `ForwardingCookieHandler` to OkHttp that uses the underlying Android webkit `CookieManager`. Use a `LazyCookieHandler` to defer initialization of `CookieManager` as this will in turn trigger initialization of the Chromium stack in KitKat+ which takes some time. This was we will incur this cost on a background network thread instead of during startup. Also add a `clearCookies()` method to the network module. Add a cookies example to the XHR example. This example should also work for iOS (except for the clear cookies part). They are for now just scoped to Android. Closes #2792. public Reviewed By: andreicoman11 Differential Revision: D2615550 fb-gh-sync-id: ff726a35f0fc3c7124d2f755448fe24c9d1caf21 Conflicts: ReactAndroid/src/main/java/com/facebook/react/modules/network/NetworkingModule.java
1 parent dc971a3 commit 0165ae1

7 files changed

Lines changed: 420 additions & 15 deletions

File tree

Examples/UIExplorer/XHRExample.android.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ var {
2626
} = React;
2727

2828
var XHRExampleHeaders = require('./XHRExampleHeaders');
29+
var XHRExampleCookies = require('./XHRExampleCookies');
30+
2931

3032
// TODO t7093728 This is a simlified XHRExample.ios.js.
3133
// Once we have Camera roll, Toast, Intent (for opening URLs)
@@ -280,6 +282,11 @@ exports.examples = [{
280282
render() {
281283
return <XHRExampleHeaders/>;
282284
}
285+
}, {
286+
title: 'Cookies',
287+
render() {
288+
return <XHRExampleCookies/>;
289+
}
283290
}];
284291

285292
var styles = StyleSheet.create({
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
/**
2+
* The examples provided by Facebook are for non-commercial testing and
3+
* evaluation purposes only.
4+
*
5+
* Facebook reserves all rights not expressly granted.
6+
*
7+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
8+
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
9+
* FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL
10+
* FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
11+
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
12+
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
13+
*
14+
* @flow
15+
*/
16+
'use strict';
17+
18+
var React = require('react-native');
19+
var {
20+
StyleSheet,
21+
Text,
22+
TouchableHighlight,
23+
View,
24+
} = React;
25+
26+
var RCTNetworking = require('RCTNetworking');
27+
28+
class XHRExampleCookies extends React.Component {
29+
constructor(props: any) {
30+
super(props);
31+
this.cancelled = false;
32+
this.state = {
33+
status: '',
34+
a: 1,
35+
b: 2,
36+
};
37+
}
38+
39+
setCookie(domain: string) {
40+
var {a, b} = this.state;
41+
var url = `https://${domain}/cookies/set?a=${a}&b=${b}`;
42+
fetch(url).then((response) => {
43+
this.setStatus(`Cookies a=${a}, b=${b} set`);
44+
});
45+
46+
this.setState({
47+
status: 'Setting cookies...',
48+
a: a + 1,
49+
b: b + 2,
50+
});
51+
}
52+
53+
getCookies(domain: string) {
54+
fetch(`https://${domain}/cookies`).then((response) => {
55+
return response.json();
56+
}).then((data) => {
57+
this.setStatus(`Got cookies ${JSON.stringify(data.cookies)} from server`);
58+
});
59+
60+
this.setStatus('Getting cookies...');
61+
}
62+
63+
clearCookies() {
64+
RCTNetworking.clearCookies((cleared) => {
65+
this.setStatus('Cookies cleared, had cookies=' + cleared);
66+
});
67+
}
68+
69+
setStatus(status: string) {
70+
this.setState({status});
71+
}
72+
73+
render() {
74+
return (
75+
<View>
76+
<TouchableHighlight
77+
style={styles.wrapper}
78+
onPress={this.setCookie.bind(this, 'httpbin.org')}>
79+
<View style={styles.button}>
80+
<Text>Set cookie</Text>
81+
</View>
82+
</TouchableHighlight>
83+
<TouchableHighlight
84+
style={styles.wrapper}
85+
onPress={this.setCookie.bind(this, 'eu.httpbin.org')}>
86+
<View style={styles.button}>
87+
<Text>Set cookie (EU)</Text>
88+
</View>
89+
</TouchableHighlight>
90+
<TouchableHighlight
91+
style={styles.wrapper}
92+
onPress={this.getCookies.bind(this, 'httpbin.org')}>
93+
<View style={styles.button}>
94+
<Text>Get cookies</Text>
95+
</View>
96+
</TouchableHighlight>
97+
<TouchableHighlight
98+
style={styles.wrapper}
99+
onPress={this.getCookies.bind(this, 'eu.httpbin.org')}>
100+
<View style={styles.button}>
101+
<Text>Get cookies (EU)</Text>
102+
</View>
103+
</TouchableHighlight>
104+
<TouchableHighlight
105+
style={styles.wrapper}
106+
onPress={this.clearCookies.bind(this)}>
107+
<View style={styles.button}>
108+
<Text>Clear cookies</Text>
109+
</View>
110+
</TouchableHighlight>
111+
<Text>{this.state.status}</Text>
112+
</View>
113+
);
114+
}
115+
}
116+
117+
var styles = StyleSheet.create({
118+
wrapper: {
119+
borderRadius: 5,
120+
marginBottom: 5,
121+
},
122+
button: {
123+
backgroundColor: '#eeeeee',
124+
padding: 8,
125+
},
126+
});
127+
128+
module.exports = XHRExampleCookies;

Libraries/Network/RCTNetworking.android.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@ class RCTNetworking {
4040
static abortRequest(requestId) {
4141
RCTNetworkingNative.abortRequest(requestId);
4242
}
43+
44+
static clearCookies(callback) {
45+
RCTNetworkingNative.clearCookies(callback);
46+
}
4347
}
4448

4549
module.exports = RCTNetworking;

ReactAndroid/src/main/java/com/facebook/react/modules/fresco/FrescoModule.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,8 @@ public void loadLibrary(String libraryName) {
8080
}
8181

8282
Context context = this.getReactApplicationContext().getApplicationContext();
83-
OkHttpClient okHttpClient = OkHttpClientProvider.getOkHttpClient();
83+
OkHttpClient okHttpClient =
84+
OkHttpClientProvider.getCookieAwareOkHttpClient(getReactApplicationContext());
8485
ImagePipelineConfig.Builder builder =
8586
OkHttpImagePipelineConfigFactory.newBuilder(context, okHttpClient);
8687

0 commit comments

Comments
 (0)