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.