github.com/psiphon-labs/psiphon-tunnel-core@v2.0.28+incompatible/MobileLibrary/Android/SampleApps/TunneledWebView/README.md (about) 1 TunneledWebView README 2 ================================================================================ 3 4 Overview 5 -------------------------------------------------------------------------------- 6 7 TunneledWebView is a sample app that demonstrates embedding the Psiphon Library in 8 an Android app. TunneledWebView proxies a WebView through the Psiphon tunnel. 9 10 Caveats 11 -------------------------------------------------------------------------------- 12 13 ### i18n API Leaks Timezone 14 15 The Internationalization API (i18n) provides websites, though a JavaScript API, with access to the timezone used by 16 the user's browser (in this case WebView). This does not reveal the precise location of the user, but can be accurate 17 enough to identify the city in which the user is located. 18 19 The i18n API cannot be disabled without disabling JavaScript. 20 21 ### Untunneled WebRTC 22 23 WebRTC requests do not use the configured proxy settings of a WebView. JavaScript must be disabled in a WebView to 24 effectively disable WebRTC. If not disabled, WebRTC will leak the untunneled client IP address and the WebRTC connection 25 may be performed entirely outside of the tunnel. 26 27 One solution would be to use a WebRTC library which allows setting a proxy; or use 28 [Mozilla's GeckoView](https://wiki.mozilla.org/Mobile/GeckoView), which is a WebView alternative which allows disabling 29 WebRTC. 30 31 Integration 32 -------------------------------------------------------------------------------- 33 34 Uses the [Psiphon Android Library](../../../Android/README.md). 35 36 Integration is illustrated in the main activity source file in the sample app. Here are the key parts. 37 38 ```Java 39 40 /* 41 * Copyright (c) 2016, Psiphon Inc. 42 * All rights reserved. 43 */ 44 45 package ca.psiphon.tunneledwebview; 46 47 // ... 48 49 import ca.psiphon.PsiphonTunnel; 50 51 //---------------------------------------------------------------------------------------------- 52 // TunneledWebView 53 // 54 // This sample app demonstrates tunneling a WebView through the 55 // Psiphon Library. This app's main activity shows a log of 56 // events and a WebView that is loaded once Psiphon is connected. 57 // 58 // The flow is as follows: 59 // 60 // - The Psiphon tunnel is started in onResume(). PsiphonTunnel.startTunneling() 61 // is an asynchronous call that returns immediately. 62 // 63 // - Once Psiphon has selected a local HTTP proxy listening port, the 64 // onListeningHttpProxyPort() callback is called. This app records the 65 // port to use for tunneling traffic. 66 // 67 // - Once Psiphon has established a tunnel, the onConnected() callback 68 // is called. This app now loads the WebView, after setting its proxy 69 // to point to Psiphon's local HTTP proxy. 70 // 71 // To adapt this sample into your own app: 72 // 73 // - Embed a Psiphon config file in app/src/main/res/raw/psiphon_config. 74 // 75 // - Add the Psiphon Library AAR module as a dependency (see this app's 76 // project settings; to build this sample project, you need to drop 77 // ca.psiphon.aar into app/libs). 78 //---------------------------------------------------------------------------------------------- 79 80 public class MainActivity extends ActionBarActivity 81 implements PsiphonTunnel.HostService { 82 83 // ... 84 85 @Override 86 protected void onCreate(Bundle savedInstanceState) { 87 88 // ... 89 90 mPsiphonTunnel = PsiphonTunnel.newPsiphonTunnel(this); 91 } 92 93 @Override 94 protected void onResume() { 95 super.onResume(); 96 97 // NOTE: for demonstration purposes, this sample app 98 // restarts Psiphon in onPause/onResume. Since it may take some 99 // time to connect, it's generally recommended to keep 100 // Psiphon running, so start/stop in onCreate/onDestroy or 101 // even consider running a background Service. 102 103 try { 104 mPsiphonTunnel.startTunneling(""); 105 } catch (PsiphonTunnel.Exception e) { 106 logMessage("failed to start Psiphon"); 107 } 108 } 109 110 @Override 111 protected void onPause() { 112 super.onPause(); 113 114 // NOTE: stop() can block for a few seconds, so it's generally 115 // recommended to run PsiphonTunnel.start()/stop() in a background 116 // thread and signal the thread appropriately. 117 118 mPsiphonTunnel.stop(); 119 } 120 121 private void setHttpProxyPort(int port) { 122 123 // NOTE: here we record the Psiphon proxy port for subsequent 124 // use in tunneling app traffic. In this sample app, we will 125 // use WebViewProxySettings.setLocalProxy to tunnel a WebView 126 // through Psiphon. By default, the local proxy port is selected 127 // dynamically, so it's important to record and use the correct 128 // port number. 129 130 mLocalHttpProxyPort.set(port); 131 } 132 133 private void loadWebView() { 134 135 // NOTE: functions called via PsiphonTunnel.HostService may be 136 // called on background threads. It's important to ensure that 137 // these threads are not blocked and that UI functions are not 138 // called directly from these threads. Here we use runOnUiThread 139 // to handle this. 140 141 runOnUiThread(new Runnable() { 142 public void run() { 143 WebViewProxySettings.setLocalProxy( 144 MainActivity.this, mLocalHttpProxyPort.get()); 145 mWebView.loadUrl("https://ipinfo.io/"); 146 } 147 }); 148 } 149 150 // ... 151 152 //---------------------------------------------------------------------------------------------- 153 // PsiphonTunnel.HostService implementation 154 // 155 // NOTE: these are callbacks from the Psiphon Library 156 //---------------------------------------------------------------------------------------------- 157 158 // ... 159 160 @Override 161 public void onListeningSocksProxyPort(int port) { 162 logMessage("local SOCKS proxy listening on port: " + Integer.toString(port)); 163 } 164 165 // ... 166 167 @Override 168 public void onConnected() { 169 logMessage("connected"); 170 loadWebView(); 171 } 172 173 // ... 174 175 } 176 177 ``` 178 179 ## License 180 181 See the [LICENSE](../LICENSE) file.